Java-Klasse für dateFormatsType complex type.
- *
- * Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist.
- *
- * 0));
- }
-
- public void unsetDateFormat() {
- this.dateFormat = null;
- }
-
- /**
- * Ruft den Wert der default-Eigenschaft ab.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getDefault() {
- return _default;
- }
-
- /**
- * Legt den Wert der default-Eigenschaft fest.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setDefault(String value) {
- this._default = value;
- }
-
- public boolean isSetDefault() {
- return (this._default!= null);
- }
-
-}
diff --git a/base-lib/src/main/jaxb/com/gentics/lib/formatter/dateformatter/JAXBDateOrTimeType.java b/base-lib/src/main/jaxb/com/gentics/lib/formatter/dateformatter/JAXBDateOrTimeType.java
deleted file mode 100644
index c1fa5f5286..0000000000
--- a/base-lib/src/main/jaxb/com/gentics/lib/formatter/dateformatter/JAXBDateOrTimeType.java
+++ /dev/null
@@ -1,100 +0,0 @@
-
-package com.gentics.lib.formatter.dateformatter;
-
-import jakarta.xml.bind.annotation.XmlAccessType;
-import jakarta.xml.bind.annotation.XmlAccessorType;
-import jakarta.xml.bind.annotation.XmlAttribute;
-import jakarta.xml.bind.annotation.XmlSchemaType;
-import jakarta.xml.bind.annotation.XmlType;
-import jakarta.xml.bind.annotation.XmlValue;
-import jakarta.xml.bind.annotation.adapters.CollapsedStringAdapter;
-import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-
-
-/**
- * Java-Klasse für dateOrTimeType complex type.
- *
- * Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist.
- *
- * {@code
- *
- *
- *
- *
- *
- *
- *
- * }
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "dateOrTimeType", propOrder = {
- "value"
-})
-public class JAXBDateOrTimeType {
-
- @XmlValue
- protected String value;
- @XmlAttribute(name = "language", required = true)
- @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
- @XmlSchemaType(name = "token")
- protected String language;
-
- /**
- * Ruft den Wert der value-Eigenschaft ab.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getValue() {
- return value;
- }
-
- /**
- * Legt den Wert der value-Eigenschaft fest.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setValue(String value) {
- this.value = value;
- }
-
- public boolean isSetValue() {
- return (this.value!= null);
- }
-
- /**
- * Ruft den Wert der language-Eigenschaft ab.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getLanguage() {
- return language;
- }
-
- /**
- * Legt den Wert der language-Eigenschaft fest.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setLanguage(String value) {
- this.language = value;
- }
-
- public boolean isSetLanguage() {
- return (this.language!= null);
- }
-
-}
diff --git a/base-lib/src/main/jaxb/com/gentics/lib/formatter/dateformatter/ObjectFactory.java b/base-lib/src/main/jaxb/com/gentics/lib/formatter/dateformatter/ObjectFactory.java
deleted file mode 100644
index 890b5db6c3..0000000000
--- a/base-lib/src/main/jaxb/com/gentics/lib/formatter/dateformatter/ObjectFactory.java
+++ /dev/null
@@ -1,107 +0,0 @@
-
-package com.gentics.lib.formatter.dateformatter;
-
-import javax.xml.namespace.QName;
-import jakarta.xml.bind.JAXBElement;
-import jakarta.xml.bind.annotation.XmlElementDecl;
-import jakarta.xml.bind.annotation.XmlRegistry;
-
-
-/**
- * This object contains factory methods for each
- * Java content interface and Java element interface
- * generated in the com.gentics.lib.formatter.dateformatter package.
- * An ObjectFactory allows you to programmatically
- * construct new instances of the Java representation
- * for XML content. The Java representation of XML
- * content can consist of schema derived interfaces
- * and classes representing the binding of schema
- * type definitions, element declarations and model
- * groups. Factory methods for each of these are
- * provided in this class.
- *
- */
-@XmlRegistry
-public class ObjectFactory {
-
- private static final QName _DateFormats_QNAME = new QName("", "date-formats");
- private static final QName _JAXBDateFormatTypeDate_QNAME = new QName("", "date");
- private static final QName _JAXBDateFormatTypeTime_QNAME = new QName("", "time");
-
- /**
- * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.gentics.lib.formatter.dateformatter
- *
- */
- public ObjectFactory() {
- }
-
- /**
- * Create an instance of {@link JAXBDateFormatsType }
- *
- * @return
- * the new instance of {@link JAXBDateFormatsType }
- */
- public JAXBDateFormatsType createJAXBDateFormatsType() {
- return new JAXBDateFormatsType();
- }
-
- /**
- * Create an instance of {@link JAXBDateFormatType }
- *
- * @return
- * the new instance of {@link JAXBDateFormatType }
- */
- public JAXBDateFormatType createJAXBDateFormatType() {
- return new DateFormatConfig();
- }
-
- /**
- * Create an instance of {@link JAXBDateOrTimeType }
- *
- * @return
- * the new instance of {@link JAXBDateOrTimeType }
- */
- public JAXBDateOrTimeType createJAXBDateOrTimeType() {
- return new JAXBDateOrTimeType();
- }
-
- /**
- * Create an instance of {@link JAXBElement }{@code <}{@link JAXBDateFormatsType }{@code >}
- *
- * @param value
- * Java instance representing xml element's value.
- * @return
- * the new instance of {@link JAXBElement }{@code <}{@link JAXBDateFormatsType }{@code >}
- */
- @XmlElementDecl(namespace = "", name = "date-formats")
- public JAXBElement createDateFormats(JAXBDateFormatsType value) {
- return new JAXBElement<>(_DateFormats_QNAME, JAXBDateFormatsType.class, null, value);
- }
-
- /**
- * Create an instance of {@link JAXBElement }{@code <}{@link JAXBDateOrTimeType }{@code >}
- *
- * @param value
- * Java instance representing xml element's value.
- * @return
- * the new instance of {@link JAXBElement }{@code <}{@link JAXBDateOrTimeType }{@code >}
- */
- @XmlElementDecl(namespace = "", name = "date", scope = JAXBDateFormatType.class)
- public JAXBElement createJAXBDateFormatTypeDate(JAXBDateOrTimeType value) {
- return new JAXBElement<>(_JAXBDateFormatTypeDate_QNAME, JAXBDateOrTimeType.class, JAXBDateFormatType.class, value);
- }
-
- /**
- * Create an instance of {@link JAXBElement }{@code <}{@link JAXBDateOrTimeType }{@code >}
- *
- * @param value
- * Java instance representing xml element's value.
- * @return
- * the new instance of {@link JAXBElement }{@code <}{@link JAXBDateOrTimeType }{@code >}
- */
- @XmlElementDecl(namespace = "", name = "time", scope = JAXBDateFormatType.class)
- public JAXBElement createJAXBDateFormatTypeTime(JAXBDateOrTimeType value) {
- return new JAXBElement<>(_JAXBDateFormatTypeTime_QNAME, JAXBDateOrTimeType.class, JAXBDateFormatType.class, value);
- }
-
-}
diff --git a/base-lib/src/main/jaxb/date-formatPrime.xsd b/base-lib/src/main/jaxb/date-formatPrime.xsd
deleted file mode 100644
index a05ac26c0e..0000000000
--- a/base-lib/src/main/jaxb/date-formatPrime.xsd
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/base-lib/src/main/resources/com/gentics/portalnode/formatter/toolbox.xml b/base-lib/src/main/resources/com/gentics/portalnode/formatter/toolbox.xml
deleted file mode 100644
index 9a14ab7cbe..0000000000
--- a/base-lib/src/main/resources/com/gentics/portalnode/formatter/toolbox.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
- true
-
- version
- 1.1
-
-
- isSimple
- true
-
-
- foo
- this is foo.
-
-
- bar
- this is bar.
-
-
- map
- session
- java.util.HashMap
-
-
- date
- application
- org.apache.velocity.tools.generic.DateTool
-
-
-
-
-
-
- math
- application
- org.apache.velocity.tools.generic.MathTool
-
-
- number
- application
- org.apache.velocity.tools.generic.NumberTool
-
-
- render
- application
- org.apache.velocity.tools.generic.RenderTool
-
-
- esc
- application
- org.apache.velocity.tools.generic.EscapeTool
-
-
- alternator
- application
- org.apache.velocity.tools.generic.AlternatorTool
-
-
- parser
- org.apache.velocity.tools.generic.ValueParser
-
-
- list
- application
- org.apache.velocity.tools.generic.ListTool
-
-
- sort
- org.apache.velocity.tools.generic.SortTool
-
-
- iterator
- request
- org.apache.velocity.tools.generic.IteratorTool
-
-
diff --git a/base-lib/src/test/java/com/gentics/lib/formatter/GenticsDateFormatterTest.java b/base-lib/src/test/java/com/gentics/lib/formatter/GenticsDateFormatterTest.java
deleted file mode 100644
index 2cceba0dfd..0000000000
--- a/base-lib/src/test/java/com/gentics/lib/formatter/GenticsDateFormatterTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package com.gentics.lib.formatter;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import com.gentics.api.portalnode.imp.ImpException;
-import com.gentics.contentnode.tests.category.BaseLibTest;
-import com.gentics.lib.jaxb.JAXBHelper;
-
-import jakarta.xml.bind.JAXBException;
-
-@Category(BaseLibTest.class)
-public class GenticsDateFormatterTest {
-
- private static GenericGenticsDateFormatter formatter;
- private final static String IMP_NAME = "bogus";
- private final static String DATE_FORMAT = "dd MMM yyyy HH:mm:ss";
- private final static String DATE_RESULT = "01 Jan 1970 01:00:00";
- private final static long FIXED_DATE_IN_2014 = 1397478595585L;
-
- @BeforeClass
- public static void setupOnce() throws JAXBException, ImpException {
- JAXBHelper.init(null);
- formatter = new GenericGenticsDateFormatter();
- Map settings = new HashMap();
-
- String confPath = GenticsDateFormatterTest.class.getResource("dateformatter.xml").getFile();
- settings.put(GenericGenticsDateFormatter.CONFIGPATH_PARAM, confPath);
-
- formatter.init(IMP_NAME, settings);
-
- }
-
- @Test
- public void testInvalidFormat() {
- String dateString = formatter.format(new Integer(2));
- assertNull(dateString);
- }
-
- @Test
- @Ignore("Test unstable due to local settings")
- public void simpleFormatterTest() throws ImpException, JAXBException {
- assertNotNull(formatter.format());
- String dateResult = "Thu Jan 01 01:00:00 CET 1970";
- assertEquals("The result should match the expected format", dateResult, formatter.format(new Date(3)));
- assertEquals("The result should match the expected format", dateResult, formatter.format((Object) new Date(3)));
- assertNotNull(formatter.format(DATE_FORMAT));
-
- assertEquals("The result should match the expected format", DATE_RESULT, formatter.format((Object) new Date(1), DATE_FORMAT));
- assertNotNull(formatter.format(DATE_FORMAT, "DE"));
- assertEquals("The result should match the expected format", DATE_RESULT, formatter.format(new Date(1), DATE_FORMAT, "DE"));
- assertEquals("The result should match the expected format", DATE_RESULT, formatter.format((Object) new Date(1), DATE_FORMAT, "DE"));
- }
-
- @Test
- @Ignore("Test unstable due to local settings")
- public void testFormatDate() {
- assertNotNull(formatter.formatDate());
- String date = "Thu Jan 01 01:00:00 CET 1970";
- assertEquals("The dates should match.", date, formatter.formatDate(new Date(1)));
- String input = "1.1.2014 12:30";
- assertEquals("Input should match the output.", input, formatter.formatDate(input));
-
- assertEquals("The dates should match.", DATE_RESULT, formatter.formatDate(new Date(1), DATE_FORMAT));
- assertEquals("The dates should match.", DATE_RESULT, formatter.formatDate((Object) new Date(1), DATE_FORMAT));
- assertNotNull(formatter.formatDate(DATE_FORMAT, "EN"));
- assertEquals("The dates should match.", DATE_RESULT, formatter.formatDate(new Date(1), DATE_FORMAT, "EN"));
- assertEquals("The dates should match.", DATE_RESULT, formatter.formatDate((Object) new Date(1), DATE_FORMAT, "EN"));
- }
-
- @Test
- public void testFromTimestamp() {
- Date date = formatter.fromTimestamp(1000);
- assertEquals("Both dates should match", new Date(1000 * 1000).getTime(), date.getTime());
- date = formatter.fromTimestamp("1000");
- assertEquals("Both dates should match", new Date(1000 * 1000).getTime(), date.getTime());
- }
-
- @Test
- public void testParseDate() {
- String inputDate = "2014-03-12 12:30";
- Date date = formatter.parse(null);
- assertNull(date);
- date = formatter.parseDate(inputDate, DATE_FORMAT, "EN");
- assertNull(date);
- date = formatter.parse(inputDate, DATE_FORMAT, "DE");
- assertNull(date);
- }
-
- @Test
- public void testDateDiff() {
-
- GenericGenticsDateFormatter formatter = new GenericGenticsDateFormatter();
- long diff = formatter.dateDiff(new Date(0), new Date(1));
- assertEquals("Diff does not match", 1, diff);
- diff = formatter.dateDiff((Object) new Date(1), (Object) new Date(2));
- assertEquals("diff does not match", 1, diff);
-
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "y");
- assertEquals("Years since 1970 do not match", 44, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "M");
- assertEquals("Months since 1970 do not match", 531, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "w");
- assertEquals("Weeks since 1970 do not match", 2310, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "d");
- assertEquals("Days since 1970 do not match", 16174, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "h");
- assertEquals("Hours since 1970 do not match", 388188, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "m");
- assertEquals("Minutes since 1970 do not match", 23291309, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "s");
- assertEquals("Seconds since 1970 do not match", 1397478595, diff);
- diff = formatter.dateDiff((Object) new Date(0), (Object) new Date(FIXED_DATE_IN_2014), "M");
- assertEquals("Months since 1970 do not match.", 531, diff);
- diff = formatter.dateDiff((Object) new Date(0), (Object) new Date(FIXED_DATE_IN_2014), "y");
- assertEquals("44 Years have past since 1970.", 44, diff);
- }
-
- @Test
- public void testMisc() {
- assertEquals("The impname should match the name we choose during init.", IMP_NAME, formatter.getImpId());
-
- TimeZone tz = TimeZone.getTimeZone("Europe/Vienna");
- int offset = (int) ((Calendar.getInstance().get(Calendar.ZONE_OFFSET) + Calendar.getInstance().get(Calendar.DST_OFFSET)) / 60 / 60 / 1000);
-
- assertEquals("+0" + offset + ":00", formatter.getRfc3339Timezone());
- assertEquals("+0" + offset + ":00", formatter.getRfc3339Timezone(new Date()));
-
- assertFalse("The given object is not a date object", formatter.isDate("1.1.2014"));
- assertTrue("The given object is a date", formatter.isDate(new Date(1)));
- assertFalse("The given object is not a date", formatter.isDate(new Integer(1)));
- }
-
- @Test
- public void testCustomFormat() {
- Date now = new Date();
- new SimpleDateFormat("dd", Locale.forLanguageTag("en"));
-
- assertThat(formatter.format(now, "custom", "en"))
- .describedAs("Date formatter with customer formatter in en")
- .isEqualTo(new SimpleDateFormat("dd", Locale.forLanguageTag("en")).format(now) + " "
- + new SimpleDateFormat("hh", Locale.forLanguageTag("en")).format(now));
- assertThat(formatter.format(now, "custom", "de")).describedAs("Date formatter with customer formatter in de")
- .isEqualTo(new SimpleDateFormat("MM", Locale.forLanguageTag("de")).format(now) + " "
- + new SimpleDateFormat("ss", Locale.forLanguageTag("de")).format(now));
- }
-}
diff --git a/base-lib/src/test/java/com/gentics/node/tests/formatter/BlockingHttpConnectionHandler.java b/base-lib/src/test/java/com/gentics/node/tests/formatter/BlockingHttpConnectionHandler.java
deleted file mode 100644
index 97295ac9df..0000000000
--- a/base-lib/src/test/java/com/gentics/node/tests/formatter/BlockingHttpConnectionHandler.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.gentics.node.tests.formatter;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.Socket;
-import java.util.Scanner;
-
-import com.gentics.testutils.http.IHttpServerConnectionHandler;
-
-public class BlockingHttpConnectionHandler implements IHttpServerConnectionHandler {
-
- private long nMilisecondsToWait = 0;
-
- /**
- * Create a new blocking http connection handler that will block the connection for the given amount of time.
- *
- * @param nMilisecondsToWait
- */
- public BlockingHttpConnectionHandler(long nMilisecondsToWait) {
- this.nMilisecondsToWait = nMilisecondsToWait;
- }
-
- /**
- * Set the amount of miliseconds which the connection should be stalled
- *
- * @param time
- */
- public void setBlockingTime(long nMilisecondsToWait) {
- this.nMilisecondsToWait = nMilisecondsToWait;
- }
-
- public void handleConnection(Socket client) throws IOException {
-
- InputStream ins = client.getInputStream();
- OutputStream out = client.getOutputStream();
-
- System.out.println("Handling Connection - Starting Block");
- try {
- Thread.sleep(nMilisecondsToWait);
- } catch (InterruptedException e) {
-
- e.printStackTrace();
- }
- System.out.println("Handling Connection - Blocking finished");
-
- Scanner in = new Scanner(ins);
- PrintWriter output = new PrintWriter(out, true);
-
- String cmd = in.nextLine();
-
- output.println("HTTP/1.0 200 OK");
- output.println("");
- output.println("Here you go: " + cmd);
-
- out.close();
- ins.close();
- }
-
-}
-
diff --git a/base-lib/src/test/java/com/gentics/node/tests/formatter/UrlIncludeImpTest.java b/base-lib/src/test/java/com/gentics/node/tests/formatter/UrlIncludeImpTest.java
deleted file mode 100644
index 10925838d3..0000000000
--- a/base-lib/src/test/java/com/gentics/node/tests/formatter/UrlIncludeImpTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.gentics.node.tests.formatter;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-
-import com.gentics.contentnode.tests.category.BaseLibTest;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.portalnode.formatter.URLIncludeImp;
-import com.gentics.testutils.http.HttpServer;
-import org.junit.experimental.categories.Category;
-
-@Category(BaseLibTest.class)
-public class UrlIncludeImpTest {
-
- public final static int HTTPPORT = 0;
- public final static long BLOCKTIME = 8000;
- public HttpServer server;
- public BlockingHttpConnectionHandler handler;
- public int cacheLifeTime = 20;
- public String defaultContent = "This is the default content";
- String url = "";
-
- @Before
- public void setup() throws IOException {
-
- server = new HttpServer(HTTPPORT);
- handler = new BlockingHttpConnectionHandler(1000);
- server.setConnectionHandler(handler);
- new Thread(server).start();
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- url = getServerURL();
- }
-
- @After
- public void tearDown() throws IOException {
- server.stop();
- }
-
- @Test
- public void testIncludeImpTimeout() throws NodeException {
-
- URLIncludeImp urlImp = new URLIncludeImp();
-
- int soTimeout = 200;
-
- String output = urlImp.includeUrl(url, cacheLifeTime, soTimeout, defaultContent);
-
- assertEquals("We expected the default content since the connection should have been failed.", defaultContent, output);
-
- // Wait some more time to give the blocking http connection handler time to finish
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- public String getServerURL() {
- System.out.println("Selected ServerPort:" + server.getPort());
- String url = "http://localhost:" + server.getPort();
-
- return url;
- }
-
- @Test
- public void testIncludeImpMultithreading() throws NodeException {
-
- final URLIncludeImp urlImp = new URLIncludeImp();
-
- final int soTimeout = 200;
-
- for (int i = 0; i < 2000; i++) {
- System.out.println("Starting thread: " + i);
-
- if (i % 5 == 0) {
- System.out.println("Waiting");
- // Wait some more time to give the blocking http connection handler time to finish
- try {
- Thread.sleep(5);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- new Thread(new Runnable() {
-
- public void run() {
- try {
- String output = urlImp.includeUrl(url, cacheLifeTime, soTimeout, defaultContent);
-
- System.out.println(output);
- } catch (NodeException e) {
- e.printStackTrace();
- }
- }
- }).start();
-
- }
-
- }
-
- /**
- * Test the url imp include with a higher socket timeout value.
- *
- * @throws NodeException
- */
- @Test
- public void testIncludeImpTimeout2() throws NodeException {
-
- URLIncludeImp urlImp = new URLIncludeImp();
- int soTimeout = 30000;
-
- handler.setBlockingTime(0);
- url += "?blaa";
- String output = urlImp.includeUrl(url, cacheLifeTime, soTimeout, defaultContent);
-
- assertEquals("We expected the acctual server response since the connection should be fine.", "Here you go: GET /?blaa HTTP/1.1\n", output);
- System.out.println(output);
-
- // Wait some more time to give the blocking http connection handler time to finish
- try {
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-}
diff --git a/base-lib/src/test/resources/com/gentics/lib/formatter/dateformatter.xml b/base-lib/src/test/resources/com/gentics/lib/formatter/dateformatter.xml
deleted file mode 100644
index e7572d2950..0000000000
--- a/base-lib/src/test/resources/com/gentics/lib/formatter/dateformatter.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
- dd
- hh
- MM
- ss
-
-
diff --git a/cms-core/src/main/java/com/gentics/contentnode/factory/PartTypeFactory.java b/cms-core/src/main/java/com/gentics/contentnode/factory/PartTypeFactory.java
index a1f25b599d..152afab4ae 100644
--- a/cms-core/src/main/java/com/gentics/contentnode/factory/PartTypeFactory.java
+++ b/cms-core/src/main/java/com/gentics/contentnode/factory/PartTypeFactory.java
@@ -9,6 +9,8 @@
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.gentics.api.contentnode.parttype.ExtensiblePartType;
@@ -18,6 +20,7 @@
import com.gentics.contentnode.object.Value;
import com.gentics.contentnode.object.parttype.ExtensiblePartTypeWrapper;
import com.gentics.contentnode.object.parttype.PartType;
+import com.gentics.contentnode.object.parttype.UnavailablePartType;
import com.gentics.lib.etc.StringUtils;
/**
@@ -25,6 +28,15 @@
* parttype-id.
*/
public class PartTypeFactory {
+ /**
+ * Type IDs of optional part types (33: VelocityPartType, 34: BreadcrumbPartType, 35: NavigationPartType)
+ */
+ protected final static Set OPTIONAL_TYPE_IDS = Set.of(33, 34, 35);
+
+ /**
+ * Type IDs of optional part types, which are valueless
+ */
+ protected final static Set OPTIONAL_VALUELESS_IDS = Set.of(33, 34, 35);
private static PartTypeFactory factory;
@@ -66,6 +78,10 @@ public boolean isValueless(int typeId) throws NodeException {
public boolean isValueless(int typeId, boolean failIfPartTypeNotFound) throws NodeException {
PartTypeInfo partTypeInfo = getPartTypeInfo(typeId, failIfPartTypeNotFound);
+ if (OPTIONAL_VALUELESS_IDS.contains(typeId)) {
+ return true;
+ }
+
// check if classname is set
if (null == partTypeInfo) {
return true;
@@ -113,9 +129,10 @@ private PartTypeInfo getPartTypeInfo(int partTypeId, boolean failIfNotFound) thr
res = p.executeQuery();
if (res.next()) {
- Class partTypeClass = null;
+ Class> partTypeClass = null;
String partTypeClassName = res.getString("javaclass");
String partTypeName = res.getString("name");
+ String originalClassName = null;
res.close();
@@ -127,10 +144,15 @@ private PartTypeInfo getPartTypeInfo(int partTypeId, boolean failIfNotFound) thr
try {
partTypeClass = Class.forName(partTypeClassName);
} catch (ClassNotFoundException e) {
- throw new NodeException("No class for partType " + partTypeId, e);
+ if (OPTIONAL_TYPE_IDS.contains(partTypeId)) {
+ partTypeClass = UnavailablePartType.class;
+ originalClassName = partTypeClassName;
+ } else {
+ throw new NodeException("No class for partType " + partTypeId, e);
+ }
}
- partTypeInfo = new PartTypeInfo(partTypeClass, partTypeName);
+ partTypeInfo = new PartTypeInfo(partTypeClass, partTypeName, originalClassName);
partTypeInfoCache.put(partTypeId, partTypeInfo);
return partTypeInfo;
} else {
@@ -184,6 +206,13 @@ public PartType getPartType(int typeId, Value value) throws NodeException {
if (!PartType.class.isAssignableFrom(partTypeInfo.getClazz())) {// TODO error handling
}
+ // special handling for UnavailablePartType
+ if (partTypeInfo.getClazz() == UnavailablePartType.class) {
+ PartType partType = new UnavailablePartType(value, partTypeInfo.getOriginalClassName());
+ partType.setAnnotationClass(partTypeInfo.getAnnotationClass());
+ return partType;
+ }
+
try {
// get the desired constructor
Constructor constructor = partTypeInfo.getClazz().getConstructor(new Class[] { Value.class});
@@ -221,6 +250,16 @@ public boolean matches(Part part, PartType partType) throws NodeException {
}
}
+ /**
+ * Check whether the part type with given ID is available
+ * @param typeId type ID
+ * @return true iff available
+ * @throws NodeException
+ */
+ public boolean isAvailable(int typeId) throws NodeException {
+ return Optional.ofNullable(getPartTypeInfo(typeId, false)).map(PartTypeInfo::isAvailable).orElse(false);
+ }
+
/**
* Class for parttype info (class and annotation name)
*/
@@ -236,14 +275,21 @@ protected class PartTypeInfo {
*/
protected String annotationClass;
+ /**
+ * If the {@link #clazz} is {@link UnavailablePartType}, this string specifies the original class name (which is unavailable)
+ */
+ protected String originalClassName;
+
/**
* Create an instance
* @param clazz class
* @param name name (will be transformed to the annotation class)
+ * @param originalClassName optional original class name
*/
- public PartTypeInfo(Class> clazz, String name) {
+ public PartTypeInfo(Class> clazz, String name, String originalClassName) {
this.clazz = clazz;
this.annotationClass = buildAnnotationClass(name);
+ this.originalClassName = originalClassName;
}
/**
@@ -273,5 +319,21 @@ public Class> getClazz() {
public String getAnnotationClass() {
return annotationClass;
}
+
+ /**
+ * Get the original class name
+ * @return original class name
+ */
+ public String getOriginalClassName() {
+ return originalClassName;
+ }
+
+ /**
+ * Check whether the part type is available
+ * @return true iff available
+ */
+ public boolean isAvailable() {
+ return !clazz.isAssignableFrom(UnavailablePartType.class);
+ }
}
}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/formatter/CNDateFormatterImp.java b/cms-core/src/main/java/com/gentics/contentnode/formatter/CNDateFormatterImp.java
deleted file mode 100644
index d898d0ec70..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/formatter/CNDateFormatterImp.java
+++ /dev/null
@@ -1,516 +0,0 @@
-package com.gentics.contentnode.formatter;
-
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Map;
-
-import com.gentics.api.portalnode.imp.AbstractGenticsImp;
-import com.gentics.api.portalnode.imp.ImpException;
-import com.gentics.contentnode.etc.ContentNodeDate;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.render.RenderableResolvable;
-import com.gentics.contentnode.resolving.StackResolvable;
-import com.gentics.lib.formatter.dateformatter.DateFormatConfig;
-
-/**
- * New and better Version if the GenticsDateFormatter. Can be used to format
- * dates in Portal.Node and Content.Node
- */
-public class CNDateFormatterImp extends AbstractGenticsImp {
-
- /**
- * some basic definitions needed for calculations
- */
- public static final int MINUTE = 60;
-
- public static final int HOUR = 60 * MINUTE;
-
- public static final int DAY = 24 * HOUR;
-
- public static final int WEEK = 7 * DAY;
-
- public static final int MONTH = 30 * DAY;
-
- public static final int YEAR = 365 * DAY;
-
- /**
- *
- */
- public CNDateFormatterImp() {
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.gentics.api.portalnode.imp.AbstractGenticsImp#init(java.lang.String,
- * java.util.Map)
- */
- public void init(String impId, Map parameters) throws ImpException {
- super.init(impId, parameters);
- }
-
- /**
- * Format the current date in the given format and the current language
- *
- * @param format
- * format
- * @return formatted date
- */
- public String format(String format) {
- return format(new Date(), format, getCurrentLanguageCode());
- }
-
- /**
- * @param format
- * @deprecated use {@link #format(String)} instead
- * @return
- */
- public String formatDate(String format) {
- return format(format);
- }
-
- /**
- * Format the current date in the given format and language
- *
- * @param format
- * format
- * @param languageCode
- * language code
- * @return formatted date
- */
- public String format(String format, String languageCode) {
- return format(new Date(), format, languageCode);
- }
-
- /**
- * @param format
- * @param languageCode
- * @deprecated use {@link #format(String, String)} instead
- * @return
- */
- public String formatDate(String format, String languageCode) {
- return format(format, languageCode);
- }
-
- /**
- * Format the given date in the given format and current language
- *
- * @param date
- * date
- * @param format
- * format
- * @return formatted date
- */
- public String format(Date date, String format) {
- return format(date, format, getCurrentLanguageCode());
- }
-
- /**
- *
- * @param date
- * @param format
- * @deprecated use {@link #format(Date, String)} instead
- * @return
- */
- public String formatDate(Date date, String format) {
- return format(date, format);
- }
-
- /**
- * Format the given date in the given format and language
- *
- * @param date
- * date
- * @param format
- * format
- * @param languageCode
- * language
- * @return formatted date
- */
- public String format(Date date, String format, String languageCode) {
- DateFormat dateFormat = DateFormatConfig.createDateTimeFormat(format, DateFormatConfig.getLocale(languageCode));
- return dateFormat.format(date);
- }
-
- /**
- * @param date
- * @param format
- * @param languageCode
- * @deprecated use {@link #format(Date, String, String)} instead
- * @return
- */
- public String formatDate(Date date, String format, String languageCode) {
- return format(date, format, languageCode);
- }
-
- /**
- * Format the given date in the given format and current language
- *
- * @param date
- * date
- * @param format
- * format
- * @return formatted date
- */
- public String format(Object date, String format) {
- return format(toDate(date), format);
- }
-
- /**
- *
- * @param date
- * @param format
- * @deprecated use {@link #format(Object, String)} instead
- * @return
- */
- public String formatDate(Object date, String format) {
- return format(date, format);
- }
-
- /**
- * Format the given date in the given format and language
- *
- * @param date
- * date
- * @param format
- * format
- * @param languageCode
- * language
- * @return formatted date
- */
- public String format(Object date, String format, String languageCode) {
- return format(toDate(date), format, languageCode);
- }
-
- /**
- *
- * @param date
- * @param format
- * @param languageCode
- * @deprecated use {@link #format(Object, String, String)} instead
- * @return
- */
- public String formatDate(Object date, String format, String languageCode) {
- return format(date, format, languageCode);
- }
-
- /**
- * parse the given string to a date (in the default format) and return the
- * date or null if the string is not parsable
- *
- * @param formattedDate
- * formatted date to be parsed
- * @return date object or null
- */
- public Date parse(String formattedDate) {
- return parse(formattedDate, null);
- }
-
- /**
- *
- * @param formattedDate
- * @deprecated use {@link #parse(String)} instead
- * @return
- */
- public Date parseDate(String formattedDate) {
- return parse(formattedDate);
- }
-
- /**
- * parse the given string to a date in the given format and return the date
- * or null if the string is unparseable
- *
- * @param formattedDate
- * formatted date to be parsed
- * @param dateFormat
- * date format or null for the default format
- * @return date object or null
- */
- public Date parse(String formattedDate, String dateFormat) {
- return parse(formattedDate, dateFormat, getCurrentLanguageCode());
- }
-
- /**
- *
- * @param formattedDate
- * @param dateFormat
- * @deprecated use {@link #parse(String, String))} instead
- * @return
- */
- public Date parseDate(String formattedDate, String dateFormat) {
- return parse(formattedDate, dateFormat);
- }
-
- /**
- * Parse the given string to a date in the given format and given
- * languagecode
- *
- * @param formattedDate
- * formatted date to be parsed
- * @param format
- * date format or null for the default format
- * @param languageCode
- * language code
- * @return date object or null
- */
- public Date parse(String formattedDate, String format, String languageCode) {
-
- try {
- DateFormat dateFormat = DateFormatConfig.createDateTimeFormat(format, DateFormatConfig.getLocale(languageCode));
- return dateFormat.parse(formattedDate);
- } catch (ParseException e) {
- logger.error("Error while parsing {" + formattedDate + "} into a date with format {" + format + "}", e);
- return null;
- }
- }
-
- /**
- *
- * @param formattedDate
- * @param format
- * @param languageCode
- * @deprecated use {@link #parse(String, String, String)} instead
- * @return
- */
- public Date parseDate(String formattedDate, String format, String languageCode) {
- return parse(formattedDate, format, languageCode);
- }
-
- /**
- * generate a date from a timestamp
- *
- * @param timestamp
- * timestamp
- * @return date object
- */
- public Date fromTimestamp(int timestamp) {
- return new Date((long) timestamp * 1000L);
- }
-
- /**
- * generate a date from a timestamp
- *
- * @param timestamp
- * timestamp (as string)
- * @return date object
- */
- public Date fromTimestamp(String timestamp) {
- try {
- return new Date(Long.parseLong(timestamp) * 1000L);
- } catch (NumberFormatException ex) {
- return null;
- }
- }
-
- /**
- * check whether the object is a date or not
- *
- * @param object
- * object to check
- * @return true when the object is a date, false if not
- */
- public boolean isDate(Object object) {
- return object instanceof Date;
- }
-
- /**
- * Calculate the difference between the given dates in the given time unit.
- * Possible time units are:
- *
- * y for years
- * M for months
- * w for weeks
- * d for days
- * h for hours
- * m for minutes
- * s for seconds
- * ms for milliseconds (the default)
- *
- *
- * @param fromDate
- * first date (should be earlier)
- * @param toDate
- * second date (should be later)
- * @param unit
- * the time unit for output of the date difference
- * @return difference in the given unit
- */
- public long dateDiff(Date fromDate, Date toDate, String unit) {
- long msDiff = toDate.getTime() - fromDate.getTime();
- long diff = msDiff;
-
- if ("y".equals(unit)) {
- // difference in years
- Calendar toCal = Calendar.getInstance();
-
- toCal.setTime(toDate);
- Calendar fromCal = Calendar.getInstance();
-
- fromCal.setTime(fromDate);
- diff = toCal.get(Calendar.YEAR) - fromCal.get(Calendar.YEAR);
- // now check whether the to-day is earlier in the year as the
- // from-day
- toCal.set(Calendar.YEAR, fromCal.get(Calendar.YEAR));
- if (toCal.getTime().before(fromCal.getTime())) {
- diff -= 1;
- }
- } else if ("M".equals(unit)) {
- // difference in months
- Calendar toCal = Calendar.getInstance();
-
- toCal.setTime(toDate);
- Calendar fromCal = Calendar.getInstance();
-
- fromCal.setTime(fromDate);
- diff = (toCal.get(Calendar.YEAR) - fromCal.get(Calendar.YEAR)) * 12;
- // now check whether the to-day is earlier in the year as the
- // from-day
- toCal.set(Calendar.YEAR, fromCal.get(Calendar.YEAR));
- diff += (toCal.get(Calendar.MONTH) - fromCal.get(Calendar.MONTH));
- toCal.set(Calendar.MONTH, fromCal.get(Calendar.MONTH));
- if (toCal.getTime().before(fromCal.getTime())) {
- diff -= 1;
- }
- } else if ("w".equals(unit)) {
- // difference in weeks
- diff = msDiff / (7 * 24 * 60 * 60 * 1000);
- } else if ("d".equals(unit)) {
- // difference in days
- diff = msDiff / (24 * 60 * 60 * 1000);
- } else if ("h".equals(unit)) {
- // difference in hours
- diff = msDiff / (60 * 60 * 1000);
- } else if ("m".equals(unit)) {
- // difference in minutes
- diff = msDiff / (60 * 1000);
- } else if ("s".equals(unit)) {
- // difference in seconds
- diff = msDiff / 1000;
- }
- return diff;
- }
-
- /**
- * Other version of the {@link #dateDiff(Date, Date, String)} Method
- *
- * @param fromDate
- * first date
- * @param toDate
- * second date
- * @param unit
- * the time unit for output of the date difference
- * @return difference in the given unit
- */
- public long dateDiff(Object fromDate, Object toDate, String unit) {
- return dateDiff(toDate(fromDate), toDate(toDate), unit);
- }
-
- /**
- * Calculate the difference between the given dates in milliseconds.
- *
- * @param fromDate
- * first date (should be earlier)
- * @param toDate
- * second date (should be later)
- * @return difference in milliseconds
- */
- public long dateDiff(Date fromDate, Date toDate) {
- return dateDiff(fromDate, toDate, "ms");
- }
-
- /**
- * Other version of the {@link #dateDiff(Date, Date)} Method
- *
- * @param fromDate
- * first date (should be earlier)
- * @param toDate
- * second date (should be later)
- * @return difference in milliseconds
- */
- public long dateDiff(Object fromDate, Object toDate) {
- return dateDiff(toDate(fromDate), toDate(toDate));
- }
-
- /**
- * Transform the ContentNodeDate to a Date
- *
- * @param date
- * ContentNodeDate
- * @return Date
- */
- protected static Date toDate(Object date) {
- if (date == null) {
- return null;
- }
-
- // unwrap the object (if wrapped)
- if (date instanceof RenderableResolvable) {
- date = ((RenderableResolvable) date).getWrappedObject();
- }
-
- if (date instanceof Date) {
- return (Date) date;
- } else if (date instanceof ContentNodeDate) {
- return new Date(((ContentNodeDate) date).getTimestamp().longValue() * 1000L);
- } else if (date instanceof Integer) {
- return new Date((Integer) date);
- } else {
- return null;
- }
- }
-
- /**
- * Get the current language code or null
- *
- * @return current language code or null
- */
- protected String getCurrentLanguageCode() {
-
- // try to get the currently rendered page (if any)
- try {
- Transaction t = TransactionManager.getCurrentTransaction();
- StackResolvable rootObject = t.getRenderType().getRenderedRootObject();
- if (rootObject instanceof Page) {
- return ((Page) rootObject).getLanguage().getCode();
- }
- } catch (Exception e) {// hmm, silently ignore these exceptions?
- }
- return null;
- }
-
- /**
- * Get the timezone of the current date in RFC3339 format. See RFC 3339 for details.
- *
- * @return timezone of the current time in RFC3339 format.
- */
- public String getRfc3339Timezone() {
-
- Date date = new Date();
-
- return getRfc3339Timezone(date);
- }
-
- /**
- * Get the timezone of the given date in RFC3339 format. See RFC 3339 for details.
- *
- * @param date
- * date
- * @return timezone of the given date in RFC3339 format.
- */
- public String getRfc3339Timezone(Object date) {
- Date foo = toDate(date);
- SimpleDateFormat format = new SimpleDateFormat("Z");
- String rfc3339tz = format.format(foo).substring(0, 3) + ":" + format.format(foo).substring(3);
-
- return rfc3339tz;
- }
-
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/logger/VelocityLogSystem.java b/cms-core/src/main/java/com/gentics/contentnode/logger/VelocityLogSystem.java
deleted file mode 100644
index 26b8549afe..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/logger/VelocityLogSystem.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * @author herbert
- * @date Mar 20, 2008
- * @version $Id: VelocityLogSystem.java,v 1.3 2010-09-28 17:01:30 norbert Exp $
- */
-package com.gentics.contentnode.logger;
-
-import org.apache.velocity.runtime.RuntimeServices;
-import org.apache.velocity.runtime.log.LogSystem;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionException;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.render.RenderResult;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.contentnode.resolving.StackResolver;
-import com.gentics.lib.log.NodeLogger;
-
-public class VelocityLogSystem implements LogSystem {
-
- NodeLogger logger = NodeLogger.getNodeLogger(VelocityLogSystem.class);
-
- public void init(RuntimeServices rs) throws Exception {
- // TODO Auto-generated method stub
- // runtime.log.logsystem.class
- logger.info("Initializing custom velocity log system.");
- }
-
- /**
- * trys to log the given message into the render result
- * (so users can see them in the debug stream in the CMS.
- * if we are not in a render phase, this method returns false
- * and will not log anything.)
- */
- private boolean internalLogRenderResult(int level, String message) {
- try {
- Transaction t = TransactionManager.getCurrentTransaction();
-
- if (t == null) {
- return false;
- }
-
- RenderType renderType = t.getRenderType();
-
- String postfix = null;
-
- if (renderType != null) {
- StackResolver stack = renderType.getStack();
-
- postfix = stack.getUIReadableStack();
- }
-
- RenderResult result = t.getRenderResult();
-
- if (result == null) {
- return false;
- }
-
- if (postfix != null) {
- message = new StringBuffer("Velocity " + logLevelToString(level) + " while rendering: ").append(postfix).append(" --- ").append(message).toString();
- }
-
- switch (level) {
- case LogSystem.WARN_ID:
- result.warn(VelocityLogSystem.class, message);
- break;
-
- case LogSystem.INFO_ID:
- result.info(VelocityLogSystem.class, message);
- break;
-
- case LogSystem.DEBUG_ID:
- result.debug(VelocityLogSystem.class, message);
- break;
-
- case LogSystem.ERROR_ID:
- result.error(VelocityLogSystem.class, message);
- break;
-
- default:
- result.debug(VelocityLogSystem.class, message);
- break;
- }
- } catch (TransactionException e) {
- return false;
- } catch (NodeException e) {
- logger.debug("Error while trying to log message into render result.", e);
- return false;
- }
- return true;
- }
-
- private String logLevelToString(int level) {
- switch (level) {
- case LogSystem.WARN_ID:
- return "warning";
-
- case LogSystem.INFO_ID:
- return "info";
-
- case LogSystem.DEBUG_ID:
- return "debug";
-
- case LogSystem.ERROR_ID:
- return "error";
-
- default:
- return "unknown";
- }
- }
-
- public void logVelocityMessage(int level, String message) {
- // first try to log into the render result ..
- if (!internalLogRenderResult(level, message)) {
- switch (level) {
- case LogSystem.WARN_ID:
- logger.warn(message);
- break;
-
- case LogSystem.INFO_ID:
- logger.info(message);
- break;
-
- case LogSystem.DEBUG_ID:
- logger.debug(message);
- break;
-
- case LogSystem.ERROR_ID:
- logger.error(message);
- break;
-
- default:
- logger.debug(message);
- break;
- }
- }
- }
-
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/AbstractVelocityCompatibilityPartType.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/AbstractVelocityCompatibilityPartType.java
deleted file mode 100644
index 9cf5256925..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/AbstractVelocityCompatibilityPartType.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * @author alexander
- * @date 12.04.2007
- * @version $Id: AbstractVelocityCompatibilityPartType.java,v 1.1 2007-04-12 15:18:28 alexander Exp $
- */
-package com.gentics.contentnode.object.parttype;
-
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * Abstract base class for all compatibility part types
- */
-public abstract class AbstractVelocityCompatibilityPartType extends AbstractVelocityPartType {
-
- /**
- * Read all text and cdata sections of node and append
- *
- * @param node The node from which to extract all text and cdata nodes
- * @return The extracted template.
- */
- protected static String getTemplateFromNode(Node node) {
-
- StringBuffer text = new StringBuffer();
-
- // read children (text and cdata nodes) and aggregate
- if (node.hasChildNodes()) {
- NodeList children = node.getChildNodes();
-
- for (int k = 0; k < children.getLength(); k++) {
- Node item = children.item(k);
-
- if (item.getNodeType() == Node.CDATA_SECTION_NODE || item.getNodeType() == Node.TEXT_NODE) {
- text.append(item.getNodeValue());
- }
- }
- }
-
- return text.toString();
- }
-
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/AbstractVelocityPartType.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/AbstractVelocityPartType.java
deleted file mode 100644
index fa0b78f98f..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/AbstractVelocityPartType.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * @author alexander
- * @date 11.04.2007
- * @version $Id: AbstractVelocityPartType.java,v 1.6 2010-11-16 12:46:24 norbert Exp $
- */
-package com.gentics.contentnode.object.parttype;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.velocity.Template;
-import org.apache.velocity.app.Velocity;
-import org.apache.velocity.context.Context;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
-import org.apache.velocity.runtime.resource.util.StringResourceRepository;
-
-import com.gentics.api.contentnode.parttype.AbstractExtensiblePartType;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.object.Tag;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.lib.etc.StringUtils;
-import com.gentics.lib.log.NodeLogger;
-import com.gentics.lib.render.velocity.SerializableVelocityTemplateWrapper;
-
-/**
- * Abstract navigation parttype providing common methods for all navigation
- * parttypes and velocity parttype. Class could be separated into two classes,
- * one for all navigation parttypes and one only for the velocity partttype.
- */
-public abstract class AbstractVelocityPartType extends AbstractExtensiblePartType {
- /**
- * Sequence that is used as template name postfix. See {@link #getTemplateFromString(String)} for details.
- */
- protected static final AtomicLong templateNamePostfixSequence = new AtomicLong();
-
- /**
- * Logger
- */
- protected static NodeLogger logger = NodeLogger.getNodeLogger(AbstractVelocityPartType.class);
-
- /**
- * Put string into string resource repository, read template from velocity,
- * delete from string resource repository and return parsed template.
- * Additionally, add velocity macros.
- *
- * The name of the template will be made unique by adding a new value of {@link #templateNamePostfixSequence}.
- * Uniqueness of templates is important so that the velocimacros of the template can safely be removed from the velocimacro factory,
- * When the {@link SerializableVelocityTemplateWrapper} instance of the template is garbage collected.
- * @param template The template as string.
- * @return The template object constructed from the string.
- */
- protected Template getTemplateFromString(String template) throws Exception {
- // use the current thread's name as part of the template name, to
- // separate the velocimacros (template name is the "namespace" of
- // locally defined velocimacros)
- // Additionally, we add the tag id to the template name, so that different velocity tags do not interfer
- RenderType renderType = TransactionManager.getCurrentTransaction().getRenderType();
- Tag tag = renderType.getTopmostTag();
-
- StringBuilder templateNameBuilder = new StringBuilder();
-
- if (tag == null) {
- templateNameBuilder.append("Internal Template");
- } else {
- templateNameBuilder.append("Tag Template ").append(tag.getName());
- }
- templateNameBuilder.append("-").append(templateNamePostfixSequence.incrementAndGet());
- String templateName = templateNameBuilder.toString();
- StringResourceRepository srr = StringResourceLoader.getRepository();
-
- srr.putStringResource(templateName, template);
- Template tmp = Velocity.getTemplate(templateName);
-
- srr.removeStringResource(templateName);
-
- return tmp;
- }
-
- /**
- * Parse the template given by the parameters.
- *
- * Check whether the template has been cached (cache key is the md5 sum of the template source)
- * Call {@link #getTemplateFromString(String)} to parse the template source into a Template
- * Wrap the Template object into a {@link SerializableVelocityTemplateWrapper} instance that is put in the cache and returned from this object
- *
- * @param fullTemplate template source
- * @return A Template object.
- * @throws NodeException
- */
- protected SerializableVelocityTemplateWrapper parseTemplate(String fullTemplate) throws NodeException {
- // the md5Sum of the template will be used as cache key and part of its name
- String md5Sum = StringUtils.md5(fullTemplate);
-
- // try to get parsed templates from portal cache
- Object tmpTemplates = getCachedObject(md5Sum);
-
- if (tmpTemplates instanceof SerializableVelocityTemplateWrapper) {
- logger.debug("Template found in cache.");
- SerializableVelocityTemplateWrapper wrapper = (SerializableVelocityTemplateWrapper)tmpTemplates;
- Template template = wrapper.getTemplate();
-
- // template might be null as it is stored as transient in the
- // wrapper
- // if it is null, treat as cache miss
- if (template != null) {
- return wrapper;
- } else {
- logger.warn("Template cached, but null. Do not use disk-based cache for templates!");
- }
- }
-
- Template tmp = null;
-
- try {
- tmp = getTemplateFromString(fullTemplate);
- } catch (Exception e) {
- logger.error("StringResourceLoader didn't return a valid template. " + e.getMessage());
- throw new NodeException("StringResourceLoader didn't return a valid template. " + e.getMessage(), e);
- }
-
- SerializableVelocityTemplateWrapper wrapper = new SerializableVelocityTemplateWrapper(tmp);
-
- putObjectIntoCache(md5Sum, wrapper);
-
- return wrapper;
- }
-
- /**
- * Render the template wrapped by the wrapper and make sure that the wrapper is not garbage collected while the template is still rendered
- * @param wrapper wrapper
- * @param context velocity context
- * @param writer write to receive the rendered template
- * @throws ResourceNotFoundException
- * @throws ParseErrorException
- * @throws MethodInvocationException
- * @throws IOException
- */
- protected void mergeTemplate(SerializableVelocityTemplateWrapper wrapper, Context context, Writer writer)
- throws ResourceNotFoundException, ParseErrorException, MethodInvocationException, IOException {
- wrapper.getTemplate().merge(context, writer);
-
- // special hack to avoid the instance of SerializableVelocityTemplateWrapper to
- // be garbage collected while the template is still rendered.
- // If the SerializableVelocityTemplateWrapper is garbage collected, the finalize() method would dump the VM namespace of the template
- // to remove the local inline macros from the Velocity store (this is done to avoid memory leaks)
- // if this happens while the template is rendered, the macros would not be resolved any more.
- // accessing the config object after the call to getTemplate().merge() above will keep the reference, so the SerializableVelocityTemplateWrapper
- // will not be eligible for garbage collection to an inapropriate moment.
- wrapper.toString();
- }
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/BreadcrumbCompatibilityPartType.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/BreadcrumbCompatibilityPartType.java
deleted file mode 100644
index 63cb614c4a..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/BreadcrumbCompatibilityPartType.java
+++ /dev/null
@@ -1,860 +0,0 @@
-/*
- * @author alexander
- * @date 14.03.2007
- * @version $Id: BreadcrumbCompatibilityPartType.java,v 1.13 2009-12-16 16:12:12 herbert Exp $
- */
-package com.gentics.contentnode.object.parttype;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Vector;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.api.lib.exception.UnknownPropertyException;
-import com.gentics.api.lib.resolving.PropertyResolver;
-import com.gentics.api.lib.resolving.Resolvable;
-import com.gentics.contentnode.render.RenderableResolvable;
-import com.gentics.lib.etc.StringUtils;
-import com.gentics.lib.log.NodeLogger;
-
-/**
- * This parttype implements the compatibility breadcrumb navigation.
- */
-
-public class BreadcrumbCompatibilityPartType extends AbstractVelocityCompatibilityPartType {
-
- /**
- * Static logger
- */
- protected static NodeLogger logger = NodeLogger.getNodeLogger(BreadcrumbCompatibilityPartType.class);
-
- /**
- * Static type code for folders.
- */
- protected static final int TYPE_FOLDER = 10002;
-
- /**
- * Name of input parameter for startfolder
- */
- protected static final String INPUT_STARTFOLDER = "startfolder";
-
- /**
- * Default value for startfolder
- */
- protected static final String INPUT_STARTFOLDER_DEFAULT = "node.folder";
-
- /**
- * Name of input parameter for template
- */
- public static final String INPUT_TEMPLATE = "templates";
-
- /**
- * Name of input parameter for tagname_hidden
- */
- protected static final String INPUT_TAGNAMEHIDDEN = "tagname_hidden";
-
- /**
- * Default value for tagname_hidden
- */
- protected static final String INPUT_TAGNAMEHIDDEN_DEFAULT = "navhidden";
-
- /**
- * Name of input parameter for disable_fallback
- */
- protected static final String INPUT_DISABLEFALLBACK = "disable_fallback";
-
- /**
- * Default value for disable_fallback 0 ... use fallback to default language
- * 1 ... cut (end breadcrumb if language not available) 2 ... skip (skip
- * folder if language not available)
- */
- protected static final String INPUT_DISABLEFALLBACK_DEFAULT = "0";
-
- /**
- * Name of input parameter for disable_activepage
- */
- protected static final String INPUT_DISABLEACTIVEPAGE = "disable_activepage";
-
- /**
- * Default value for disable_activepage
- */
- protected static final boolean INPUT_DISABLEACTIVEPAGE_DEFAULT = false;
-
- /**
- * Name of input parameter for startpage (of folder) compatibility mode
- */
- protected static final String INPUT_TAGNAME_STARTPAGE = "tagname_startpage2";
-
- /**
- * Default value for startpage of folder
- */
- protected static final String INPUT_TAGNAME_STARTPAGE_DEFAULT = "object.startpage";
-
- /**
- * Name of input parameter for startfolder
- */
- protected static final String INPUT_LANGUAGECODE = "languagecode";
-
- /**
- * Default value for startfolder
- */
- protected static final String INPUT_LANGUAGECODE_DEFAULT = "";
-
- /**
- * Name of input parameter for disable_hidden
- */
- protected static final String INPUT_DISABLEHIDDEN = "disable_hidden";
-
- /**
- * Default value for disable_hidden
- */
- protected static final boolean INPUT_DISABLEHIDDEN_DEFAULT = false;
-
- /**
- * Name of input parameter for page
- */
- protected static final String INPUT_PAGE = "page";
-
- /**
- * Name of attribute for folder of page
- */
- protected static final String NAV_FOLDER = "folder";
-
- /**
- * Name of attribute for parent
- */
- protected static final String NAV_PARENT = "parent";
-
- /**
- * Name of attribute for translated name
- */
- protected static final String NAV_NAME_LANGUAGE = "object.name_";
-
- /**
- * Name of attribute for name
- */
- protected static final String NAV_NAME = "name";
-
- /**
- * Name of attribute for URL
- */
- protected static final String NAV_URL = "url";
-
- /**
- * Name of attribute for ID
- */
- protected static final String NAV_ID = "id";
-
- /**
- * Name of attribute for objecttype
- */
- protected static final String NAV_OBJECTTYPE = "ttype";
-
- /**
- * Name of attribute for language variants
- */
- protected static final String NAV_LANGUAGES = "languageset.pages.";
-
- /**
- * Render the navigation. Gets all needed input parameters and starts
- * rendering at startpage. Parse old-style templates from XML.
- * @throws NodeException
- */
- public String render() throws NodeException {
- logger.info("Start rendering breadcrumb.");
-
- ConfigObject config = getInitParameters();
-
- Iterator pathIterator = config.path.iterator();
- StringWriter outwriter = new StringWriter();
-
- // compatibility breadcrumb starts counting at 1
- int level = 1;
-
- while (pathIterator.hasNext()) {
- Object folder = pathIterator.next();
-
- if (folder instanceof Resolvable) {
- // create the corresponding nav object
- NavObject nav = new NavObject(new RenderableResolvable((Resolvable) folder), level, config);
-
- // check for hidden folder
- if (nav.getHidden()) {
- continue;
- }
-
- if ("".equals(nav.getName())) {
- if (config.disableFallback == 1) {
- // cut navigation
- logger.debug("Disable fallback == 1, cutting navigation.");
- break;
- } else if (config.disableFallback == 2) {
- // skip item
- logger.debug("Disable fallback == 2, skipping item.");
- continue;
- }
- }
- renderObject(outwriter, nav, level, config);
- level++;
- }
- }
-
- logger.info("End rendering breadcrumb.");
- if (logger.isDebugEnabled()) {
- logger.debug("Breadcrumb: " + outwriter.toString());
- }
-
- return outwriter.toString();
- }
-
- /**
- * Read all needed init parameters using the resolve() method. Populates
- * instance variables.
- * @throws NodeException
- */
- protected ConfigObject getInitParameters() throws NodeException {
-
- logger.debug("Start reading configuration.");
-
- ConfigObject config = new ConfigObject();
-
- // get startfolder from input parameters
- Object tmpStartfolder = resolve(INPUT_STARTFOLDER);
-
- if (tmpStartfolder instanceof Resolvable) {
- config.startfolder = (Resolvable) tmpStartfolder;
- }
-
- // if no startfolder specified, use default node.folder
- if (config.startfolder == null) {
- config.startfolder = (Resolvable) resolve(INPUT_STARTFOLDER_DEFAULT);
- }
-
- // if still no startfolder, something has gone wrong
- if (config.startfolder == null) {
- logger.error("No startfolder set and couldn't find default start folder.");
- throw new NodeException("No startfolder set and couldn't find default start folder.");
- }
-
- // get template
- config.template = ObjectTransformer.getString(resolve(INPUT_TEMPLATE), "");
- if ("".equals(config.template)) {
- logger.error("No templates found.");
- throw new NodeException("No templates found.");
- }
-
- // get disable_activepage flag
- // default to false
- config.disableActivepage = ObjectTransformer.getBoolean(resolve(INPUT_DISABLEACTIVEPAGE), INPUT_DISABLEACTIVEPAGE_DEFAULT);
-
- // get tagname_hidden
- // default to "navhidden"
- config.tagnameHidden = ObjectTransformer.getString(resolve(INPUT_TAGNAMEHIDDEN), INPUT_TAGNAMEHIDDEN_DEFAULT);
- if (config.tagnameHidden == null || "".equals(config.tagnameHidden)) {
- config.tagnameHidden = INPUT_TAGNAMEHIDDEN_DEFAULT;
- }
-
- // get languagecode
- // default to ""
- config.languagecode = ObjectTransformer.getString(resolve(INPUT_LANGUAGECODE), INPUT_LANGUAGECODE_DEFAULT);
- if (config.languagecode == null || "".equals(config.languagecode)) {
- config.languagecode = INPUT_LANGUAGECODE_DEFAULT;
- }
-
- // get disable_fallback
- String tmpDisableFallback = ObjectTransformer.getString(resolve(INPUT_DISABLEFALLBACK), INPUT_DISABLEFALLBACK_DEFAULT);
-
- config.disableFallback = 0;
- if ("2".equals(tmpDisableFallback) || "skip".equalsIgnoreCase(tmpDisableFallback)) {
- config.disableFallback = 2;
- } else if ("1".equals(tmpDisableFallback) || "yes".equalsIgnoreCase(tmpDisableFallback) || "true".equalsIgnoreCase(tmpDisableFallback)) {
- config.disableFallback = 1;
- }
-
- // get tagname_startpage
- config.tagnameStartpage = ObjectTransformer.getString(resolve(INPUT_TAGNAME_STARTPAGE), INPUT_TAGNAME_STARTPAGE_DEFAULT);
- if (config.tagnameStartpage == null || "".equals(config.tagnameStartpage)) {
- config.tagnameStartpage = INPUT_TAGNAME_STARTPAGE_DEFAULT;
- }
-
- // get disable_hidden
- config.disableHidden = ObjectTransformer.getBoolean(resolve(INPUT_DISABLEHIDDEN), INPUT_DISABLEHIDDEN_DEFAULT);
-
- // get current page
- Object tmpCurrentPage = resolve(INPUT_PAGE);
-
- if (tmpCurrentPage instanceof Resolvable) {
- config.currentPage = (Resolvable) tmpCurrentPage;
- } else {
- logger.warn("Current page not found.");
- }
-
- // get current folder
- if (config.currentPage != null) {
- Object tmpCurrentFolder = config.currentPage.get(NAV_FOLDER);
-
- if (tmpCurrentFolder instanceof Resolvable) {
- config.currentFolder = (Resolvable) tmpCurrentFolder;
- } else {
- logger.error("Current folder could not be resolved.");
- throw new NodeException("Current folder could not be resolved.");
- }
- } else {
- logger.warn("Current folder could not be resolved.");
- throw new NodeException("Current folder could not be resolved.");
- }
-
- // get path from current page to startpage and add objects to vector
- config.path = new Vector();
- Resolvable pathitem = config.currentFolder;
-
- while (!config.startfolder.equals(pathitem) && pathitem != null) {
- config.path.add(pathitem);
- Object parent = pathitem.get(NAV_PARENT);
-
- if (parent instanceof Resolvable) {
- pathitem = (Resolvable) parent;
- } else {
- pathitem = null;
- }
- }
- // add startfolder to path
- if (config.startfolder.equals(pathitem)) {
- config.path.add(pathitem);
- }
-
- // reverse path vector
- Collections.reverse(config.path);
-
- // parse old style templates
- config.templates = parseTemplates(config.template);
-
- if (logger.isDebugEnabled()) {
- logger.debug("End reading configuration." + config);
- }
-
- return config;
- }
-
- /**
- * Parse old-style XML templates and transform to Velocity templates.
- * @param inputTemplate All templates as one XML document.
- * @return A HashMap containing all transformed templates, hashed by level
- * and type.
- * @throws NodeException If an exception occured during XML parsing.
- */
- protected HashMap parseTemplates(String inputTemplate) throws NodeException {
-
- logger.debug("Start parsing templates.");
-
- // add surrounding block to make valid XML
- inputTemplate = "" + inputTemplate + " ";
-
- // try to get parsed templates from portal cache
- Object tmpTemplates = getCachedObject(inputTemplate);
-
- if (tmpTemplates instanceof HashMap) {
- logger.debug("Templates found in cache.");
- return (HashMap) tmpTemplates;
- }
-
- logger.debug("Templates not found in cache, start parsing from XML.");
-
- // templates not cached, create new
- HashMap templates = new HashMap();
-
- try {
- // Read XML input string into a DOM document
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- DocumentBuilder db = dbf.newDocumentBuilder();
- Document document = db.parse(new InputSource(new StringReader(inputTemplate)));
-
- // loop over all templates
- NodeList nodeTemplates = document.getElementsByTagName("template");
-
- for (int i = 0; i < nodeTemplates.getLength(); i++) {
-
- // read a template
- Node node = nodeTemplates.item(i);
-
- // get template level
- NamedNodeMap nodeAttributes = node.getAttributes();
- Node nodeLevel = nodeAttributes.getNamedItem("level");
- Integer templateLevel = Integer.valueOf(nodeLevel.getNodeValue());
-
- // read subtemplates
- NodeList nodeSubTemplates = node.getChildNodes();
- HashMap subTemplates = new HashMap();
-
- for (int j = 0; j < nodeSubTemplates.getLength(); j++) {
-
- // read template
- Node nodeSubTemplate = nodeSubTemplates.item(j);
-
- // check to see if node is an element
- if (nodeSubTemplate.getNodeType() != Node.ELEMENT_NODE) {
- continue;
- }
-
- String elementName = nodeSubTemplate.getNodeName();
- String elementValue = getTemplateFromNode(nodeSubTemplate);
-
- // put into hashmap to store in cache
- Template tmp = getTemplateFromString(convertVelocity(elementValue));
-
- subTemplates.put(elementName, tmp);
- }
- templates.put(templateLevel, subTemplates);
- }
-
- // put parsed templates into cache
- putObjectIntoCache(inputTemplate, templates);
-
- logger.debug("End parsing templates.");
-
- // return templates
- return templates;
-
- } catch (ParserConfigurationException pce) {
- logger.error("ParserConfigurationException while parsing templates. " + pce.getMessage());
- throw new NodeException(pce.getMessage(), pce);
- } catch (IOException ioe) {
- logger.error("IOException while parsing templates. " + ioe.getMessage());
- throw new NodeException(ioe.getMessage(), ioe);
- } catch (SAXException saxe) {
- logger.error("SAXException while parsing templates. " + saxe.getMessage());
- throw new NodeException(saxe.getMessage(), saxe);
- } catch (Exception e) {
- logger.error("Exception while parsing templates. " + e.getMessage());
- throw new NodeException(e.getMessage(), e);
- }
- }
-
- /**
- * Replace all old-style tags by Velocity $nav.xxx statements.
- * @param input The old-style template.
- * @return A Velocity-fied template.
- */
- protected String convertVelocity(String input) {
- return input.replaceAll("", "\\${folder.$1}");
- }
-
- /**
- * Render a resovable object.
- * @param outwriter StringWriter to append output to
- * @param nav The navigation object that should be rendered.
- * @param level The current level of the object (startpage has level -1, as
- * only sub-elements of startpage are shown).
- * @throws NodeException
- */
- protected void renderObject(StringWriter outwriter, NavObject nav, int level,
- ConfigObject config) throws NodeException {
-
- if (logger.isDebugEnabled()) {
- logger.debug("Start rendering object: " + nav.toString());
- }
-
- // create Velocity context, populate
- VelocityContext context = new VelocityContext(createContext(true));
-
- context.put("folder", nav);
-
- // fetch template for object
- String type = "";
-
- if ((!"".equals(nav.getLinkstartpage()) && !config.disableActivepage)
- || (config.disableActivepage && !"".equals(nav.getLinkstartpage())
- && (config.currentPage != null && !config.currentPage.equals(nav.getLanguageStartpage())))) {
- type = "linked";
- } else {
- type = "notlinked";
- }
-
- try {
- Template template = getTemplate(type, level, true, config);
-
- if (template != null) {
- logger.debug("Merging template.");
- template.merge(context, outwriter);
- }
-
- } catch (ParseErrorException pee) {
- logger.error("ParseErrorException while merging template. " + pee.getMessage());
- throw new NodeException("ParseErrorException while merging template. " + pee.getMessage(), pee);
- } catch (ResourceNotFoundException rnfe) {
- logger.error("ResourceNotFoundException while merging template. " + rnfe.getMessage());
- throw new NodeException("ResourceNotFoundException while merging template. " + rnfe.getMessage(), rnfe);
- } catch (MethodInvocationException mie) {
- logger.error("MethodInvocationException while merging template. " + mie.getMessage());
- throw new NodeException("MethodInvocationException while merging template. " + mie.getMessage(), mie);
- } catch (IOException ioe) {
- logger.error("IOException while merging template. " + ioe.getMessage());
- throw new NodeException("IOException while merging template. " + ioe.getMessage(), ioe);
- } catch (Exception e) {
- logger.error("Exception while merging template. " + e.getMessage());
- throw new NodeException("Exception while merging template. " + e.getMessage(), e);
- }
- }
-
- /**
- * Get template for specified object and level.
- * @param type Type of template to return (selected, unselectedlinked,
- * unselectednotlinked)
- * @param level The template level.
- * @param fallback True if level should gradually be decremented until a
- * template is found, false if not.
- * @return The already to Velocity converted template.
- */
- protected Template getTemplate(String type, int level, boolean fallback,
- ConfigObject config) {
-
- if (logger.isDebugEnabled()) {
- logger.debug("Get template from map. type = " + type + ". level = " + level + ". fallback = " + fallback);
- }
-
- // check level. exit if level < 0 to prevent infinite loop
- if (level < 0) {
- logger.debug("Level < 0, aborting search for template.");
- return null;
- }
-
- // try to get right template level
- Object tmpSubTemplates = config.templates.get(new Integer(level));
-
- if (tmpSubTemplates instanceof HashMap) {
- HashMap subTemplates = (HashMap) tmpSubTemplates;
-
- // get template
- Object template = subTemplates.get(type);
-
- if (template instanceof Template) {
- logger.debug("Template found.");
- return (Template) template;
- }
-
- // still no template found, step up one level if fallback enabled
- if (fallback) {
- logger.debug("No template found, fallback to upper level.");
- return getTemplate(type, level - 1, fallback, config);
- } else {
- logger.debug("No template found, fallback disabled.");
- return null;
- }
-
- // no template found for this level, try to step up
- } else {
- if (fallback) {
- logger.debug("No template found, fallback to upper level.");
- return getTemplate(type, level - 1, fallback, config);
- } else {
- logger.debug("No template found, fallback disabled.");
- return null;
- }
- }
- }
-
- /**
- * The object representing a navigation element.
- * @author alexander
- */
- public class NavObject {
-
- /**
- * The level of this element.
- */
- protected int level;
-
- /**
- * The resolvable object this navobject renders.
- */
- protected Resolvable object;
-
- /**
- * Store configuration
- */
- protected ConfigObject config;
-
- /**
- * Constructor of the Navigation Object.
- * @param object The resolvable object that is rendered.
- * @param level The level of the object.
- */
- public NavObject(Resolvable object, int level, ConfigObject config) {
- this.object = object;
- this.level = level;
- this.config = config;
- }
-
- /**
- * @return The resolvable object that is rendered.
- */
- public Resolvable getObject() {
- return object;
- }
-
- /**
- * @return Level of the element (startfolder has level -1).
- */
- public int getLevel() {
- return level;
- }
-
- /**
- * @return Name of the element.
- */
- public String getName() {
-
- String nameLanguage = "";
-
- if (getType() == TYPE_FOLDER && !"".equals(config.languagecode)) {
-
- try {
- nameLanguage = ObjectTransformer.getString(PropertyResolver.resolve(object, NAV_NAME_LANGUAGE + config.languagecode), "");
- } catch (UnknownPropertyException upe) {
- nameLanguage = "";
- }
-
- if ((nameLanguage == null || "".equals(nameLanguage)) && config.disableFallback != 0) {
- return "";
- }
- }
-
- if (!"".equals(nameLanguage)) {
- return nameLanguage;
- }
-
- // fallback to default language
- return ObjectTransformer.getString(object.get(NAV_NAME), "");
- }
-
- /**
- * @return URL of element.
- */
- public String getLinkstartpage() {
- // try to get the language specific startpage
- Resolvable startpage = getLanguageStartpage();
-
- if (startpage != null) {
- return ObjectTransformer.getString(startpage.get(NAV_URL), "");
- } else {
- // no startpage found, this means that object.startpage does not
- // point to a page
- // in that case, simply render object.startpage.url
- try {
- return ObjectTransformer.getString(PropertyResolver.resolve(object, config.tagnameStartpage + ".url"), "");
- } catch (UnknownPropertyException upe) {
- return "";
- }
- }
- }
-
- /**
- * @return Resolvable representing startpage of object
- */
- protected Resolvable getStartpage() {
- // if not page, try to get startpage
- if (getType() == TYPE_FOLDER) {
-
- Object startpage = null;
-
- try {
- startpage = PropertyResolver.resolve(object, config.tagnameStartpage + ".url.target");
- } catch (UnknownPropertyException upe) {
- if (logger.isDebugEnabled()) {
- logger.debug("No startpage found for folder: " + object);
- }
- startpage = null;
- }
-
- // Object startpage = object.get(config.tagnameStartpage);
- if (startpage instanceof Resolvable) {
- return (Resolvable) startpage;
- }
- return null;
- }
-
- // if page, return itself
- return object;
- }
-
- /**
- * Get language-variant of startpage.
- * @return The language-variant of the startpage.
- */
- protected Resolvable getLanguageStartpage() {
-
- Resolvable startpage = getStartpage();
-
- if (startpage == null) {
- return null;
- }
-
- if (StringUtils.isEmpty(config.languagecode)) {
- return startpage;
- }
-
- Object page = null;
-
- try {
- page = PropertyResolver.resolve(startpage, NAV_LANGUAGES + config.languagecode);
- } catch (UnknownPropertyException upe) {
- page = null;
- }
-
- if (page instanceof Resolvable) {
- return (Resolvable) page;
- }
-
- return startpage;
- }
-
- /**
- * @return The ID of the element.
- */
- public Object getId() {
- //TODO use obj transformer and return integer?
- return object.get(NAV_ID);
- }
-
- /**
- * @return Type of element (e.g. 10002 == folder).
- */
- public int getType() {
- return ObjectTransformer.getInt(object.get(NAV_OBJECTTYPE), 0);
- }
-
- /**
- * @return True if element is hidden from navigation, false otherwise.
- */
- public boolean getHidden() {
- try {
- return ObjectTransformer.getBoolean(PropertyResolver.resolve(object, "object." + config.tagnameHidden), false);
- } catch (UnknownPropertyException upe) {
- return false;
- }
- }
-
- /**
- * Check to see if this element is the current page.
- * @return If this element is the current page.
- */
- protected boolean isCurrentpage() {
- if (config.currentPage != null) {
- return config.currentPage.equals(getObject());
- } else {
- return false;
- }
- }
- }
-
- public class ConfigObject {
-
- /**
- * Startfolder of the navigation.
- */
- public Resolvable startfolder;
-
- /**
- * Template to use to render navigation.
- */
- public String template;
-
- /**
- * If current page should be linked
- */
- public boolean disableActivepage;
-
- /**
- * Code of language to use in navigation
- */
- public String languagecode;
-
- /**
- * Property which stores the hidden attribute name.
- */
- public String tagnameHidden;
-
- /**
- * If navigation should display hidden elements.
- */
- public boolean disableHidden;
-
- /**
- * If language fallback is enabled
- */
- public int disableFallback;
-
- /**
- * The current page for which the navigation is created.
- */
- public Resolvable currentPage;
-
- /**
- * The current folder for which the navigation is created (parent of
- * currentPage).
- */
- public Resolvable currentFolder;
-
- /**
- * Set containing all resolvables leading from the current page to the
- * startpage.
- */
- public List path;
-
- /**
- * Store all templates read from XML input.
- */
- public HashMap templates;
-
- /**
- * Name of tag for startpage of folder
- */
- public String tagnameStartpage;
-
- public ConfigObject() {
- startfolder = null;
- template = null;
- disableActivepage = INPUT_DISABLEACTIVEPAGE_DEFAULT;
- languagecode = null;
- tagnameHidden = null;
- disableHidden = INPUT_DISABLEHIDDEN_DEFAULT;
- disableFallback = 0;
- currentPage = null;
- currentFolder = null;
- path = null;
- templates = null;
- tagnameStartpage = null;
- }
-
- /**
- * Return all configuration parameters as string.
- */
- public String toString() {
- return " startfolder: " + startfolder + ". template: " + template + ". disableActivepage: " + disableActivepage + ". languagecode: " + languagecode
- + ". tagnameHidden: " + tagnameHidden + ". disableHidden: " + disableHidden + ". disableFallback: " + disableFallback + ". currentPage: "
- + currentPage + ". currentFolder: " + currentFolder + ". path: " + path + ". templates: " + templates + ". tagnameStartpage: " + tagnameStartpage;
- }
- }
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/BreadcrumbPartType.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/BreadcrumbPartType.java
deleted file mode 100644
index a6f229b9b8..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/BreadcrumbPartType.java
+++ /dev/null
@@ -1,718 +0,0 @@
-/*
- * @author alexander
- * @date 14.03.2007
- * @version $Id: BreadcrumbPartType.java,v 1.9 2009-12-16 16:12:12 herbert Exp $
- */
-package com.gentics.contentnode.object.parttype;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Vector;
-
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.api.lib.exception.UnknownPropertyException;
-import com.gentics.api.lib.resolving.PropertyResolver;
-import com.gentics.api.lib.resolving.Resolvable;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.contentnode.render.RenderableResolvable;
-import com.gentics.contentnode.rest.model.Property;
-import com.gentics.contentnode.rest.model.Property.Type;
-import com.gentics.lib.etc.StringUtils;
-import com.gentics.lib.log.NodeLogger;
-import com.gentics.lib.render.velocity.SerializableVelocityTemplateWrapper;
-
-/**
- * PartType 34 - Breadcrumb
- */
-public class BreadcrumbPartType extends AbstractVelocityPartType implements TransformablePartType {
-
- /**
- * Logger
- */
- protected static NodeLogger logger = NodeLogger.getNodeLogger(BreadcrumbPartType.class);
-
- /**
- * Static type code for folders.
- */
- protected static final int TYPE_FOLDER = 10002;
-
- /**
- * Name of input parameter for startfolder
- */
- protected static final String INPUT_STARTFOLDER = "startfolder.target";
-
- /**
- * Default value for startfolder
- */
- protected static final String INPUT_STARTFOLDER_DEFAULT = "node.folder";
-
- /**
- * Name of input parameter for template
- */
- public static final String INPUT_TEMPLATE = "template";
-
- /**
- * Name of input parameter for startpage (of folder)
- */
- protected static final String INPUT_TAGNAME_STARTPAGE = "tagname_startpage";
-
- /**
- * Default value for startpage of folder
- */
- protected static final String INPUT_TAGNAME_STARTPAGE_DEFAULT = "startpage";
-
- /**
- * Name of input parameter for disable_fallback
- */
- protected static final String INPUT_DISABLEFALLBACK = "disable_fallback";
-
- /**
- * Default value for disable_fallback 0 ... use fallback to default language
- * 1 ... cut (end breadcrumb if language not available) 2 ... skip (skip
- * folder if language not available)
- */
- protected static final String INPUT_DISABLEFALLBACK_DEFAULT = "0";
-
- /**
- * Name of input parameter for disable_activepage
- */
- protected static final String INPUT_DISABLEACTIVEPAGE = "disable_activepage";
-
- /**
- * Default value for disable_activepage
- */
- protected static final boolean INPUT_DISABLEACTIVEPAGE_DEFAULT = false;
-
- /**
- * Name of input parameter for tagname_hidden
- */
- protected static final String INPUT_TAGNAMEHIDDEN = "tagname_hidden";
-
- /**
- * Default value for tagname_hidden
- */
- protected static final String INPUT_TAGNAMEHIDDEN_DEFAULT = "navhidden";
-
- /**
- * Name of input parameter for disable_hidden
- */
- protected static final String INPUT_DISABLEHIDDEN = "disable_hidden";
-
- /**
- * Default value for disable_hidden
- */
- protected static final boolean INPUT_DISABLEHIDDEN_DEFAULT = false;
-
- /**
- * Name of input parameter for page
- */
- protected static final String INPUT_PAGE = "page";
-
- /**
- * Name of attribute for folder of page
- */
- protected static final String NAV_FOLDER = "folder";
-
- /**
- * Name of attribute for parent
- */
- protected static final String NAV_PARENT = "parent";
-
- /**
- * Name of attribute for objecttype
- */
- protected static final String NAV_OBJECTTYPE = "ttype";
-
- /**
- * Name of attribute for languagecode
- */
- protected static final String NAV_LANGUAGECODE = "language.code";
-
- /**
- * Name of attribute for translated name
- */
- protected static final String NAV_NAME_LANGUAGE = "object.name_";
-
- /**
- * Name of attribute for name
- */
- protected static final String NAV_NAME = "name";
-
- /**
- * Name of attribute for language variants
- */
- protected static final String NAV_LANGUAGES = "languageset.pages.";
-
- /**
- * Render the navigation. Gets all needed input parameters and starts
- * rendering at startpage. Parse old-style templates from XML.
- * @throws NodeException
- */
- public String render() throws NodeException {
- logger.info("Start rendering breadcrumb.");
-
- ConfigObject config = getInitParameters();
-
- Iterator pathIterator = config.path.iterator();
- StringWriter outwriter = new StringWriter();
-
- int level = 0;
- Vector navObjects = new Vector();
-
- while (pathIterator.hasNext()) {
- Object folder = pathIterator.next();
-
- if (folder instanceof Resolvable) {
- NavObject nav = new NavObject((Resolvable) folder, level, config);
-
- level++;
-
- if ("".equals(nav.getName())) {
- if (config.disableFallback == 1) {
- // cut navigation
- break;
- } else if (config.disableFallback == 2) {
- // skip item
- continue;
- }
- }
-
- navObjects.add(nav);
- }
- }
-
- BCObject bc = new BCObject(navObjects, config.disableActivepage);
-
- // create Velocity context, populate
- VelocityContext context = new VelocityContext(createContext(true));
-
- context.put("ctx", context);
- context.put("bc", bc);
-
- RenderType renderType = TransactionManager.getCurrentTransaction().getRenderType();
- int editMode = renderType.getEditMode();
- boolean editModeChanged = false;
-
- try {
- // when edit mode is edit or realedit, switch to preview mode
- if (editMode == RenderType.EM_ALOHA) {
- editModeChanged = true;
- renderType.setEditMode(RenderType.EM_ALOHA_READONLY);
- }
- if (editModeChanged) {
- renderType.setParameter(CMSResolver.ModeResolver.PARAM_OVERWRITE_EDITMODE, new Integer(editMode));
- }
-
- if (config.wrapper != null) {
- mergeTemplate(config.wrapper, context, outwriter);
- }
-
- } catch (ParseErrorException pee) {
- logger.error("ParseErrorException while rendering. " + pee.getMessage());
- throw new NodeException("ParseErrorException while rendering. " + pee.getMessage(), pee);
- } catch (ResourceNotFoundException rnfe) {
- logger.error("ResourceNotFoundException while rendering. " + rnfe.getMessage());
- throw new NodeException("ResourceNotFoundException while rendering. " + rnfe.getMessage(), rnfe);
- } catch (MethodInvocationException mie) {
- logger.error("MethodInvocationException while rendering. " + mie.getMessage());
- throw new NodeException("MethodInvocationException while rendering. " + mie.getMessage(), mie);
- } catch (IOException ioe) {
- logger.error("IOException while rendering. " + ioe.getMessage());
- throw new NodeException("IOException while rendering. " + ioe.getMessage(), ioe);
- } catch (Exception e) {
- logger.error("Exception while rendering. " + e.getMessage());
- throw new NodeException("Exception while rendering. " + e.getMessage(), e);
- } finally {
- // when edit mode was changed, change it back
- if (editModeChanged) {
- renderType.setEditMode(editMode);
- if (editModeChanged) {
- renderType.setParameter(CMSResolver.ModeResolver.PARAM_OVERWRITE_EDITMODE, null);
- }
- }
- }
-
- logger.info("End rendering breadcrumb.");
- if (logger.isDebugEnabled()) {
- logger.debug("Breadcrumb: " + outwriter.toString());
- }
-
- return outwriter.toString();
- }
-
- /**
- * Read all needed init parameters using the resolve() method. Populates
- * instance variables.
- * @throws NodeException
- */
- protected ConfigObject getInitParameters() throws NodeException {
- logger.debug("Start reading configuration.");
-
- ConfigObject config = new ConfigObject();
-
- // get startfolder from input parameters
- Object tmpStartfolder = resolve(INPUT_STARTFOLDER);
-
- if (tmpStartfolder instanceof Resolvable) {
- config.startfolder = (Resolvable) tmpStartfolder;
- }
-
- // if no startfolder specified, use default node.folder
- if (config.startfolder == null) {
- config.startfolder = (Resolvable) resolve(INPUT_STARTFOLDER_DEFAULT);
- }
-
- // if still no startfolder, something has gone wrong
- if (config.startfolder == null) {
- logger.error("No startfolder set and couldn't find default start folder.");
- throw new NodeException("No startfolder set and couldn't find default start folder.");
- }
-
- // get template
- config.template = ObjectTransformer.getString(resolve(INPUT_TEMPLATE), "");
- if ("".equals(config.template)) {
- logger.error("No templates found.");
- throw new NodeException("No templates found.");
- }
-
- // get disable_activepage flag
- // default to false
- config.disableActivepage = ObjectTransformer.getBoolean(ObjectTransformer.getString(resolve(INPUT_DISABLEACTIVEPAGE), ""),
- INPUT_DISABLEACTIVEPAGE_DEFAULT);
-
- // get tagname_hidden
- // default to "navhidden"
- config.tagnameHidden = ObjectTransformer.getString(resolve(INPUT_TAGNAMEHIDDEN), INPUT_TAGNAMEHIDDEN_DEFAULT);
- if (config.tagnameHidden == null || "".equals(config.tagnameHidden)) {
- config.tagnameHidden = INPUT_TAGNAMEHIDDEN_DEFAULT;
- }
-
- // get disable_fallback
- String tmpDisableFallback = ObjectTransformer.getString(resolve(INPUT_DISABLEFALLBACK), INPUT_DISABLEFALLBACK_DEFAULT);
-
- config.disableFallback = 0;
- if ("2".equals(tmpDisableFallback) || "skip".equalsIgnoreCase(tmpDisableFallback)) {
- config.disableFallback = 2;
- } else if ("1".equals(tmpDisableFallback) || "yes".equalsIgnoreCase(tmpDisableFallback) || "true".equalsIgnoreCase(tmpDisableFallback)) {
- config.disableFallback = 1;
- }
-
- // get tagname_startpage
- config.tagnameStartpage = ObjectTransformer.getString(resolve(INPUT_TAGNAME_STARTPAGE), INPUT_TAGNAME_STARTPAGE_DEFAULT);
- if (config.tagnameStartpage == null || "".equals(config.tagnameStartpage)) {
- config.tagnameStartpage = INPUT_TAGNAME_STARTPAGE_DEFAULT;
- }
-
- // get disable_hidden
- config.disableHidden = ObjectTransformer.getBoolean(resolve(INPUT_DISABLEHIDDEN), INPUT_DISABLEHIDDEN_DEFAULT);
-
- // get current page
- Object tmpCurrentPage = resolve(INPUT_PAGE);
-
- if (tmpCurrentPage instanceof Resolvable) {
- config.currentPage = (Resolvable) tmpCurrentPage;
- } else {
- logger.warn("Current page not found.");
- }
-
- // get current folder
- if (config.currentPage != null) {
- Object tmpCurrentFolder = config.currentPage.get(NAV_FOLDER);
-
- if (tmpCurrentFolder instanceof Resolvable) {
- config.currentFolder = (Resolvable) tmpCurrentFolder;
- } else {
- logger.error("Current folder cannot be resolved.");
- throw new NodeException("Current folder cannot be resolved.");
- }
- } else {
- logger.warn("Current folder cannot be resolved.");
- throw new NodeException("Current folder cannot be resolved.");
- }
-
- // get languagecode
- try {
- config.languagecode = ObjectTransformer.getString(PropertyResolver.resolve(config.currentPage, NAV_LANGUAGECODE), "");
- } catch (UnknownPropertyException upe) {
- config.languagecode = "";
- }
-
- // get path from current page to startpage and add objects to hashset
- config.path = new Vector();
- Resolvable pathitem = config.currentFolder;
-
- while (!config.startfolder.equals(pathitem) && pathitem != null) {
- config.path.add(pathitem);
- Object parent = pathitem.get(NAV_PARENT);
-
- if (parent instanceof Resolvable) {
- pathitem = (Resolvable) parent;
- } else {
- pathitem = null;
- }
- }
- // add startfolder to path
- if (config.startfolder.equals(pathitem)) {
- config.path.add(pathitem);
- }
-
- // reverse path vector
- Collections.reverse(config.path);
-
- // parse old style templates
- config.wrapper = parseTemplate(config.template);
-
- config.cutNavigation = false;
-
- if (logger.isDebugEnabled()) {
- logger.debug("End reading configuration." + config);
- }
-
- return config;
- }
-
- @Override
- public Type getPropertyType() {
- return Type.BREADCRUMB;
- }
-
- @Override
- public void fromProperty(Property property) throws NodeException {
- }
-
- @Override
- public Property toProperty() throws NodeException {
- return null;
- }
-
- /**
- * The object representing the breadcrumb.
- * @author alexander
- */
- public class BCObject {
-
- /**
- * Vector holding all navigation objects in path
- */
- protected Vector navObjects;
-
- /**
- * True if active page should not be linked, false otherwise.
- */
- protected boolean disableActivepage;
-
- /**
- * Create new object.
- * @param navObjects The vector of all folders in path for breadcrumb
- * @param disableActivepage True if active page should not be linked.
- */
- public BCObject(Vector navObjects, boolean disableActivepage) {
- this.navObjects = navObjects;
- this.disableActivepage = disableActivepage;
- }
-
- /**
- * @return Vector of all folders in path to current page.
- */
- public Vector getPath() {
- return navObjects;
- }
-
- /**
- * @return True if active page should not be linked.
- */
- public boolean getDisableactivepage() {
- return disableActivepage;
- }
- }
-
- /**
- * The object representing a navigation element.
- * @author alexander
- */
- public class NavObject {
-
- /**
- * The level of this element.
- */
- protected int level;
-
- /**
- * The resolvable object this navobject renders.
- */
- protected Resolvable object;
-
- /**
- * Store configuration
- */
- protected ConfigObject config;
-
- /**
- * Constructor of the Navigation Object.
- * @param object The resolvable object that is rendered.
- * @param level The level of the object.
- */
- public NavObject(Resolvable object, int level, ConfigObject config) {
- this.object = object;
- this.level = level;
- this.config = config;
- }
-
- /**
- * @return The resolvable object that is rendered.
- */
- public Resolvable getObject() {
- return new RenderableResolvable(object);
- }
-
- /**
- * @return Level of the element (startfolder has level -1).
- */
- public int getLevel() {
- return level;
- }
-
- /**
- * @return Name of the element.
- */
- public String getName() {
-
- String nameLanguage = "";
-
- if (getType() == TYPE_FOLDER && !"".equals(config.languagecode)) {
-
- try {
- nameLanguage = ObjectTransformer.getString(PropertyResolver.resolve(getObject(), NAV_NAME_LANGUAGE + config.languagecode), "");
- } catch (UnknownPropertyException upe) {
- nameLanguage = "";
- }
-
- if ((nameLanguage == null || "".equals(nameLanguage)) && config.disableFallback != 0) {
- return "";
- }
- }
-
- if (!"".equals(nameLanguage)) {
- return nameLanguage;
- }
-
- // fallback to default language
- return ObjectTransformer.getString(object.get(NAV_NAME), "");
- }
-
- /**
- * @return Resolvable representing startpage of object
- */
- public Resolvable getStartpage() {
- // try to get language specific startpage for folder
- // this will fail if the startpage is an external url
- Object obj = getLanguageStartpage();
-
- if (obj != null) {
- return new RenderableResolvable(obj);
- }
-
- // startpage is an external URL
- try {
- return new RenderableResolvable(PropertyResolver.resolve(object, "object." + config.tagnameStartpage));
- } catch (UnknownPropertyException upe) {
- return null;
- }
- }
-
- /**
- * @return Startpage object for folder.
- */
- protected Resolvable getInternalStartpage() {
- // if not page, try to get startpage
- if (getType() == TYPE_FOLDER) {
-
- Object startpage = null;
-
- try {
- startpage = PropertyResolver.resolve(object, "object." + config.tagnameStartpage + ".url.target");
- } catch (UnknownPropertyException upe) {
- if (logger.isDebugEnabled()) {
- logger.debug("No startpage found for folder: " + object);
- }
- startpage = null;
- }
-
- // Object startpage = object.get(config.tagnameStartpage);
- if (startpage instanceof Resolvable) {
- return (Resolvable) startpage;
- }
- return null;
- }
-
- // if page, return itself
- return object;
- }
-
- /**
- * Get language-variant of startpage.
- * @return The language-variant of the startpage.
- */
- protected Resolvable getLanguageStartpage() {
- Resolvable startpage = getInternalStartpage();
-
- if (startpage == null) {
- return null;
- }
-
- if (StringUtils.isEmpty(config.languagecode)) {
- return startpage;
- }
-
- Object page = null;
-
- try {
- page = PropertyResolver.resolve(startpage, NAV_LANGUAGES + config.languagecode);
- } catch (UnknownPropertyException upe) {
- page = null;
- }
-
- if (page instanceof Resolvable) {
- return (Resolvable) page;
- }
-
- return startpage;
- }
-
- /**
- * @return Type of element (e.g. 10002 == folder).
- */
- protected int getType() {
- return ObjectTransformer.getInt(object.get(NAV_OBJECTTYPE), 0);
- }
-
- /**
- * @return True if element is hidden from navigation, false otherwise.
- */
- public boolean getHidden() {
- try {
- return ObjectTransformer.getBoolean(PropertyResolver.resolve(getObject(), "object." + config.tagnameHidden), false);
- } catch (UnknownPropertyException upe) {
- return false;
- }
- }
-
- /**
- * Check to see if this element is the current page.
- * @return If this element is the current page.
- */
- protected boolean isCurrentpage() {
- if (config.currentPage != null) {
- return config.currentPage.equals(getObject());
- } else {
- return false;
- }
- }
- }
-
- public class ConfigObject {
-
- /**
- * Startfolder of the navigation.
- */
- protected Resolvable startfolder;
-
- /**
- * Template to use to render navigation.
- */
- protected String template;
-
- /**
- * If current page should be linked
- */
- protected boolean disableActivepage;
-
- /**
- * Code of language to use in navigation
- */
- protected String languagecode;
-
- /**
- * Property which stores the hidden attribute name.
- */
- protected String tagnameHidden;
-
- /**
- * If navigation should display hidden elements.
- */
- protected boolean disableHidden;
-
- /**
- * If language fallback is enabled
- */
- protected int disableFallback;
-
- /**
- * The current page for which the navigation is created.
- */
- protected Resolvable currentPage;
-
- /**
- * The current folder for which the navigation is created (parent of
- * currentPage).
- */
- protected Resolvable currentFolder;
-
- /**
- * Set containing all resolvables leading from the current page to the
- * startpage.
- */
- protected List path;
-
- /**
- * Store all templates read from XML input.
- */
- protected SerializableVelocityTemplateWrapper wrapper;
-
- /**
- * Name of tag for startpage of folder
- */
- protected String tagnameStartpage;
-
- /**
- * True if navigation should be cut (ie no more items should be rendered)
- */
- protected boolean cutNavigation;
-
- public ConfigObject() {
- startfolder = null;
- template = null;
- disableActivepage = INPUT_DISABLEACTIVEPAGE_DEFAULT;
- languagecode = null;
- tagnameHidden = null;
- disableHidden = INPUT_DISABLEHIDDEN_DEFAULT;
- disableFallback = 0;
- currentPage = null;
- currentFolder = null;
- path = null;
- wrapper = null;
- tagnameStartpage = null;
- cutNavigation = false;
- }
-
- /**
- * Return all configuration parameters as string.
- */
- public String toString() {
- return " startfolder: " + startfolder + ". template: " + template + ". disableActivepage: " + disableActivepage + ". languagecode: " + languagecode
- + ". tagnameHidden: " + tagnameHidden + ". disableHidden: " + disableHidden + ". disableFallback: " + disableFallback + ". currentPage: "
- + currentPage + ". currentFolder: " + currentFolder + ". path: " + path + ". tagnameStartpage: " + tagnameStartpage;
- }
-
- }
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/CMSResolver.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/CMSResolver.java
index 9dd9ddab67..62bb42359a 100644
--- a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/CMSResolver.java
+++ b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/CMSResolver.java
@@ -12,17 +12,12 @@
import java.util.Set;
import org.apache.commons.collections4.SetUtils;
-import org.apache.commons.pool.KeyedObjectPool;
-import org.apache.commons.pool.KeyedPoolableObjectFactory;
-import org.apache.commons.pool.impl.GenericKeyedObjectPool;
-import org.apache.commons.pool.impl.GenericObjectPool;
import com.gentics.api.lib.exception.NodeException;
import com.gentics.api.lib.resolving.Resolvable;
import com.gentics.api.lib.resolving.ResolvableBean;
-import com.gentics.api.portalnode.imp.GenticsImpInterface;
+import com.gentics.contentnode.etc.ServiceLoaderUtil;
import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.formatter.CNDateFormatterImp;
import com.gentics.contentnode.object.ContentFile;
import com.gentics.contentnode.object.Folder;
import com.gentics.contentnode.object.Node;
@@ -31,16 +26,11 @@
import com.gentics.contentnode.object.Page;
import com.gentics.contentnode.object.Tag;
import com.gentics.contentnode.object.Template;
-import com.gentics.contentnode.object.parttype.imps.CMSLoaderImp;
import com.gentics.contentnode.render.RenderInfo;
import com.gentics.contentnode.render.RenderType;
import com.gentics.contentnode.resolving.ResolvableMapWrappable;
import com.gentics.contentnode.resolving.StackResolvable;
import com.gentics.lib.log.NodeLogger;
-import com.gentics.portalnode.formatter.GenticsStringFormatter;
-import com.gentics.portalnode.formatter.SortImp;
-import com.gentics.portalnode.formatter.URLIncludeImp;
-import com.gentics.portalnode.formatter.VelocityToolsImp;
/**
* Resolver for objects put into the context for AbstractExtensiblePartTypes
@@ -49,14 +39,18 @@
public class CMSResolver implements ResolvableMapWrappable {
protected ModeResolver modeResolver;
- protected ImpsResolver impsResolver;
-
protected static Map properties = new HashMap<>();
protected static NodeLogger logger = NodeLogger.getNodeLogger(CMSResolver.class);
protected final static Set resolvableKeys;
+ /**
+ * Service loader for {@link CMSResolverService}s
+ */
+ private final static ServiceLoaderUtil cmsResolverServiceLoader = ServiceLoaderUtil
+ .load(CMSResolverService.class);
+
static {
properties.put("rendermode", new Property() {
public Object get(CMSResolver cmsResolver) {
@@ -98,11 +92,6 @@ public Object get(CMSResolver cmsResolver) {
return cmsResolver.getFile();
}
});
- properties.put("imps", new Property() {
- public Object get(CMSResolver cmsResolver) {
- return cmsResolver.getImpsResolver();
- }
- });
resolvableKeys = SetUtils.difference(properties.keySet(), Collections.singleton("imps"));
}
@@ -124,6 +113,11 @@ public Object get(CMSResolver cmsResolver) {
*/
protected NodeObject rootObject;
+ /**
+ * Map of all resolvers, provided by {@link CMSResolverService}s
+ */
+ protected Map providedResolvers = new HashMap<>();
+
/**
* Create an instance of the cms resolver
* @param page page
@@ -136,7 +130,10 @@ public Object get(CMSResolver cmsResolver) {
*/
public CMSResolver(Page page, Template template, Tag tag, Folder folder, Node node,
ContentFile file) throws NodeException {
- impsResolver = new ImpsResolver();
+ cmsResolverServiceLoader.forEach(service -> {
+ providedResolvers.putAll(service.getResolvers());
+ });
+
this.page = page;
this.file = file;
this.template = template;
@@ -196,6 +193,11 @@ public Object get(String key) {
if (prop != null) {
Object value = prop.get(this);
+ addDependency(key, value);
+ return value;
+ } else if (providedResolvers.containsKey(key)) {
+ Object value = providedResolvers.get(key);
+
addDependency(key, value);
return value;
} else {
@@ -231,14 +233,6 @@ protected void addDependency(String property, Object resolvedObject) {
}
}
- /**
- * Get the imps resolver
- * @return imps resolver
- */
- protected ImpsResolver getImpsResolver() {
- return impsResolver;
- }
-
/**
* Get the mode resolver
* @return the mode resolver
@@ -436,334 +430,10 @@ public boolean getBackend() throws NodeException {
}
}
- /**
- * Imps resolver
- */
- public static class ImpsResolver {
-
- /**
- * velocity tools imp (when fetched from the pool)
- */
- protected GenticsImpInterface velocityToolsImp;
-
- /**
- * gentics string formatter (when fetched from the pool)
- */
- protected GenticsImpInterface genticsStringFormatter;
-
- /**
- * date formatter (when fetched from the pool)
- */
- protected GenticsImpInterface genticsDateFormatter;
-
- /**
- * sort imp (when fetched from the pool)
- */
- protected GenticsImpInterface sortImp;
-
- /**
- * loader imp
- */
- protected GenticsImpInterface loaderImp;
-
- /**
- * URL include imp
- */
- protected GenticsImpInterface urlIncludeImp;
-
- /**
- * constant for the velo imp
- */
- public final static String VELOIMP = "velocitytools";
-
- /**
- * constant for the string imp
- */
- public final static String STRINGIMP = "string";
-
- /**
- * constant for the date imp
- */
- public final static String DATEIMP = "date";
-
- /**
- * constant for the sorter imp
- */
- public final static String SORTIMP = "sorter";
-
- /**
- * constant for the loader imp
- */
- public final static String LOADERIMP = "loader";
-
- /**
- * constant for the url imp
- */
- public final static String URLIMP = "url";
-
- /**
- * Create instance of the imps resolver
- */
- public ImpsResolver() {}
-
- /**
- * Get the velocity tools imp
- * @return velocity tools imp
- */
- public GenticsImpInterface getVelocitytools() {
- if (velocityToolsImp == null) {
- velocityToolsImp = ImpProvider.getImp(VELOIMP);
- }
- return velocityToolsImp;
- }
-
- /**
- * Get the velocity tools imp - an alias which is the same as in PN 3.3
- * @return velocity tools imp
- */
- public GenticsImpInterface getVelocityTools() {
- if (velocityToolsImp == null) {
- velocityToolsImp = ImpProvider.getImp(VELOIMP);
- }
- return velocityToolsImp;
- }
-
- /**
- * Get the gentics string formatter imp
- * @return gentics string formatter imp
- */
- public GenticsImpInterface getString() {
- if (genticsStringFormatter == null) {
- genticsStringFormatter = ImpProvider.getImp(STRINGIMP);
- }
- return genticsStringFormatter;
- }
-
- /**
- * Get the sorter imp
- * @return sorter imp
- */
- public GenticsImpInterface getSorter() {
- if (sortImp == null) {
- sortImp = ImpProvider.getImp(SORTIMP);
- }
- return sortImp;
- }
-
- /**
- * Get the date formatter imp
- * @return date formatter imp
- */
- public GenticsImpInterface getDate() {
- if (genticsDateFormatter == null) {
- genticsDateFormatter = ImpProvider.getImp(DATEIMP);
- }
- return genticsDateFormatter;
- }
-
- public GenticsImpInterface getLoader() {
- if (loaderImp == null) {
- loaderImp = ImpProvider.getImp(LOADERIMP);
- }
- return loaderImp;
- }
-
- public GenticsImpInterface getUrl() {
- if (urlIncludeImp == null) {
- urlIncludeImp = ImpProvider.getImp(URLIMP);
- }
- return urlIncludeImp;
- }
- }
-
- /**
- * Class for the singleton imp provider, that provides imps which are held
- * in pools
- */
- protected final static class ImpProvider {
-
- /**
- * internal imp pool
- */
- protected KeyedObjectPool impPool = null;
-
- /**
- * the singleton instance
- */
- protected static ImpProvider instance = null;
-
- /**
- * static method to get an imp from the pool
- * @param impId id of the imp
- * @return imp or null
- */
- public static GenticsImpInterface getImp(String impId) {
- try {
- ImpProvider impProvider = getInstance();
- Object borrowedObject = impProvider.impPool.borrowObject(impId);
-
- if (logger.isInfoEnabled()) {
- logger.info(
- "borrowed imp {" + impId + "}. Active: " + impProvider.impPool.getNumActive(impId) + ", Idle: " + impProvider.impPool.getNumIdle(impId));
- }
- return (GenticsImpInterface) borrowedObject;
- } catch (Exception e) {
- logger.error("Error while fetching imp {" + impId + "}", e);
- return null;
- }
- }
-
- /**
- * static method to return an imp
- * @param imp imp to return
- * @param impId id of the imp
- */
- public static void returnImp(GenticsImpInterface imp, String impId) {
- try {
- ImpProvider impProvider = getInstance();
-
- impProvider.impPool.returnObject(impId, imp);
- if (logger.isInfoEnabled()) {
- logger.info(
- "returned imp {" + impId + "}. Active: " + impProvider.impPool.getNumActive(impId) + ", Idle: " + impProvider.impPool.getNumIdle(impId));
- }
- } catch (Exception e) {
- logger.error("Error while returning imp {" + impId + "} to pool.", e);
- }
- }
-
- /**
- * Get the singleton instance of the imp provider
- * @return imp provider
- */
- protected static ImpProvider getInstance() {
- if (instance == null) {
- instance = new ImpProvider();
- }
- return instance;
- }
-
- /**
- * private constructor for the singleton
- */
- private ImpProvider() {
- // create the pool
- impPool = new GenericKeyedObjectPool(new ImpFactory(), 20, GenericObjectPool.WHEN_EXHAUSTED_GROW, -1, 5, false, false);
- }
-
- /**
- * Internal imp factory
- */
- protected class ImpFactory implements KeyedPoolableObjectFactory {
-
- /*
- * (non-Javadoc)
- * @see org.apache.commons.pool.KeyedPoolableObjectFactory#activateObject(java.lang.Object,
- * java.lang.Object)
- */
- public void activateObject(Object key, Object imp) throws Exception {}
-
- /*
- * (non-Javadoc)
- * @see org.apache.commons.pool.KeyedPoolableObjectFactory#destroyObject(java.lang.Object,
- * java.lang.Object)
- */
- public void destroyObject(Object key, Object imp) throws Exception {}
-
- /*
- * (non-Javadoc)
- * @see org.apache.commons.pool.KeyedPoolableObjectFactory#makeObject(java.lang.Object)
- */
- public Object makeObject(Object key) throws Exception {
- try {
- if (ImpsResolver.VELOIMP.equals(key)) {
- VelocityToolsImp velocityToolsImp = new VelocityToolsImp();
-
- velocityToolsImp.init("velocitytools", new HashMap());
-
- return velocityToolsImp;
- } else if (ImpsResolver.STRINGIMP.equals(key)) {
- GenticsStringFormatter genticsStringFormatter = new GenticsStringFormatter();
-
- genticsStringFormatter.init("genticsstringformatter", new HashMap());
-
- return genticsStringFormatter;
- } else if (ImpsResolver.SORTIMP.equals(key)) {
- SortImp sortImp = new SortImp();
-
- sortImp.init("sorter", new HashMap());
-
- return sortImp;
- } else if (ImpsResolver.LOADERIMP.equals(key)) {
- CMSLoaderImp loaderImp = new CMSLoaderImp();
-
- loaderImp.init("loader", new HashMap());
-
- return loaderImp;
- } else if (ImpsResolver.URLIMP.equals(key)) {
- URLIncludeImp urlIncludeImp = new URLIncludeImp();
-
- urlIncludeImp.init("url", new HashMap());
-
- return urlIncludeImp;
- } else if (ImpsResolver.DATEIMP.equals(key)) {
- CNDateFormatterImp dateformatterImp = new CNDateFormatterImp();
- return dateformatterImp;
- }
- } catch (Exception e) {
- logger.error("Imp {" + key + "} could not be initialized.", e);
- }
- return null;
- }
-
- /*
- * (non-Javadoc)
- * @see org.apache.commons.pool.KeyedPoolableObjectFactory#passivateObject(java.lang.Object,
- * java.lang.Object)
- */
- public void passivateObject(Object key, Object imp) throws Exception {}
-
- /*
- * (non-Javadoc)
- * @see org.apache.commons.pool.KeyedPoolableObjectFactory#validateObject(java.lang.Object,
- * java.lang.Object)
- */
- public boolean validateObject(Object key, Object imp) {
- return true;
- }
- }
- }
-
/**
* Clean the cms resolver (give imps back to pool, etc.)
*/
public void clean() {
- if (impsResolver != null) {
- if (impsResolver.genticsDateFormatter != null) {
- ImpProvider.returnImp(impsResolver.genticsDateFormatter, ImpsResolver.DATEIMP);
- impsResolver.genticsDateFormatter = null;
- }
- if (impsResolver.genticsStringFormatter != null) {
- ImpProvider.returnImp(impsResolver.genticsStringFormatter, ImpsResolver.STRINGIMP);
- impsResolver.genticsStringFormatter = null;
- }
- if (impsResolver.sortImp != null) {
- ImpProvider.returnImp(impsResolver.sortImp, ImpsResolver.SORTIMP);
- impsResolver.sortImp = null;
- }
- if (impsResolver.velocityToolsImp != null) {
- ImpProvider.returnImp(impsResolver.velocityToolsImp, ImpsResolver.VELOIMP);
- impsResolver.velocityToolsImp = null;
- }
- if (impsResolver.loaderImp != null) {
- ImpProvider.returnImp(impsResolver.loaderImp, ImpsResolver.LOADERIMP);
- impsResolver.loaderImp = null;
- }
- if (impsResolver.urlIncludeImp != null) {
- ImpProvider.returnImp(impsResolver.urlIncludeImp, ImpsResolver.URLIMP);
- impsResolver.urlIncludeImp = null;
- }
- impsResolver = null;
- }
+ providedResolvers.values().forEach(ProvidedResolver::clean);
}
}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/CMSResolverService.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/CMSResolverService.java
new file mode 100644
index 0000000000..0ddbcefb27
--- /dev/null
+++ b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/CMSResolverService.java
@@ -0,0 +1,14 @@
+package com.gentics.contentnode.object.parttype;
+
+import java.util.Map;
+
+/**
+ * Interface for services that return additional resolvers
+ */
+public interface CMSResolverService {
+ /**
+ * Get a map of resolvers. The map may be empty but must not be null
+ * @return map of resolvers
+ */
+ Map getResolvers();
+}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/NavigationCompatibilityPartType.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/NavigationCompatibilityPartType.java
deleted file mode 100644
index 9dbd02fdd5..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/NavigationCompatibilityPartType.java
+++ /dev/null
@@ -1,1741 +0,0 @@
-/*
- * @author alexander
- * @date 14.03.2007
- * @version $Id: NavigationCompatibilityPartType.java,v 1.23 2010-09-28 17:01:29 norbert Exp $
- */
-package com.gentics.contentnode.object.parttype;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Vector;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-import com.gentics.api.lib.datasource.Datasource;
-import com.gentics.api.lib.datasource.Datasource.Sorting;
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.api.lib.exception.UnknownPropertyException;
-import com.gentics.api.lib.resolving.PropertyResolver;
-import com.gentics.api.lib.resolving.Resolvable;
-import com.gentics.api.lib.resolving.ResolvableComparator;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionException;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.object.ContentFile;
-import com.gentics.contentnode.object.File;
-import com.gentics.contentnode.object.Folder;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.object.TagmapEntry;
-import com.gentics.contentnode.publish.CnMapPublisher;
-import com.gentics.contentnode.publish.cr.DummyTagmapEntry;
-import com.gentics.contentnode.publish.cr.TagmapEntryRenderer;
-import com.gentics.contentnode.render.RenderableResolvable;
-import com.gentics.contentnode.resolving.StackResolvable;
-import com.gentics.lib.content.GenticsContentAttribute;
-import com.gentics.lib.etc.MiscUtils;
-import com.gentics.lib.etc.StringUtils;
-import com.gentics.lib.log.NodeLogger;
-
-/**
- * This parttype implements the navigation.
- */
-
-public class NavigationCompatibilityPartType extends AbstractVelocityCompatibilityPartType {
-
- /**
- * Static logger
- */
- protected static NodeLogger logger = NodeLogger.getNodeLogger(NavigationCompatibilityPartType.class);
-
- /**
- * Static type code for folders.
- */
- protected static final int TYPE_FOLDER = 10002;
-
- /**
- * Static type code of pages
- */
- protected static final int TYPE_PAGE = 10007;
-
- /**
- * Static type code for folders.
- */
- protected static final int TYPE_FILE = 10008;
-
- /**
- * Property name for folders.
- */
- protected static final String OBJECTS_FOLDERS = "folders";
-
- /**
- * Property name for images.
- */
- protected static final String OBJECTS_IMAGES = "images";
-
- /**
- * Property name for files.
- */
- protected static final String OBJECTS_FILES = "files";
-
- /**
- * Property name for pages.
- */
- protected static final String OBJECTS_PAGES = "pages";
-
- /**
- * Property name for all types.
- */
- protected static final String OBJECTS_ALL = "all";
-
- /**
- * Name of input parameter for startfolder
- */
- protected static final String INPUT_STARTFOLDER = "startfolder";
-
- /**
- * Default value for startfolder
- */
- protected static final String INPUT_STARTFOLDER_DEFAULT = "node.folder";
-
- /**
- * Name of input parameter for template
- */
- public static final String INPUT_TEMPLATE = "templates";
-
- /**
- * Name of input parameter for startfolder
- */
- protected static final String INPUT_SORTBY = "sortby";
-
- /**
- * Default value for startfolder
- */
- protected static final String INPUT_SORTBY_DEFAULT = "name";
-
- /**
- * Name of input parameter for sitemap
- */
- protected static final String INPUT_SITEMAP = "disable_flapping";
-
- /**
- * Default value for sitemap
- */
- protected static final boolean INPUT_SITEMAP_DEFAULT = false;
-
- /**
- * Name of input parameter for disable_fallback
- */
- protected static final String INPUT_DISABLEFALLBACK = "disable_fallback";
-
- /**
- * Default value for disable_fallback
- */
- protected static final boolean INPUT_DISABLEFALLBACK_DEFAULT = false;
-
- /**
- * Name of input parameter for enable_activepath
- */
- protected static final String INPUT_ACTIVEPATH = "enable_activepath";
-
- /**
- * Default value for tagname_hidden
- */
- protected static final boolean INPUT_ACTIVEPATH_DEFAULT = false;
-
- /**
- * Name of input parameter for sortorder
- */
- protected static final String INPUT_SORTORDER = "sortorder";
-
- /**
- * Value of sortorder ascending
- */
- protected static final String INPUT_SORTORDER_ASC = "ASC";
-
- /**
- * Value of sortorder descending
- */
- protected static final String INPUT_SORTORDER_DESC = "DESC";
-
- /**
- * Default value for sortorder
- */
- protected static final String INPUT_SORTORDER_DEFAULT = INPUT_SORTORDER_ASC;
-
- /**
- * Name of input parameter for tagname_sort
- */
- protected static final String INPUT_TAGNAMESORT = "tagname_sort";
-
- /**
- * Default value for tagname_sort
- */
- protected static final String INPUT_TAGNAMESORT_DEFAULT = "navsort";
-
- /**
- * Name of input parameter for tagname_hidden
- */
- protected static final String INPUT_TAGNAMEHIDDEN = "tagname_hidden";
-
- /**
- * Default value for tagname_hidden
- */
- protected static final String INPUT_TAGNAMEHIDDEN_DEFAULT = "navhidden";
-
- /**
- * Name of input parameter for startfolder
- */
- protected static final String INPUT_LANGUAGECODE = "languagecode";
-
- /**
- * Default value for startfolder
- */
- protected static final String INPUT_LANGUAGECODE_DEFAULT = "";
-
- /**
- * Name of input parameter for startpage (of folder)
- */
- protected static final String INPUT_TAGNAME_STARTPAGE = "tagname_startpage";
-
- /**
- * Default value for startpage of folder
- */
- protected static final String INPUT_TAGNAME_STARTPAGE_DEFAULT = "object.startpage";
-
- /**
- * Name of input parameter for objects
- */
- protected static final String INPUT_OBJECTS = "objects";
-
- /**
- * Name of input parameter for disable_hidden
- */
- protected static final String INPUT_DISABLEHIDDEN = "disable_hidden";
-
- /**
- * Default value for disable_hidden
- */
- protected static final boolean INPUT_DISABLEHIDDEN_DEFAULT = false;
-
- /**
- * Name of input parameter for page
- */
- protected static final String INPUT_PAGE = "page";
-
- /**
- * Name of attribute for parent
- */
- protected static final String NAV_PARENT = "parent";
-
- /**
- * Name of attribute for folder of page
- */
- protected static final String NAV_FOLDER = "folder";
-
- /**
- * Name of attribute for translated name
- */
- protected static final String NAV_NAME_LANGUAGE = "object.name_";
-
- /**
- * Name of attribute for translated name
- */
- protected static final String NAV_LANGUAGES = "languageset.pages.";
-
- /**
- * Name of attribute for name
- */
- protected static final String NAV_NAME = "name";
-
- /**
- * Name of attribute for URL
- */
- protected static final String NAV_URL = "url";
-
- /**
- * Name of attribute for ID
- */
- protected static final String NAV_ID = "id";
-
- /**
- * Name of attribute for edit timestamp
- */
- protected static final String NAV_EDITTIMESTAMP = "edittimestamp";
-
- /**
- * Name of attribute for objecttype
- */
- protected static final String NAV_OBJECTTYPE = "ttype";
-
- /**
- * Name of attribute for mother id
- */
- protected static final String NAV_MOTHERID = "mother";
-
- /**
- * Name of attribute for mother id, if the object is not a folder itself
- */
- protected static final String NAV_MOTHERID_NONFOLDER = "folder_id";
-
- /**
- * Name of attribute for language code of page
- */
- protected static final String NAV_LANGUAGECODE = "language.code";
-
- /**
- * Tagmap cache for basic types Page, Folder and File Structure: keys are
- * the objecttypes (as instances of Integer), values are maps of mapname
- * (String) -> {@link CnMapPublisher#TagmapEntry}
- */
- protected Map tagmapCache = new HashMap(3);
-
- /**
- * Render the navigation. Gets all needed input parameters and starts
- * rendering at startpage. Parse old-style templates from XML.
- * @throws NodeException
- */
- public String render() throws NodeException {
- logger.info("Start rendering navigation.");
-
- buildTagmapCache();
-
- ConfigObject config = getInitParameters();
- String navigation = renderObject(new RenderableResolvable(config.startfolder), -1, config);
-
- logger.info("End rendering navigation.");
- if (logger.isDebugEnabled()) {
- logger.debug("Navigation: " + navigation);
- }
-
- // we don't need that cache anymore
- tagmapCache.clear();
-
- return navigation;
- }
-
- /**
- * cache the tagmap to a hashmap
- */
- protected void buildTagmapCache() {
- Transaction t;
-
- // build basic cache structure
- tagmapCache.put(new Integer(Page.TYPE_PAGE), new HashMap());
- tagmapCache.put(new Integer(Folder.TYPE_FOLDER), new HashMap());
- tagmapCache.put(new Integer(File.TYPE_FILE), new HashMap());
-
- try {
- t = TransactionManager.getCurrentTransaction();
-
- PreparedStatement stmt = null;
- ResultSet rs = null;
-
- try {
- com.gentics.contentnode.object.Node node = getNodeOfRenderedObject();
-
- stmt = t.prepareStatement(
- "SELECT tagname, mapname, object, objtype, attributetype FROM tagmap LEFT JOIN node ON tagmap.contentrepository_id = node.contentrepository_id WHERE object IN ("
- + Page.TYPE_PAGE + ", " + Folder.TYPE_FOLDER + ", " + File.TYPE_FILE + ") AND node.id = ? ORDER BY object ASC");
- stmt.setObject(1, node != null ? node.getId() : "0");
- rs = stmt.executeQuery();
-
- while (rs.next()) {
- ((HashMap) tagmapCache.get(rs.getObject("object"))).put(rs.getObject("mapname"),
- new DummyTagmapEntry(rs.getInt("object"), rs.getString("tagname"), rs.getString("mapname"), rs.getInt("attributetype"), rs.getInt("objType")));
- }
- } catch (Exception e) {
- logger.error("could not load tagmap entries", e);
- } finally {
- t.closeResultSet(rs);
- t.closeStatement(stmt);
- }
- } catch (TransactionException e1) {
- logger.error("unable to get current transaction", e1);
- }
- }
-
- /**
- * Read all needed init parameters using the resolve() method. Populates
- * instance variables.
- * @throws NodeException
- */
- protected ConfigObject getInitParameters() throws NodeException {
-
- logger.debug("Start reading configuration.");
-
- // create new config object to store configuration parameters
- // can't use instance variables since same instance might render
- // different navigations
- ConfigObject config = new ConfigObject();
-
- // get startfolder from input parameters
- Object tmpStartfolder = resolve(INPUT_STARTFOLDER);
-
- if (tmpStartfolder instanceof Resolvable) {
- config.startfolder = (Resolvable) tmpStartfolder;
- }
-
- // if no startfolder specified, use default node.folder
- // if (config.startfolder == null) {
- // config.startfolder = (Resolvable) resolve(INPUT_STARTFOLDER_DEFAULT);
- // }
-
- // if still no startfolder, something has gone wrong
- if (config.startfolder == null) {
- logger.error("No startfolder set and couldn't find default start folder.");
- throw new NodeException("No startfolder set and couldn't find default start folder.");
- }
-
- // get template
- config.template = ObjectTransformer.getString(resolve(INPUT_TEMPLATE), "");
- if ("".equals(config.template)) {
- logger.error("No templates found.");
- throw new NodeException("No templates found.");
- }
-
- // get sortby
- // default to "name"
- config.sortBy = ObjectTransformer.getString(resolve(INPUT_SORTBY), INPUT_SORTBY_DEFAULT);
- if (config.sortBy == null || "".equals(config.sortBy)) {
- config.sortBy = INPUT_SORTBY_DEFAULT;
- }
-
- // get sortorder
- // default to "ASC"
- String sortOrder = ObjectTransformer.getString(resolve(INPUT_SORTORDER), INPUT_SORTORDER_DEFAULT);
-
- config.sortOrder = getSortOrder(sortOrder);
-
- // get tagname_sort
- // default to "navsort"
- config.tagnameSort = ObjectTransformer.getString(resolve(INPUT_TAGNAMESORT), INPUT_TAGNAMESORT_DEFAULT);
- if (config.tagnameSort == null || "".equals(config.tagnameSort)) {
- config.tagnameSort = INPUT_TAGNAMESORT_DEFAULT;
- }
-
- // get sitemap flag
- // default to false
- config.sitemap = ObjectTransformer.getBoolean(resolve(INPUT_SITEMAP), INPUT_SITEMAP_DEFAULT);
-
- // get enable_activepath flag
- // default to false
- config.activepath = ObjectTransformer.getBoolean(resolve(INPUT_ACTIVEPATH), INPUT_ACTIVEPATH_DEFAULT);
-
- // get tagname_hidden
- // default to "navhidden"
- config.tagnameHidden = ObjectTransformer.getString(resolve(INPUT_TAGNAMEHIDDEN), INPUT_TAGNAMEHIDDEN_DEFAULT);
- if (config.tagnameHidden == null || "".equals(config.tagnameHidden)) {
- config.tagnameHidden = INPUT_TAGNAMEHIDDEN_DEFAULT;
- }
-
- // get disable_fallback
- config.disableFallback = ObjectTransformer.getBoolean(resolve(INPUT_DISABLEFALLBACK), INPUT_DISABLEFALLBACK_DEFAULT);
-
- // get tagname_startpage
- config.tagnameStartpage = ObjectTransformer.getString(resolve(INPUT_TAGNAME_STARTPAGE), INPUT_TAGNAME_STARTPAGE_DEFAULT);
- if (config.tagnameStartpage == null || "".equals(config.tagnameStartpage)) {
- config.tagnameStartpage = INPUT_TAGNAME_STARTPAGE_DEFAULT;
- }
-
- // get objects to be displayed
- // default to pages, folders, files
- String tmpObjects = ObjectTransformer.getString(resolve(INPUT_OBJECTS), "");
-
- config.objects = new HashSet();
- if (tmpObjects == null || "".equals(tmpObjects)) {
- config.objects.add(OBJECTS_PAGES);
- config.objects.add(OBJECTS_FOLDERS);
- config.objects.add(OBJECTS_FILES);
- } else {
- String[] tObjects = tmpObjects.split(",");
-
- for (int i = 0; i < tObjects.length; i++) {
- if (OBJECTS_FILES.equals(tObjects[i].toLowerCase())) {
- config.objects.add(OBJECTS_FILES);
- } else if (OBJECTS_FOLDERS.equals(tObjects[i].toLowerCase())) {
- config.objects.add(OBJECTS_FOLDERS);
- } else if (OBJECTS_IMAGES.equals(tObjects[i].toLowerCase())) {
- config.objects.add(OBJECTS_IMAGES);
- } else if (OBJECTS_PAGES.equals(tObjects[i].toLowerCase())) {
- config.objects.add(OBJECTS_PAGES);
- } else if (OBJECTS_ALL.equals(tObjects[i].toLowerCase())) {
- config.objects.add(OBJECTS_ALL);
- }
- }
- }
-
- // get disable_hidden
- config.disableHidden = ObjectTransformer.getBoolean(resolve(INPUT_DISABLEHIDDEN), INPUT_DISABLEHIDDEN_DEFAULT);
-
- // get current page
- Object tmpCurrentPage = resolve(INPUT_PAGE);
-
- if (tmpCurrentPage instanceof Resolvable) {
- config.currentPage = (Resolvable) tmpCurrentPage;
- } else {
- logger.warn("Current page not found.");
- }
-
- // get languagecode
- // default to language code of current page
- config.languagecode = ObjectTransformer.getString(resolve(INPUT_LANGUAGECODE), INPUT_LANGUAGECODE_DEFAULT);
- if (config.languagecode == null || "".equals(config.languagecode)) {
- try {
- config.languagecode = ObjectTransformer.getString(PropertyResolver.resolve(config.currentPage, NAV_LANGUAGECODE), INPUT_LANGUAGECODE_DEFAULT);
- } catch (UnknownPropertyException upe) {
- logger.error("Language of current page could not be resolved.");
- }
- }
-
- // get path from current page to startpage and add objects to hashset
- config.path = new HashSet();
- Resolvable pathitem = config.currentPage;
-
- while (pathitem != null) {
- config.path.add(pathitem);
- Object parent = pathitem.get(NAV_PARENT);
-
- if (logger.isDebugEnabled()) {
- logger.debug("resolving path to startpage: currentPage {" + config.currentPage + "} pathitem {" + pathitem + "} parent {" + parent + "}");
- }
- if (parent instanceof Resolvable) {
- pathitem = (Resolvable) parent;
- } else {
- parent = pathitem.get(NAV_FOLDER);
- // folders can resolve themselves (folder.folder) - so check if
- // the
- // resolved item is equal to the old item to avoid endless
- // loops.
- if (parent instanceof Resolvable && !parent.equals(pathitem)) {
- pathitem = (Resolvable) parent;
- } else {
- pathitem = null;
- }
- }
- }
-
- // parse old style templates
- config.templates = parseTemplates(config.template);
-
- if (logger.isDebugEnabled()) {
- logger.debug("End reading configuration." + config);
- }
-
- return config;
- }
-
- /**
- * Parse old-style XML templates and transform to Velocity templates.
- * @param inputTemplate All templates as one XML document.
- * @return A HashMap containing all transformed templates, hashed by level
- * and type.
- * @throws NodeException If an exception occured during XML parsing.
- */
- protected HashMap parseTemplates(String inputTemplate) throws NodeException {
-
- logger.debug("Start parsing templates.");
-
- // add surrounding block to make valid XML
- inputTemplate = "" + inputTemplate + " ";
-
- // try to get parsed templates from portal cache
- Object tmpTemplates = getCachedObject(inputTemplate);
-
- if (tmpTemplates instanceof HashMap) {
- logger.debug("Templates found in cache.");
- return (HashMap) tmpTemplates;
- }
-
- logger.debug("Templates not found in cache, start parsing from XML.");
-
- // templates not cached, create new
- HashMap templates = new HashMap();
-
- try {
- // Read XML input string into a DOM document
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- DocumentBuilder db = dbf.newDocumentBuilder();
- Document document = db.parse(new InputSource(new StringReader(inputTemplate)));
-
- // loop over all templates
- NodeList nodeTemplates = document.getElementsByTagName("template");
- int maxLevel = 0;
-
- for (int i = 0; i < nodeTemplates.getLength(); i++) {
-
- // read a template
- Node node = nodeTemplates.item(i);
-
- // get template level
- NamedNodeMap nodeAttributes = node.getAttributes();
- Node nodeLevel = nodeAttributes.getNamedItem("level");
- Integer templateLevel = Integer.valueOf(nodeLevel.getNodeValue());
-
- if (templateLevel.intValue() > maxLevel) {
- maxLevel = templateLevel.intValue();
- }
-
- // read subtemplates
- NodeList nodeSubTemplates = node.getChildNodes();
- HashMap subTemplates = new HashMap();
-
- for (int j = 0; j < nodeSubTemplates.getLength(); j++) {
-
- // read template
- Node nodeSubTemplate = nodeSubTemplates.item(j);
-
- // check to see if node is an element
- if (nodeSubTemplate.getNodeType() != Node.ELEMENT_NODE) {
- continue;
- }
-
- String elementName = nodeSubTemplate.getNodeName();
- String elementValue = getTemplateFromNode(nodeSubTemplate);
-
- // when the subtemplate is the "childs" template, but does
- // not contain , we replace it by the fake
- // childs template (same behaviour as in 3.6, fixes part of
- // RT#21705)
- if ("childs".equals(elementName) && elementValue.indexOf("") < 0) {
- Template tmp = getTemplateFromString("$nav.childs");
-
- subTemplates.put(elementName, tmp);
- } else {
- // put into hashmap to store in cache
- Template tmp = getTemplateFromString(convertVelocity(elementValue));
-
- subTemplates.put(elementName, tmp);
- }
- }
-
- // Append template for child elements. (RT #9581)
- // Either use a template if it exists, otherwise
- // use fake template since navigation relies on $nav.childs
- // to do the recursion.
- String templateName = "childs";
-
- if (!subTemplates.containsKey(templateName)) {
- Template tmp = getTemplateFromString("$nav.childs");
-
- subTemplates.put(templateName, tmp);
- }
-
- templates.put(templateLevel, subTemplates);
-
- }
-
- // add "childs" template for level -1 (root level)
- // needed since we do all recursion using $nav.childs, we need
- // an entry point
- String templateName = "childs";
- Template tmp = getTemplateFromString("$nav.childs");
- HashMap rootTemplate = new HashMap();
-
- rootTemplate.put(templateName, tmp);
- templates.put(new Integer(-1), rootTemplate);
-
- // put parsed templates into cache
- putObjectIntoCache(inputTemplate, templates);
-
- logger.debug("End parsing templates.");
-
- // return templates
- return templates;
-
- } catch (ParserConfigurationException pce) {
- logger.error("ParserConfigurationException while parsing templates. " + pce.getMessage());
- throw new NodeException("ParserConfigurationException while parsing templates. " + pce.getMessage(), pce);
- } catch (IOException ioe) {
- logger.error("IOException while parsing templates. " + ioe.getMessage());
- throw new NodeException("IOException while parsing templates. " + ioe.getMessage(), ioe);
- } catch (SAXException saxe) {
- logger.error("SAXException while parsing templates. " + saxe.getMessage());
- throw new NodeException("SAXException while parsing templates. " + saxe.getMessage(), saxe);
- } catch (Exception e) {
- logger.error("Exception while parsing templates. " + e.getMessage());
- throw new NodeException("Exception while parsing templates. " + e.getMessage(), e);
- }
- }
-
- /**
- * Replace all old-style tags by Velocity $nav.xxx statements.
- * @param input The old-style template.
- * @return A Velocity-fied template.
- */
- protected String convertVelocity(String input) {
- return input.replaceAll("", "\\${nav.$1}");
- }
-
- /**
- * Render a resovable object.
- * @param object The resovable object that should be rendered.
- * @param level The current level of the object (startpage has level -1, as
- * only sub-elements of startpage are shown).
- * @return The rendered string containing this and all sub-elements.
- * @throws NodeException
- */
- protected String renderObject(Resolvable object, int level, ConfigObject config) throws NodeException {
-
- if (logger.isDebugEnabled()) {
- logger.debug("Start rendering object: " + object.toString());
- }
-
- // create the corresponding nav object
- NavObject nav = new NavObject(object, level, config);
-
- // create Velocity context, populate
- VelocityContext context = new VelocityContext(createContext(true));
-
- context.put("nav", nav);
-
- // TODO initial size
- StringWriter outwriter = new StringWriter();
-
- // fetch template for object
- String type = "";
-
- if (nav.isCurrentpage() || (config.activepath && nav.isInpath())) {
- type = "selected";
- } else if (!"".equals(nav.getUrl())) {
- type = "unselectedlinked";
- } else {
- type = "unselectednotlinked";
- }
-
- String objecttype = "";
-
- if (nav.getType() == TYPE_FOLDER) {
- objecttype = "_folder";
- } else if (nav.getType() == TYPE_FILE) {
- objecttype = "_file";
- }
-
- try {
- Template template = getTemplate(type, objecttype, level, true, config);
-
- if (template != null) {
- logger.debug("Merging main template.");
- template.merge(context, outwriter);
- } else {
- logger.debug("No template found, skipping.");
- }
-
- // always render nav childs template if element is open to be
- // compatible to php
- if (nav.isOpen()) {
- Template childTemplate = getTemplate("childs", "", level, true, config);
-
- if (childTemplate != null) {
- logger.debug("Merging child template.");
- childTemplate.merge(context, outwriter);
- } else {
- logger.debug("No child template found, skipping.");
- }
- }
- } catch (ParseErrorException pee) {
- logger.error("ParseErrorException while rendering object. " + pee.getMessage());
- throw new NodeException("ParseErrorException while rendering object. " + pee.getMessage(), pee);
- } catch (ResourceNotFoundException rnfe) {
- logger.error("ResourceNotFoundException while rendering object. " + rnfe.getMessage());
- throw new NodeException("ResourceNotFoundException while rendering object. " + rnfe.getMessage(), rnfe);
- } catch (MethodInvocationException mie) {
- logger.error("MethodInvocationException while rendering object. " + mie.getMessage());
- throw new NodeException("MethodInvocationException while rendering object. " + mie.getMessage(), mie);
- } catch (IOException ioe) {
- logger.error("IOException while rendering object. " + ioe.getMessage());
- throw new NodeException("IOException while rendering object. " + ioe.getMessage(), ioe);
- } catch (Exception e) {
- logger.error("Exception while rendering object. " + e.getMessage());
- throw new NodeException("Exception while rendering object. " + e.getMessage(), e);
- }
-
- logger.debug("End rendering object.");
-
- return outwriter.toString();
- }
-
- /**
- * Get template for specified object and level.
- * @param type Type of template to return (selected, unselectedlinked,
- * unselectednotlinked)
- * @param objecttype Type of object to allow specific templates for folders
- * and files.
- * @param level The template level.
- * @param fallback True if level should gradually be decremented until a
- * template is found, false if not.
- * @return The already to Velocity converted template.
- */
- protected Template getTemplate(String type, String objecttype, int level, boolean fallback,
- ConfigObject config) {
-
- if (logger.isDebugEnabled()) {
- logger.debug("Get template from map. type = " + type + ". objecttype = " + objecttype + ". level = " + level + ". fallback = " + fallback);
- }
-
- // check level. exit if level < -1 to prevent infinite loop
- if (level < -1) {
- logger.debug("Level < -1, aborting search for template.");
- return null;
- }
-
- // try to get right template level
- Object tmpSubTemplates = config.templates.get(new Integer(level));
-
- if (tmpSubTemplates instanceof HashMap) {
-
- HashMap subTemplates = (HashMap) tmpSubTemplates;
-
- // get specific template
- Object template = subTemplates.get(type + objecttype);
-
- if (template instanceof Template) {
- logger.debug("Specific template found.");
- return (Template) template;
- }
-
- // no specific template found, get generic template
- template = subTemplates.get(type);
- if (template instanceof Template) {
- logger.debug("Generic template found.");
- return (Template) template;
- }
-
- logger.debug("No template found, but template node for level exists. Returning null.");
- return null;
-
- // no template found for this level, try to step up
- } else {
- if (fallback) {
- logger.debug("No template found, fallback to upper level.");
- return getTemplate(type, objecttype, level - 1, fallback, config);
- } else {
- logger.debug("No template found, fallback disabled.");
- return null;
- }
- }
- }
-
- /**
- * Get the Node of the rendered root object or null
- * @return Node or null
- * @throws NodeException
- */
- protected com.gentics.contentnode.object.Node getNodeOfRenderedObject() throws NodeException {
- com.gentics.contentnode.object.Node node = null;
-
- Transaction t = TransactionManager.getCurrentTransaction();
- StackResolvable renderedRootObject = t.getRenderType().getRenderedRootObject();
-
- if (renderedRootObject instanceof Page) {
- node = ((Page) renderedRootObject).getFolder().getNode();
- } else if (renderedRootObject instanceof Folder) {
- node = ((Folder) renderedRootObject).getNode();
- } else if (renderedRootObject instanceof ContentFile) {
- node = ((ContentFile) renderedRootObject).getFolder().getNode();
- }
-
- return node;
- }
-
- /**
- * Decode sort order from String to int
- * @param sortOrder String representing sortorder ("asc", "desc")
- * @return int representing sortorder
- */
- protected int getSortOrder(String sortOrder) {
- if (INPUT_SORTORDER_ASC.equalsIgnoreCase(sortOrder)) {
- return Datasource.SORTORDER_ASC;
- } else if (INPUT_SORTORDER_DESC.equalsIgnoreCase(sortOrder)) {
- return Datasource.SORTORDER_DESC;
- } else {
- return Datasource.SORTORDER_ASC;
- }
- }
-
- /**
- * The object representing a navigation element.
- * @author alexander
- */
- public class NavObject {
-
- /**
- * The level of this element.
- */
- protected int level;
-
- /**
- * The resolvable object this navobject renders.
- */
- protected Resolvable object;
-
- /**
- * The name of the attribute by which children of this element are
- * sorted.
- */
- protected String folderSortBy;
-
- /**
- * The order by which children of this element are sorted.
- */
- protected int folderSortOrder;
-
- /**
- * The cached result of the hasItems() method.
- */
- protected boolean hasItems;
-
- /**
- * If hasItems contains a valid result.
- */
- protected boolean hasItemsCache;
-
- /**
- * The cached result of the isOpen() method.
- */
- protected boolean isOpen;
-
- /**
- * If isOpen contains a valid result.
- */
- protected boolean isOpenCache;
-
- /**
- * Store configuration parameters
- */
- protected ConfigObject config;
-
- /**
- * Constructor of the Navigation Object.
- * @param object The resolvable object that is rendered.
- * @param level The level of the object.
- */
- public NavObject(Resolvable object, int level, ConfigObject config) {
-
- this.object = object;
- this.level = level;
- this.config = config;
-
- this.isOpen = false;
- this.isOpenCache = false;
-
- this.folderSortBy = config.sortBy;
- this.folderSortOrder = config.sortOrder;
-
- this.hasItems = false;
- this.hasItemsCache = false;
- }
-
- /**
- * Check if this object has a specific sorting set as a property. Decode
- * sorting as sortorder;sortby. If it exists, set as sortorder for this
- * folder.
- */
- protected void checkSorting() {
- Object tmpSorting = resolveTagmapProperty(getObject(), config.tagnameSort);
- String sorting = ObjectTransformer.getString(tmpSorting, "");
-
- if (sorting == null || "".equals(sorting)) {
- folderSortBy = config.sortBy;
- folderSortOrder = config.sortOrder;
- } else {
- String[] sort = sorting.split(";");
-
- if (sort.length != 2) {
- folderSortBy = config.sortBy;
- folderSortOrder = config.sortOrder;
- } else {
- folderSortOrder = getSortOrder(sort[0]);
- folderSortBy = sort[1];
- if (ObjectTransformer.isEmpty(folderSortBy)) {
- folderSortBy = config.sortBy;
- }
- }
- }
- if (logger.isDebugEnabled()) {
- logger.debug(
- "sorting from tagname is {" + sorting + "}, setting folderSortBy to {" + folderSortBy + "} and folderSortOrder to {" + folderSortOrder + "}");
- }
- }
-
- /**
- * @return The resolvable object that is rendered.
- */
- public Resolvable getObject() {
- return object;
- }
-
- /**
- * @return Level of the element (startfolder has level -1).
- */
- public int getLevel() {
- return level;
- }
-
- /**
- * @return Name of the element.
- */
- public String getName() {
-
- String nameLanguage = "";
-
- if (getType() == TYPE_FOLDER && !"".equals(config.languagecode)) {
-
- try {
- nameLanguage = ObjectTransformer.getString(PropertyResolver.resolve(object, NAV_NAME_LANGUAGE + config.languagecode), "");
- } catch (UnknownPropertyException upe) {
- nameLanguage = "";
- }
-
- if ((nameLanguage == null || "".equals(nameLanguage)) && config.disableFallback) {
- return "";
- }
- }
-
- if (!"".equals(nameLanguage)) {
- return nameLanguage;
- }
-
- // fallback to default language
- return ObjectTransformer.getString(object.get(NAV_NAME), "");
- }
-
- /**
- * @return URL of element.
- */
- public String getUrl() {
- // try to get the language specific startpage
- Resolvable startpage = getLanguageStartpage();
-
- if (startpage != null) {
- // when the page is offline, simply render empty string
- if (!ObjectTransformer.getBoolean(startpage.get("online"), false)) {
- logger.debug(" startpage not online");
- return "";
- }
- if (logger.isDebugEnabled()) {
- logger.debug(" returning url: {" + ObjectTransformer.getString(startpage.get(NAV_URL), "") + "}");
- }
- return ObjectTransformer.getString(startpage.get(NAV_URL), "");
- } else {
- // no startpage found, this means that object.startpage does not
- // point to a page
- // in that case, simply render object.startpage.url
- try {
- if (logger.isDebugEnabled()) {
- logger.debug(
- " resolving {" + config.tagnameStartpage + "}: {"
- + ObjectTransformer.getString(PropertyResolver.resolve(object, config.tagnameStartpage + ".url"), "") + "}");
- }
- // first try to resolve the URL ...
- String url = ObjectTransformer.getString(PropertyResolver.resolve(object, config.tagnameStartpage + ".url"), null);
-
- if (url != null) {
- return url;
- }
-
- // now try to resolve through the tagmap
- Object obj = resolveTagmapProperty(object, config.tagnameStartpage);
-
- if (obj instanceof Resolvable) {
- // we resolved the startpage (i guess ?)
- obj = ((Resolvable) obj).get(NAV_URL);
- }
- return ObjectTransformer.getString(obj, "");
- } catch (UnknownPropertyException upe) {
- return "";
- }
- }
- }
-
- /**
- * @return Resolvable representing startpage of object
- */
- protected Resolvable getStartpage() {
- // if not page, try to get startpage
- if (getType() != TYPE_PAGE) {
-
- Object startpage = null;
-
- try {
- if (logger.isDebugEnabled()) {
- logger.debug("resolving {" + config.tagnameStartpage + ".url.target" + "}");
- }
- startpage = PropertyResolver.resolve(object, config.tagnameStartpage + ".url.target");
- } catch (UnknownPropertyException upe) {
- if (logger.isDebugEnabled()) {
- logger.debug("No startpage found for folder: " + object);
- }
- startpage = null;
- }
-
- if (startpage == null) {
- // try to resolve startpage through tagmap ..
- startpage = resolveTagmapProperty(object, config.tagnameStartpage);
- }
-
- if (startpage instanceof Resolvable) {
- return (Resolvable) startpage;
- }
- return null;
- }
-
- // if page, return itself
- return object;
- }
-
- /**
- * Get language-variant of startpage.
- * @return The language-variant of the startpage.
- */
- protected Resolvable getLanguageStartpage() {
-
- Resolvable startpage = getStartpage();
-
- if (startpage == null) {
- return null;
- }
-
- if (StringUtils.isEmpty(config.languagecode)) {
- return startpage;
- }
-
- Object page = null;
-
- try {
- page = PropertyResolver.resolve(startpage, NAV_LANGUAGES + config.languagecode);
- } catch (UnknownPropertyException upe) {
- page = null;
- }
-
- if (page instanceof Resolvable) {
- return (Resolvable) page;
- }
-
- return startpage;
- }
-
- /**
- * @return The ID of the element.
- */
- public Object getId() {
- return object.get(NAV_ID);
- }
-
- /**
- * @return Update timestamp of element.
- */
- public int getUpdate() {
- return ObjectTransformer.getInt(object.get(NAV_EDITTIMESTAMP), 0);
- }
-
- /**
- * @return Type of element (e.g. 10002 == folder).
- */
- public int getType() {
- return ObjectTransformer.getInt(object.get(NAV_OBJECTTYPE), 0);
- }
-
- /**
- * @return "" if object property is not active, "0" if element is not
- * hidden and "1" if element is hidden.
- */
- public String getHidden() {
- try {
- return ObjectTransformer.getString(PropertyResolver.resolve(object, "object." + config.tagnameHidden), "");
- } catch (UnknownPropertyException upe) {
- return "";
- }
- }
-
- /**
- * @param element The resolvable for which the hidden attribute should
- * be resolved.
- * @return True if the element is hidden from navigation, false
- * otherwise.
- */
- protected boolean getHidden(Resolvable element) {
- try {
- return ObjectTransformer.getBoolean(PropertyResolver.resolve(element, "object." + config.tagnameHidden), false);
- } catch (UnknownPropertyException upe) {
- return false;
- }
- }
-
- /**
- * @return Id of parent element.
- */
- public Object getMotherid() {
- return "10002." + (objectIsFolder() ? object.get(NAV_MOTHERID) : object.get(NAV_MOTHERID_NONFOLDER));
- }
-
- /**
- * Return true when the navobject is a folder, false if not
- * @return true for folders, false for other objects
- */
- protected boolean objectIsFolder() {
- Object tmpType = getObject().get(NAV_OBJECTTYPE);
-
- return ObjectTransformer.getInt(tmpType, 0) == TYPE_FOLDER;
- }
-
- /**
- * Check to see if this folder should be opened in the navigation. Cache
- * to speed up following calls.
- * @return If folder is open.
- */
- protected boolean isOpen() {
-
- if (isOpenCache) {
- return isOpen;
- }
-
- boolean open = false;
- // get object type for this object
- Object tmpType = getObject().get(NAV_OBJECTTYPE);
- int type = ObjectTransformer.getInt(tmpType, 0);
-
- // only folders can have sub items
- if (type == TYPE_FOLDER) {
- open = isInpath() || config.sitemap || config.startfolder.equals(getObject());
- }
-
- isOpenCache = true;
- isOpen = open;
- return open;
- }
-
- /**
- * Check to see if this element is in the path between the current page
- * and the startpage
- * @return If this element is in the path.
- */
- protected boolean isInpath() {
- return config.path.contains(getObject());
- }
-
- /**
- * Check to see if this element is the current page.
- * @return If this element is the current page.
- */
- protected boolean isCurrentpage() {
- if (config.currentPage != null) {
- return config.currentPage.equals(getObject());
- } else {
- return false;
- }
- }
-
- /**
- * Checks any child elements that are included in objects and are
- * visible for the navigation. Cache the result to speed up following
- * calls.
- * @return If the element has child elements.
- */
- protected boolean hasItems() {
- // check cache to see if we already calculated hasItems
- if (hasItemsCache) {
- return hasItems;
- }
-
- // only open elements have items
- if (!isOpen()) {
- return false;
- }
-
- // get object type for this object
- Object tmpType = object.get(NAV_OBJECTTYPE);
- int type = ObjectTransformer.getInt(tmpType, 0);
-
- // only folders can have sub items
- if (type != TYPE_FOLDER) {
- return false;
- }
-
- // check if object contains pages
- if (config.objects.contains(OBJECTS_PAGES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpPages = object.get(OBJECTS_PAGES);
-
- if (tmpPages instanceof Collection) {
- Collection pagesList = (Collection) tmpPages;
- Iterator it = pagesList.iterator();
-
- while (it.hasNext()) {
- Object tmpPage = it.next();
-
- if (tmpPage instanceof Resolvable) {
- Resolvable page = (Resolvable) tmpPage;
- boolean hidden = getHidden(page);
-
- String languageCode = "";
-
- try {
- languageCode = ObjectTransformer.getString(PropertyResolver.resolve(page, NAV_LANGUAGECODE), "");
- } catch (UnknownPropertyException upe) {
- languageCode = "";
- }
-
- // exit loop if page is not published
- boolean online = ((Boolean) page.get("online")).booleanValue();
-
- if (!online) {
- continue;
- }
-
- if ((!hidden || config.disableHidden) && (config.currentPage == null || config.languagecode.equals(languageCode))) {
- hasItems = true;
- hasItemsCache = true;
- return true;
- }
- }
- }
- }
- }
-
- // check if object contains folders
- if (config.objects.contains(OBJECTS_FOLDERS) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpFolders = object.get(OBJECTS_FOLDERS);
-
- if (tmpFolders instanceof Collection) {
- Collection foldersList = (Collection) tmpFolders;
- Iterator it = foldersList.iterator();
-
- while (it.hasNext()) {
- Object tmpFolder = it.next();
-
- if (tmpFolder instanceof Resolvable) {
- Resolvable folder = (Resolvable) tmpFolder;
- boolean hidden = getHidden(folder);
-
- if (!hidden || config.disableHidden) {
- hasItems = true;
- hasItemsCache = true;
- return true;
- }
- }
- }
- }
- }
-
- // check if object contains files
- // note that files and images appear to be the same to xnlnav
- if (config.objects.contains(OBJECTS_FILES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpFiles = object.get(OBJECTS_FILES);
-
- if (tmpFiles instanceof Collection) {
- Collection filesList = (Collection) tmpFiles;
- Iterator it = filesList.iterator();
-
- while (it.hasNext()) {
- Object tmpFile = it.next();
-
- if (tmpFile instanceof Resolvable) {
- Resolvable file = (Resolvable) tmpFile;
- boolean hidden = getHidden(file);
-
- if (!hidden || config.disableHidden) {
- hasItems = true;
- hasItemsCache = true;
- return true;
- }
- }
- }
- }
- Object tmpImages = object.get(OBJECTS_IMAGES);
-
- if (tmpImages instanceof Collection) {
- Collection imagesList = (Collection) tmpImages;
- Iterator it = imagesList.iterator();
-
- while (it.hasNext()) {
- Object tmpImage = it.next();
-
- if (tmpImage instanceof Resolvable) {
- Resolvable image = (Resolvable) tmpImage;
- boolean hidden = getHidden(image);
-
- if (!hidden || config.disableHidden) {
- hasItems = true;
- hasItemsCache = true;
- return true;
- }
- }
- }
- }
- }
-
- // neither files, folders, images, pages found, folder is empty
- hasItems = false;
- hasItemsCache = true;
-
- return false;
- }
-
- /**
- * Render any child elements this element has.
- * @return The rendered output for all child elements.
- * @throws NodeException If rendering fails.
- */
- public String getChilds() throws NodeException {
- // there is an unexpected null pointer exception hidden in here
- // somewhere. Unfortunately, Velocity will intercept the exception
- // and throw a different one by itself, which doesn't include the
- // line number where the NPE occurred, so we have to catch and log
- // the exception here.
- try {
- // check if node is open
- if (!isOpen()) {
- return "";
- }
-
- if (logger.isDebugEnabled()) {
- logger.debug("Get all children for folder: " + getObject().toString());
- }
-
- // TODO initial size for stringbuffer
- StringWriter outputWriter = new StringWriter();
-
- checkSorting();
-
- // merge all children
- // create new vector to avoid unmodifiable singleton lists
- Vector children = new Vector();
-
- // get folders
- if (config.objects.contains(OBJECTS_FOLDERS) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpFolders = getObject().get(OBJECTS_FOLDERS);
-
- if (tmpFolders instanceof Collection) {
- children.addAll((Collection) tmpFolders);
- }
- }
-
- // get pages
- if (config.objects.contains(OBJECTS_PAGES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpPages = getObject().get(OBJECTS_PAGES);
-
- if (tmpPages instanceof Collection) {
- for (Iterator pageIt = ((Collection) tmpPages).iterator(); pageIt.hasNext();) {
- RenderableResolvable tmpPage = (RenderableResolvable) pageIt.next();
- boolean online = ((Boolean) tmpPage.get("online")).booleanValue();
-
- if (online) {
- children.add(tmpPage);
- }
- }
-
- }
- }
-
- // get files
- if (config.objects.contains(OBJECTS_FILES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpFiles = getObject().get(OBJECTS_FILES);
-
- if (tmpFiles instanceof Collection) {
- children.addAll((Collection) tmpFiles);
- }
- Object tmpImages = getObject().get(OBJECTS_IMAGES);
-
- if (tmpImages instanceof Collection) {
- children.addAll((Collection) tmpImages);
- }
- }
-
- if (logger.isDebugEnabled()) {
- logger.debug("Children for folder " + getObject().toString() + ": " + children.toString());
- }
-
- // Collections.sort(children, new ResolvableComparator(folderSortBy,
- // folderSortOrder, false));
- Collections.sort(children, new ResolvableComparator(folderSortBy, folderSortOrder, false) {
-
- /**
- * Compare the given resolvables with the given sorting setting
- * @param r1 first resolvable
- * @param r2 second resolvable
- * @param sorting sorting
- * @return -1 if r1 is "smaller", 1 if r1 is "greater" or 0 if
- * the objects are equal
- */
- protected int compare(Resolvable r1, Resolvable r2, Sorting sorting) {
-
- // switch resolvables if we sort descending ..
- switch (sorting.getSortOrder()) {
- case Datasource.SORTORDER_ASC:
- break;
-
- case Datasource.SORTORDER_DESC:
- Resolvable tmp = r2;
-
- r2 = r1;
- r1 = tmp;
- break;
-
- default:
- return 0;
- }
-
- Object value1 = resolveTagmapProperty(r1, sorting.getColumnName());
- Object value2 = resolveTagmapProperty(r2, sorting.getColumnName());
-
- int c = MiscUtils.compareObjects(value1, value2, caseSensitive);
-
- // If it is the same for the selected property, sort by "name"
- if (c == 0) {
- value1 = resolveTagmapProperty(r1, "name");
- value2 = resolveTagmapProperty(r2, "name");
- c = MiscUtils.compareObjects(value1, value2, caseSensitive);
- }
-
- return c;
- }
- });
-
- Iterator it = children.iterator();
-
- while (it.hasNext()) {
- Object tmpChild = it.next();
-
- if (tmpChild instanceof Resolvable) {
- Resolvable child = (Resolvable) tmpChild;
- boolean hidden = getHidden(child);
-
- // skip hidden items
- if (hidden && !config.disableHidden) {
- continue;
- }
-
- // skip pages in other languages
- if (TYPE_PAGE == ObjectTransformer.getInt(child.get(NAV_OBJECTTYPE), 0)) {
- String languageCode = "";
-
- try {
- languageCode = ObjectTransformer.getString(PropertyResolver.resolve(child, NAV_LANGUAGECODE), "");
- } catch (UnknownPropertyException upe) {
- languageCode = "";
- }
-
- if (!StringUtils.isEmpty(languageCode) && !StringUtils.isEmpty(config.languagecode) && !languageCode.equals(config.languagecode)
- && config.currentPage != null) {
- continue;
- }
- }
-
- // skip if the name is empty (fixes RT#22639)
- NavObject nav = new NavObject(child, level + 1, config);
-
- if (StringUtils.isEmpty(nav.getName())) {
- continue;
- }
-
- outputWriter.write(renderObject(child, level + 1, config));
- }
- }
-
- return outputWriter.toString();
- } catch (RuntimeException e) {
- logger.error("Unexpected Exception", e);
- throw e;
- }
- }
-
- /**
- * find an object's property inside the tagmap, then resolve it
- * @param property to be resolved
- * @param obj to resolve the property for
- * @return resolved property
- */
- public Object resolveTagmapProperty(Resolvable obj, String property) {
- Object resolvedProperty = null;
- Integer objType = ObjectTransformer.getInteger(obj.get("ttype"), null);
-
- // images are saved with TYPE_FILE actually, so we have to alter
- // that before lookup
- if (objType.intValue() == ContentFile.TYPE_IMAGE) {
- objType = new Integer(ContentFile.TYPE_FILE);
- }
-
- if (objType == null) {
- logger.error("could not determine type for object {" + obj + "}");
- return null;
- }
-
- if (tagmapCache.containsKey(objType)) {
- TagmapEntryRenderer tagmapEntry = (TagmapEntryRenderer) ((Map) tagmapCache.get(objType)).get(property);
-
- if (tagmapEntry == null && property.startsWith("object.")) {
- tagmapEntry = (TagmapEntryRenderer) ((Map) tagmapCache.get(objType)).get(property.substring(7));
- }
- if (tagmapEntry != null) {
- try {
- resolvedProperty = PropertyResolver.resolve(obj, tagmapEntry.getTagname());
- // when the property could be resolved to something
- // which is not null, we check the attributetype of the
- // tagmap entry and possibly transform the resolved
- // value into the proper type
- if (resolvedProperty != null) {
- switch (tagmapEntry.getAttributeType()) {
- case GenticsContentAttribute.ATTR_TYPE_DOUBLE:
- resolvedProperty = ObjectTransformer.getDouble(resolvedProperty, null);
- break;
-
- case GenticsContentAttribute.ATTR_TYPE_LONG:
- resolvedProperty = ObjectTransformer.getLong(resolvedProperty, null);
- break;
-
- case GenticsContentAttribute.ATTR_TYPE_INTEGER:
- resolvedProperty = ObjectTransformer.getInteger(resolvedProperty, null);
- break;
-
- default:
- break;
- }
- }
- } catch (UnknownPropertyException e) {
- logger.error("Unknown property {" + tagmapEntry.getTagname() + "}", e);
- }
- }
- }
-
- return resolvedProperty;
- }
- }
-
- public class ConfigObject {
-
- /**
- * Startfolder of the navigation.
- */
- public Resolvable startfolder;
-
- /**
- * Template to use to render navigation.
- */
- public String template;
-
- /**
- * Property by which navigation should be sorted.
- */
- public String sortBy;
-
- /**
- * Order by which property should be sorted.
- */
- public int sortOrder;
-
- /**
- * Name of property which stores specific sort order for a folder.
- */
- public String tagnameSort;
-
- /**
- * If navigation should be displayed as sitemap (all folders flapped
- * open).
- */
- public boolean sitemap;
-
- /**
- * If current path should be highlighted
- */
- public boolean activepath;
-
- /**
- * Code of language to use in navigation
- */
- public String languagecode;
-
- /**
- * Property which stores the hidden attribute name.
- */
- public String tagnameHidden;
-
- /**
- * If navigation should display hidden elements.
- */
- public boolean disableHidden;
-
- /**
- * If language fallback is enabled
- */
- public boolean disableFallback;
-
- /**
- * Set containing all objects that should be included in the navigation.
- */
- public HashSet objects;
-
- /**
- * The current page for which the navigation is created.
- */
- public Resolvable currentPage;
-
- /**
- * Set containing all resolvables leading from the current page to the
- * startpage.
- */
- public HashSet path;
-
- /**
- * Store all templates read from XML input.
- */
- public HashMap templates;
-
- /**
- * Name of tag for startpage of folder
- */
- public String tagnameStartpage;
-
- public ConfigObject() {
- startfolder = null;
- template = null;
- sortBy = null;
- sortOrder = 0;
- tagnameSort = null;
- sitemap = INPUT_SITEMAP_DEFAULT;
- activepath = INPUT_ACTIVEPATH_DEFAULT;
- languagecode = null;
- tagnameHidden = null;
- disableHidden = INPUT_DISABLEHIDDEN_DEFAULT;
- disableFallback = INPUT_DISABLEFALLBACK_DEFAULT;
- objects = null;
- currentPage = null;
- path = null;
- templates = null;
- tagnameStartpage = null;
- }
-
- /**
- * Return all configuration parameters as string.
- */
- public String toString() {
- return " startfolder: " + startfolder + ". template: " + template + ". sortBy: " + sortBy + ". sortOrder: " + sortOrder + ". tagnameSort: "
- + tagnameSort + ". sitemap: " + sitemap + ". activepath: " + activepath + ". languagecode: " + languagecode + ". tagnameHidden: " + tagnameHidden
- + ". disableHidden: " + disableHidden + ". disableFallback: " + disableFallback + ". objects: " + objects + ". currentPage: " + currentPage
- + ". path: " + path + ". templates: " + templates + ". tagnameStartpage: " + tagnameStartpage;
- }
-
- }
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/NavigationPartType.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/NavigationPartType.java
deleted file mode 100644
index 15874f1b67..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/NavigationPartType.java
+++ /dev/null
@@ -1,1173 +0,0 @@
-/*
- * @author alexander
- * @date 14.03.2007
- * @version $Id: NavigationPartType.java,v 1.13 2009-12-16 16:12:12 herbert Exp $
- */
-package com.gentics.contentnode.object.parttype;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-
-import com.gentics.api.lib.datasource.Datasource;
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.api.lib.exception.UnknownPropertyException;
-import com.gentics.api.lib.resolving.PropertyResolver;
-import com.gentics.api.lib.resolving.Resolvable;
-import com.gentics.api.lib.resolving.ResolvableComparator;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.object.Folder;
-import com.gentics.contentnode.object.Folder.PageSearch;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.contentnode.render.RenderableResolvable;
-import com.gentics.contentnode.rest.model.Property;
-import com.gentics.contentnode.rest.model.Property.Type;
-import com.gentics.lib.log.NodeLogger;
-import com.gentics.lib.render.velocity.SerializableVelocityTemplateWrapper;
-
-import io.reactivex.Flowable;
-
-/**
- * PartType 35 - Navigation
- */
-public class NavigationPartType extends AbstractVelocityPartType implements TransformablePartType {
-
- /**
- * Logger
- */
- protected static NodeLogger logger = NodeLogger.getNodeLogger(NavigationPartType.class);
-
- /**
- * Static type code for folders.
- */
- protected static final int TYPE_FOLDER = 10002;
-
- /**
- * Property name for folders.
- */
- protected static final String OBJECTS_FOLDERS = "folders";
-
- /**
- * Property name for images.
- */
- protected static final String OBJECTS_IMAGES = "images";
-
- /**
- * Property name for files.
- */
- protected static final String OBJECTS_FILES = "files";
-
- /**
- * Property name for pages.
- */
- protected static final String OBJECTS_PAGES = "pages";
-
- /**
- * Property name for all types.
- */
- protected static final String OBJECTS_ALL = "all";
-
- /**
- * Name of input parameter for startfolder
- */
- protected static final String INPUT_STARTFOLDER = "startfolder.target";
-
- /**
- * Default value for startfolder
- */
- protected static final String INPUT_STARTFOLDER_DEFAULT = "node.folder";
-
- /**
- * Name of input parameter for startfolder PROPERTY
- */
- protected static final String INPUT_STARTFOLDER_PROPERTY = "startfolderproperty";
-
- /**
- * Name of input parameter for template
- */
- public static final String INPUT_TEMPLATE = "template";
-
- /**
- * Name of input parameter for sitemap
- */
- public static final String INPUT_SITEMAP = "sitemap";
-
- /**
- * Default value for sitemap
- */
- public static final String INPUT_SITEMAP_DEFAULT_STRING = "0";
-
- /**
- * Default value for sitemap
- */
- public static final boolean INPUT_SITEMAP_DEFAULT_BOOLEAN = false;
-
- /**
- * Name of input parameter for startfolder
- */
- protected static final String INPUT_SORTBY = "sortby";
-
- /**
- * Default value for startfolder
- */
- protected static final String INPUT_SORTBY_DEFAULT = "name";
-
- /**
- * Name of input parameter for sortorder
- */
- protected static final String INPUT_SORTORDER = "sortorder";
-
- /**
- * Value of sortorder ascending
- */
- protected static final String INPUT_SORTORDER_ASC = "ASC";
-
- /**
- * Value of sortorder descending
- */
- protected static final String INPUT_SORTORDER_DESC = "DESC";
-
- /**
- * Default value for sortorder
- */
- protected static final String INPUT_SORTORDER_DEFAULT = INPUT_SORTORDER_ASC;
-
- /**
- * Name of input parameter for tagname_sort
- */
- protected static final String INPUT_TAGNAMESORT = "tagname_sort";
-
- /**
- * Default value for tagname_sort
- */
- protected static final String INPUT_TAGNAMESORT_DEFAULT = "navsort";
-
- /**
- * Name of input parameter for tagname_hidden
- */
- protected static final String INPUT_TAGNAMEHIDDEN = "tagname_hidden";
-
- /**
- * Default value for tagname_hidden
- */
- protected static final String INPUT_TAGNAMEHIDDEN_DEFAULT = "navhidden";
-
- /**
- * Name of input parameter for objects
- */
- protected static final String INPUT_OBJECTS = "objects";
-
- /**
- * Name of input parameter for disable_hidden
- */
- protected static final String INPUT_DISABLEHIDDEN = "disable_hidden";
-
- /**
- * Default value for disable_hidden
- */
- public static final String INPUT_DISABLEHIDDEN_DEFAULT_STRING = "0";
-
- /**
- * Default value for disable_hidden
- */
- protected static final boolean INPUT_DISABLEHIDDEN_DEFAULT_BOOLEAN = false;
-
- /**
- * Name of input parameter for page
- */
- protected static final String INPUT_PAGE = "page";
-
- /**
- * Name of attribute for parent
- */
- protected static final String NAV_PARENT = "parent";
-
- /**
- * Name of attribute for folder of page
- */
- protected static final String NAV_FOLDER = "folder";
-
- /**
- * Name of attribute for objecttype
- */
- protected static final String NAV_OBJECTTYPE = "ttype";
-
- /**
- * Render the navigation. Gets all needed input parameters and starts
- * rendering at startpage.
- * @throws NodeException
- */
- public String render() throws NodeException {
- logger.info("Start rendering navigation.");
-
- RenderType renderType = TransactionManager.getCurrentTransaction().getRenderType();
- int editMode = renderType.getEditMode();
- boolean editModeChanged = false;
-
- try {
- // when edit mode is edit or realedit, switch to preview mode
- if (editMode == RenderType.EM_ALOHA) {
- editModeChanged = true;
- renderType.setEditMode(RenderType.EM_ALOHA_READONLY);
- }
- if (editModeChanged) {
- renderType.setParameter(CMSResolver.ModeResolver.PARAM_OVERWRITE_EDITMODE, new Integer(editMode));
- }
-
- ConfigObject config = getInitParameters();
- String navigation = renderObject(config.startfolder, 0, 0, 0, config.totalCounter, config);
-
- logger.info("End rendering navigation.");
- if (logger.isDebugEnabled()) {
- logger.debug("Navigation: " + navigation);
- }
-
- return navigation;
- } finally {
- // when edit mode was changed, change it back
- if (editModeChanged) {
- renderType.setEditMode(editMode);
- if (editModeChanged) {
- renderType.setParameter(CMSResolver.ModeResolver.PARAM_OVERWRITE_EDITMODE, null);
- }
- }
- }
- }
-
- /**
- * Read all needed init parameters using the resolve() method. Populates
- * instance variables.
- * @throws NodeException
- */
- protected ConfigObject getInitParameters() throws NodeException {
-
- logger.debug("Start reading configuration.");
-
- ConfigObject config = new ConfigObject();
-
- // get startfolder property from input parameters
- String startfolderProperty = ObjectTransformer.getString(resolve(INPUT_STARTFOLDER_PROPERTY), "");
-
- if (!"".equals(startfolderProperty)) {
- Object tmpStartfolder = resolve(startfolderProperty);
-
- if (tmpStartfolder instanceof Resolvable) {
- config.startfolder = (Resolvable) tmpStartfolder;
- }
- }
-
- if (config.startfolder == null) {
- // get startfolder from input parameters
- Object tmpStartfolder = resolve(INPUT_STARTFOLDER);
-
- if (tmpStartfolder instanceof Resolvable) {
- config.startfolder = (Resolvable) tmpStartfolder;
- }
- }
-
- // if no startfolder specified, use default node.folder
- if (config.startfolder == null) {
- config.startfolder = (Resolvable) resolve(INPUT_STARTFOLDER_DEFAULT);
- }
-
- // if still no startfolder, something has gone wrong
- if (config.startfolder == null) {
- logger.error("No startfolder set and couldn't find default start folder.");
- throw new NodeException("No startfolder set and couldn't find default start folder.");
- }
-
- // get template
- config.template = ObjectTransformer.getString(resolve(INPUT_TEMPLATE), "");
- if ("".equals(config.template)) {
- logger.error("No templates found.");
- }
-
- // get sortby
- // default to "name"
- config.sortBy = ObjectTransformer.getString(resolve(INPUT_SORTBY), INPUT_SORTBY_DEFAULT);
- if (config.sortBy == null || "".equals(config.sortBy)) {
- config.sortBy = INPUT_SORTBY_DEFAULT;
- }
-
- // get sortorder
- // default to "ASC"
- String sortOrder = ObjectTransformer.getString(resolve(INPUT_SORTORDER), INPUT_SORTORDER_DEFAULT);
-
- config.sortOrder = getSortOrder(sortOrder);
-
- // get tagname_sort
- // default to "navsort"
- config.tagnameSort = ObjectTransformer.getString(resolve(INPUT_TAGNAMESORT), INPUT_TAGNAMESORT_DEFAULT);
- if (config.tagnameSort == null || "".equals(config.tagnameSort)) {
- config.tagnameSort = INPUT_TAGNAMESORT_DEFAULT;
- }
-
- // get sitemap flag
- // default to false
- config.sitemap = ObjectTransformer.getBoolean(ObjectTransformer.getString(resolve(INPUT_SITEMAP), INPUT_SITEMAP_DEFAULT_STRING),
- INPUT_SITEMAP_DEFAULT_BOOLEAN);
-
- // get tagname_hidden
- // default to "navhidden"
- config.tagnameHidden = ObjectTransformer.getString(resolve(INPUT_TAGNAMEHIDDEN), INPUT_TAGNAMEHIDDEN_DEFAULT);
- if (config.tagnameHidden == null || "".equals(config.tagnameHidden)) {
- config.tagnameHidden = INPUT_TAGNAMEHIDDEN_DEFAULT;
- }
-
- // get objects to be displayed
- // default to pages, folders, files
- String tmpObjects = ObjectTransformer.getString(resolve(INPUT_OBJECTS), "");
-
- config.objects = new HashSet();
- if (tmpObjects == null || "".equals(tmpObjects)) {
- config.objects.add(OBJECTS_PAGES);
- config.objects.add(OBJECTS_FOLDERS);
- config.objects.add(OBJECTS_FILES);
- } else {
- String[] tObjects = tmpObjects.split(",");
-
- for (int i = 0; i < tObjects.length; i++) {
- if (OBJECTS_FILES.equals(tObjects[i].toLowerCase())) {
- config.objects.add(OBJECTS_FILES);
- } else if (OBJECTS_FOLDERS.equals(tObjects[i].toLowerCase())) {
- config.objects.add(OBJECTS_FOLDERS);
- } else if (OBJECTS_IMAGES.equals(tObjects[i].toLowerCase())) {
- config.objects.add(OBJECTS_IMAGES);
- } else if (OBJECTS_PAGES.equals(tObjects[i].toLowerCase())) {
- config.objects.add(OBJECTS_PAGES);
- } else if (OBJECTS_ALL.equals(tObjects[i].toLowerCase())) {
- config.objects.add(OBJECTS_ALL);
- }
- }
- }
-
- // get disable_hidden
- config.disableHidden = ObjectTransformer.getBoolean(ObjectTransformer.getString(resolve(INPUT_DISABLEHIDDEN), INPUT_DISABLEHIDDEN_DEFAULT_STRING),
- INPUT_DISABLEHIDDEN_DEFAULT_BOOLEAN);
-
- // get current page
- Object tmpCurrentPage = resolve(INPUT_PAGE);
-
- if (tmpCurrentPage instanceof Resolvable) {
- config.currentPage = (Resolvable) tmpCurrentPage;
- } else {
- logger.warn("Current page not found.");
- }
-
- // get path from current page to startpage
- config.path = new HashSet();
- Resolvable pathitem = config.currentPage;
-
- while (pathitem != null) {
- config.path.add(pathitem);
- Object parent = pathitem.get(NAV_PARENT);
-
- if (parent instanceof Resolvable) {
- pathitem = (Resolvable) parent;
- } else {
- parent = pathitem.get(NAV_FOLDER);
- if (parent != pathitem && parent instanceof Resolvable) {
- pathitem = (Resolvable) parent;
- } else {
- pathitem = null;
- }
- }
- }
-
- config.totalCounter = 0;
-
- // parse template
- config.wrapper = parseTemplate(config.template);
-
- if (logger.isDebugEnabled()) {
- logger.debug("End reading configuration." + config);
- }
-
- return config;
- }
-
- /**
- * Render a resovable object.
- * @param object The resovable object that should be rendered.
- * @param level The current level of the object (startpage has level 0).
- * @param relativeNr The position of this element relative to the parent
- * element.
- * @param relativeCount The number of elements with the same parent and the
- * same level as this one.
- * @param absoluteNr The total position of this element in the navigation
- * @return The rendered string containing this and all sub-elements.
- * @throws NodeException
- */
- protected String renderObject(Resolvable object, int level, int relativeNr,
- int relativeCount, int absoluteNr, ConfigObject config) throws NodeException {
-
- if (logger.isDebugEnabled()) {
- logger.debug("Start rendering object: " + object.toString());
- }
-
- NavObject nav = new NavObject(object, level, relativeNr, relativeCount, absoluteNr, config);
- VelocityContext context = new VelocityContext(createContext(true));
-
- context.put("ctx", context);
- context.put("nav", nav);
-
- // TODO initial size
- StringWriter outwriter = new StringWriter();
-
- try {
- if (config.wrapper != null) {
- logger.debug("Merging main template.");
- mergeTemplate(config.wrapper, context, outwriter);
- } else {
- logger.warn("No template available.");
- }
- } catch (ParseErrorException pee) {
- logger.error("ParseErrorException while rendering object. " + pee.getMessage());
- throw new NodeException("ParseErrorException while rendering object. " + pee.getMessage(), pee);
- } catch (ResourceNotFoundException rnfe) {
- logger.error("ResourceNotFoundException while rendering object. " + rnfe.getMessage());
- throw new NodeException("ResourceNotFoundException while rendering object. " + rnfe.getMessage(), rnfe);
- } catch (MethodInvocationException mie) {
- logger.error("MethodInvocationException while rendering object. " + mie.getMessage());
- throw new NodeException("MethodInvocationException while rendering object. " + mie.getMessage(), mie);
- } catch (IOException ioe) {
- logger.error("IOException while rendering object. " + ioe.getMessage());
- throw new NodeException("IOException while rendering object. " + ioe.getMessage(), ioe);
- } catch (Exception e) {
- logger.error("Exception while rendering object. " + e.getMessage());
- throw new NodeException("Exception while rendering object. " + e.getMessage(), e);
- }
-
- return outwriter.toString();
- }
-
- /**
- * Decode sort order from String to int
- * @param sortOrder String representing sortorder ("asc", "desc")
- * @return int representing sortorder
- */
- protected int getSortOrder(String sortOrder) {
- if (INPUT_SORTORDER_ASC.equalsIgnoreCase(sortOrder)) {
- return Datasource.SORTORDER_ASC;
- } else if (INPUT_SORTORDER_DESC.equalsIgnoreCase(sortOrder)) {
- return Datasource.SORTORDER_DESC;
- } else {
- return Datasource.SORTORDER_ASC;
- }
- }
-
- @Override
- public Type getPropertyType() {
- return Type.NAVIGATION;
- }
-
- @Override
- public void fromProperty(Property property) throws NodeException {
- }
-
- @Override
- public Property toProperty() throws NodeException {
- return null;
- }
-
- /**
- * The object representing a navigation element.
- * @author alexander
- */
- public class NavObject {
-
- /**
- * The resolvable object this object renders
- */
- protected Resolvable object;
-
- /**
- * The level of this element
- */
- protected int level;
-
- /**
- * The position of this element relative to the parent element.
- */
- protected int relativeNr;
-
- /**
- * The total position of this element in the navigation
- */
- protected int absoluteNr;
-
- /**
- * The number of elements with the same parent and same level as this
- * one (number of siblings).
- */
- protected int relativeCount;
-
- /**
- * The cached result of the hasItems() method.
- */
- protected boolean hasItems;
-
- /**
- * If hasItems contains a valid result.
- */
- protected boolean hasItemsCache;
-
- /**
- * The cached result of the getChildrenCount() method.
- */
- protected int childrenCount;
-
- /**
- * If childrenCount contains a valid result.
- */
- protected boolean childrenCountCache;
-
- /**
- * The cached result of the isOpen() method.
- */
- protected boolean isOpen;
-
- /**
- * If isOpen contains a valid result.
- */
- protected boolean isOpenCache;
-
- /**
- * The name of the attribute by which elements in the folder should be
- * sorted. Defaults to the global attribute.
- */
- protected String folderSortBy;
-
- /**
- * Order by which elements in the folder should be sorted. Defaults to
- * the global order.
- */
- protected int folderSortOrder;
-
- /**
- * Store configuration settings
- */
- protected ConfigObject config;
-
- /**
- * Constructor of the Navigation Object.
- * @param object The resolvable object that is rendered.
- * @param level The level of the object.
- * @param relativeNr The position of this element relative to its
- * parent.
- * @param relativeCount The number of elements with the same level and
- * the same parent (number of siblings).
- * @param absoluteNr The total position of this element in the
- * navigation.
- */
- public NavObject(Resolvable object, int level, int relativeNr, int relativeCount,
- int absoluteNr, ConfigObject config) {
-
- this.object = object;
- this.level = level;
- this.relativeNr = relativeNr;
- this.absoluteNr = absoluteNr;
- this.relativeCount = relativeCount;
- this.config = config;
-
- this.hasItems = false;
- this.hasItemsCache = false;
-
- this.childrenCount = 0;
- this.childrenCountCache = false;
-
- this.isOpen = false;
- this.isOpenCache = false;
-
- folderSortBy = config.sortBy;
- folderSortOrder = config.sortOrder;
- }
-
- /**
- * Check if this object has a specific sorting set as a property.
- */
- protected void checkSorting() {
- // get tagname_sort, which should contain a string in the format
- // sortorder;sortby. if it exists, set as default sort order for
- // this folder
- Object tmpSorting = null;
-
- try {
- tmpSorting = PropertyResolver.resolve(object, "object." + config.tagnameSort);
- } catch (UnknownPropertyException upe) {
- tmpSorting = null;
- }
- String sorting = ObjectTransformer.getString(tmpSorting, "");
-
- if (sorting == null || "".equals(sorting)) {
- folderSortBy = config.sortBy;
- folderSortOrder = config.sortOrder;
- } else {
- String[] sort = sorting.split(";");
-
- if (sort.length != 2) {
- folderSortBy = config.sortBy;
- folderSortOrder = config.sortOrder;
- } else {
- folderSortOrder = getSortOrder(sort[0]);
- folderSortBy = sort[1];
- }
- }
- }
-
- /**
- * Get the resovable object that is rendered.
- * @return The resolvable object.
- */
- public Resolvable getObject() {
- return new RenderableResolvable(object);
- }
-
- /**
- * Get the level of the element (startfolder has level 0).
- * @return Level of the element.
- */
- public int getLevel() {
- return level;
- }
-
- /**
- * @param element The resolvable for which the hidden attribute should
- * be resolved.
- * @return True if the element is hidden from navigation, false
- * otherwise.
- */
- protected boolean getHidden(Resolvable element) {
- try {
- return ObjectTransformer.getBoolean(PropertyResolver.resolve(new RenderableResolvable(element), "object." + config.tagnameHidden), false);
- } catch (UnknownPropertyException upe) {
- return false;
- }
- }
-
- /**
- * Checks any child elements that are included in objects and are
- * visible for the navigation. Cache the result to speed up following
- * calls.
- * @return If the element has child elements.
- */
- public boolean hasItems() {
- // check cache to see if we already calculated hasItems
- if (hasItemsCache) {
- return hasItems;
- }
-
- // get object type for this object
- Object tmpType = object.get(NAV_OBJECTTYPE);
- int type = ObjectTransformer.getInt(tmpType, 0);
-
- // only folders can have sub items
- if (type != TYPE_FOLDER) {
- return false;
- }
-
- // check if object contains pages
- if (config.objects.contains(OBJECTS_PAGES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpPages = object.get(OBJECTS_PAGES);
-
- if (tmpPages instanceof List) {
- List pagesList = (List) tmpPages;
- Iterator it = pagesList.iterator();
-
- while (it.hasNext()) {
- Object tmpPage = it.next();
-
- if (tmpPage instanceof Resolvable) {
- Resolvable page = (Resolvable) tmpPage;
- boolean online = (page.get("online") == Boolean.TRUE);
- boolean hidden = getHidden(page);
-
- if ((!hidden || config.disableHidden) && online) {
- hasItems = true;
- hasItemsCache = true;
- return true;
- }
- }
- }
- }
- }
-
- // check if object contains folders
- if (config.objects.contains(OBJECTS_FOLDERS) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpFolders = object.get(OBJECTS_FOLDERS);
-
- if (tmpFolders instanceof List) {
- List foldersList = (List) tmpFolders;
- Iterator it = foldersList.iterator();
-
- while (it.hasNext()) {
- Object tmpFolder = it.next();
-
- if (tmpFolder instanceof Resolvable) {
- Resolvable folder = (Resolvable) tmpFolder;
- boolean hidden = getHidden(folder);
-
- if (!hidden || config.disableHidden) {
- hasItems = true;
- hasItemsCache = true;
- return true;
- }
- }
- }
- }
- }
-
- // check if object contains files
- if (config.objects.contains(OBJECTS_FILES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpFiles = object.get(OBJECTS_FILES);
-
- if (tmpFiles instanceof List) {
- List filesList = (List) tmpFiles;
- Iterator it = filesList.iterator();
-
- while (it.hasNext()) {
- Object tmpFile = it.next();
-
- if (tmpFile instanceof Resolvable) {
- Resolvable file = (Resolvable) tmpFile;
- boolean hidden = getHidden(file);
-
- if (!hidden || config.disableHidden) {
- hasItems = true;
- hasItemsCache = true;
- return true;
- }
- }
- }
- }
- }
-
- // check if object contains images
- if (config.objects.contains(OBJECTS_IMAGES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpImages = object.get(OBJECTS_IMAGES);
-
- if (tmpImages instanceof List) {
- List imagesList = (List) tmpImages;
- Iterator it = imagesList.iterator();
-
- while (it.hasNext()) {
- Object tmpImage = it.next();
-
- if (tmpImage instanceof Resolvable) {
- Resolvable image = (Resolvable) tmpImage;
- boolean hidden = getHidden(image);
-
- if (!hidden || config.disableHidden) {
- hasItems = true;
- hasItemsCache = true;
- return true;
- }
- }
- }
- }
- }
-
- // neither files, folders, images, pages found, folder is empty
- hasItems = false;
- hasItemsCache = true;
-
- return false;
- }
-
- /**
- * Check to see if this folder should be opened in the navigation. Cache
- * to speed up following calls.
- * @return If folder is open.
- */
- public boolean isOpen() {
- if (isOpenCache) {
- return isOpen;
- }
-
- boolean open = false;
- // get object type for this object
- Object tmpType = object.get(NAV_OBJECTTYPE);
- int type = ObjectTransformer.getInt(tmpType, 0);
-
- // only folders can have sub items
- if (type == TYPE_FOLDER) {
- open = isInpath() || config.sitemap || config.startfolder.equals(object);
- }
-
- isOpenCache = true;
- isOpen = open;
- return open;
- }
-
- /**
- * Get the relative position of this element relative to its parent.
- * @return The relative position.
- */
- public int getRelativenr() {
- return relativeNr;
- }
-
- /**
- * Get the absolute position of this element in the navigation.
- * @return The absolute position.
- */
- public int getAbsolutenr() {
- return absoluteNr;
- }
-
- /**
- * Get the number of elements in the same level with the same parent
- * (number of siblings).
- * @return The number of siblings.
- */
- public int getRelativecount() {
- return relativeCount;
- }
-
- /**
- * Get the number of child elements for this folder. Only count elements
- * enabled through the objects parameter and only count visible
- * elements.
- * @return The number of children for this element.
- */
- public int getChildrencount() {
- // check cache to see if we already calculated hasItems
- if (childrenCountCache) {
- return childrenCount;
- }
-
- int count = 0;
-
- // get object type for this object
- Object tmpType = object.get(NAV_OBJECTTYPE);
- int type = ObjectTransformer.getInt(tmpType, 0);
-
- // only folders can have sub items
- if (type != TYPE_FOLDER) {
- return count;
- }
-
- // check if object contains pages
- if (config.objects.contains(OBJECTS_PAGES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpPages = object.get(OBJECTS_PAGES);
-
- if (tmpPages instanceof List) {
- List pagesList = (List) tmpPages;
- Iterator it = pagesList.iterator();
-
- while (it.hasNext()) {
- Object tmpPage = it.next();
-
- if (tmpPage instanceof Resolvable) {
- Resolvable page = (Resolvable) tmpPage;
- boolean hidden = getHidden(page);
- boolean online = (Boolean)page.get("online");
-
- if (online && (!hidden || config.disableHidden)) {
- count++;
- }
- }
- }
- }
- }
-
- // check if object contains folders
- if (config.objects.contains(OBJECTS_FOLDERS) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpFolders = object.get(OBJECTS_FOLDERS);
-
- if (tmpFolders instanceof List) {
- List foldersList = (List) tmpFolders;
- Iterator it = foldersList.iterator();
-
- while (it.hasNext()) {
- Object tmpFolder = it.next();
-
- if (tmpFolder instanceof Resolvable) {
- Resolvable folder = (Resolvable) tmpFolder;
- boolean hidden = getHidden(folder);
-
- if (!hidden || config.disableHidden) {
- count++;
- }
- }
- }
- }
- }
-
- // check if object contains files
- if (config.objects.contains(OBJECTS_FILES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpFiles = object.get(OBJECTS_FILES);
-
- if (tmpFiles instanceof List) {
- List filesList = (List) tmpFiles;
- Iterator it = filesList.iterator();
-
- while (it.hasNext()) {
- Object tmpFile = it.next();
-
- if (tmpFile instanceof Resolvable) {
- Resolvable file = (Resolvable) tmpFile;
- boolean hidden = getHidden(file);
-
- if (!hidden || config.disableHidden) {
- count++;
- }
- }
- }
- }
- }
-
- // check if object contains images
- if (config.objects.contains(OBJECTS_IMAGES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpImages = object.get(OBJECTS_IMAGES);
-
- if (tmpImages instanceof List) {
- List imagesList = (List) tmpImages;
- Iterator it = imagesList.iterator();
-
- while (it.hasNext()) {
- Object tmpImage = it.next();
-
- if (tmpImage instanceof Resolvable) {
- Resolvable image = (Resolvable) tmpImage;
- boolean hidden = getHidden(image);
-
- if (!hidden || config.disableHidden) {
- count++;
- }
- }
- }
- }
- }
-
- childrenCount = count;
- childrenCountCache = true;
-
- return count;
- }
-
- /**
- * Check to see if this element is in the path between the current page
- * and the startpage
- * @return If this element is in the path.
- */
- public boolean isInpath() {
- return config.path.contains(object);
- }
-
- /**
- * Check to see if this element is the current page.
- * @return If this element is the current page.
- */
- public boolean isCurrentpage() {
- if (config.currentPage != null) {
- return config.currentPage.equals(object);
- } else {
- return false;
- }
- }
-
- /**
- * Render the subtree (all child elements) of this element. Only render
- * elements listed in objects, and only render visible objects.
- * @return The rendered subtree.
- * @throws NodeException
- */
- public String getSubtree() throws NodeException {
- // check if node is open
- if (!isOpen()) {
- return "";
- }
-
- // TODO initial size for stringbuffer
- StringBuffer outputBuffer = new StringBuffer();
-
- // check to see if this object has a special sort order set
- // in tagname_sort
- checkSorting();
-
- // local counters
- int relativeNr = 0;
-
- // this list will hold all objects from the navigation for sorting
- List objects = new ArrayList<>();
-
- // get folders
- if (config.objects.contains(OBJECTS_FOLDERS) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpFolders = object.get(OBJECTS_FOLDERS);
-
- if (tmpFolders instanceof List) {
- Flowable flowable = Flowable.fromIterable((List>) tmpFolders).filter(o -> o instanceof Resolvable).map(o -> (Resolvable) o);
- if (!config.disableHidden) {
- // filter hidden
- flowable = flowable.filter(res -> !getHidden(res));
- }
- objects.addAll(flowable.toList().blockingGet());
- }
- }
-
- // get pages
- if (config.objects.contains(OBJECTS_PAGES) || config.objects.contains(OBJECTS_ALL)) {
- if (object instanceof Folder) {
- Folder folder = (Folder)object;
- PageSearch search = new PageSearch();
- search.setOnline(true);
- List tmpPages = folder.getPages(search);
-
- if (!config.disableHidden) {
- // filter hidden
- tmpPages = Flowable.fromIterable(tmpPages).filter(res -> !getHidden(res)).toList().blockingGet();
- }
- objects.addAll(tmpPages);
- }
- }
-
- // get files
- if (config.objects.contains(OBJECTS_FILES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpFiles = object.get(OBJECTS_FILES);
-
- if (tmpFiles instanceof List) {
- Flowable flowable = Flowable.fromIterable((List>) tmpFiles).filter(o -> o instanceof Resolvable).map(o -> (Resolvable) o);
- if (!config.disableHidden) {
- // filter hidden
- flowable = flowable.filter(res -> !getHidden(res));
- }
- objects.addAll(flowable.toList().blockingGet());
- }
- }
-
- // get images
- if (config.objects.contains(OBJECTS_IMAGES) || config.objects.contains(OBJECTS_ALL)) {
- Object tmpImages = object.get(OBJECTS_IMAGES);
-
- if (tmpImages instanceof List) {
- Flowable flowable = Flowable.fromIterable((List>) tmpImages).filter(o -> o instanceof Resolvable).map(o -> (Resolvable) o);
- if (!config.disableHidden) {
- // filter hidden
- flowable = flowable.filter(res -> !getHidden(res));
- }
- objects.addAll(flowable.toList().blockingGet());
- }
- }
-
- // sort the list
- Collections.sort(objects, new ResolvableComparator(folderSortBy, folderSortOrder));
-
- childrenCount = objects.size();
- childrenCountCache = true;
-
- // render items
- for (Resolvable obj : objects) {
- outputBuffer.append(renderObject(obj, level + 1, ++relativeNr, childrenCount, ++config.totalCounter, config));
- }
- return outputBuffer.toString();
- }
- }
-
- public class ConfigObject {
-
- /**
- * Startfolder of the navigation.
- */
- public Resolvable startfolder;
-
- /**
- * Template to use to render navigation.
- */
- public String template;
-
- /**
- * Property by which navigation should be sorted.
- */
- public String sortBy;
-
- /**
- * Order by which property should be sorted.
- */
- public int sortOrder;
-
- /**
- * Name of property which stores specific sort order for a folder.
- */
- public String tagnameSort;
-
- /**
- * If navigation should be displayed as sitemap (all folders flapped
- * open).
- */
- public boolean sitemap;
-
- /**
- * Property which stores the hidden attribute name.
- */
- public String tagnameHidden;
-
- /**
- * If navigation should display hidden elements.
- */
- public boolean disableHidden;
-
- /**
- * Set containing all objects that should be included in the navigation.
- */
- public HashSet objects;
-
- /**
- * The current page for which the navigation is created.
- */
- public Resolvable currentPage;
-
- /**
- * Set containing all resolvables leading from the current page to the
- * startpage.
- */
- public HashSet path;
-
- /**
- * Store all templates read from XML input.
- */
- public SerializableVelocityTemplateWrapper wrapper;
-
- /**
- * Counter over all elements in the navigation.
- */
- public int totalCounter;
-
- public ConfigObject() {
- startfolder = null;
- template = null;
- sortBy = null;
- sortOrder = 0;
- tagnameSort = null;
- sitemap = INPUT_SITEMAP_DEFAULT_BOOLEAN;
- tagnameHidden = null;
- disableHidden = INPUT_DISABLEHIDDEN_DEFAULT_BOOLEAN;
- objects = null;
- currentPage = null;
- path = null;
- wrapper = null;
- totalCounter = 0;
- }
-
- /**
- * Return all configuration parameters as string.
- */
- public String toString() {
- return " startfolder: " + startfolder + ". template: " + template + ". sortBy: " + sortBy + ". sortOrder: " + sortOrder + ". tagnameSort: "
- + tagnameSort + ". sitemap: " + sitemap + ". tagnameHidden: " + tagnameHidden + ". disableHidden: " + disableHidden + ". objects: " + objects
- + ". currentPage: " + currentPage + ". path: " + path;
- }
- }
-
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/ProvidedResolver.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/ProvidedResolver.java
new file mode 100644
index 0000000000..535776276c
--- /dev/null
+++ b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/ProvidedResolver.java
@@ -0,0 +1,11 @@
+package com.gentics.contentnode.object.parttype;
+
+/**
+ * Interface for additional resolvers, which are added via {@link CMSResolverService} implementations
+ */
+public interface ProvidedResolver {
+ /**
+ * Clean resources, which were occupied by the resolver
+ */
+ void clean();
+}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/TextPartType.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/TextPartType.java
index c6d6a1f4e6..5fe5e588d5 100644
--- a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/TextPartType.java
+++ b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/TextPartType.java
@@ -7,12 +7,14 @@
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import com.gentics.api.lib.etc.ObjectTransformer;
import com.gentics.api.lib.exception.NodeException;
+import com.gentics.contentnode.etc.ServiceLoaderUtil;
import com.gentics.contentnode.factory.TransactionManager;
import com.gentics.contentnode.object.Value;
import com.gentics.contentnode.render.RenderResult;
@@ -25,6 +27,11 @@
* TypeIDs: 1 (Text), 2 (Text/Html), 3 (HTML), 9 (Text Short), 10 (Text Html Long), 21 (HTML lang), 26 (Java), 27 (DHTML)
**/
public abstract class TextPartType extends AbstractPartType implements PartType {
+ /**
+ * Service loader for {@link TextRenderService}s
+ */
+ private final static ServiceLoaderUtil textRenderServiceLoader = ServiceLoaderUtil
+ .load(TextRenderService.class);
/**
* do not replace any newlines
@@ -76,14 +83,13 @@ public boolean hasTemplate() throws NodeException {
public String render(RenderResult result, String template) throws NodeException {
super.render(result, template);
- // if the part is inline editable and is rendered as template for a velocity part, we make the content safe by replacing # and $
- // with the escape tool. Otherwise, if the editor entered e.g. ## into the content, this would break the velocity template
- if (getValueObject().getPart().isInlineEditable() && ObjectTransformer
- .getBoolean(TransactionManager.getCurrentTransaction().getRenderType().getParameter(VelocityPartType.SAFE_INLINE_RENDERING), false)
- && !isVelocityTemplate()) {
- return parsedText.replaceAll("\\$", "\\${cms.imps.velocitytools.esc.d}").replaceAll("#", "\\${cms.imps.velocitytools.esc.h}");
+
+ Value valueObject = getValueObject();
+ String retVal = parsedText;
+ for (TextRenderService service : textRenderServiceLoader) {
+ retVal = service.render(valueObject, retVal);
}
- return parsedText;
+ return retVal;
}
/**
@@ -401,20 +407,6 @@ private boolean isBrTag(String token, int off) {
return false;
}
- /**
- * Determines whether the value is the "template" part of a VTL-tag
- * @return true iff the value is template of a VTL-part
- * @throws NodeException
- */
- private boolean isVelocityTemplate() throws NodeException {
- if ("template".equals(getValueObject().getPart().getKeyname())
- && getValueObject().getContainer().getConstruct().getParts().stream().filter(p -> p.getPartTypeId() == 33).findFirst().isPresent()) {
- return true;
- } else {
- return false;
- }
- }
-
/**
* Returns True if the value of this part type matches the configured
* regular expression that corresponds with it, or if no regular expression
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/TextRenderService.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/TextRenderService.java
new file mode 100644
index 0000000000..52e38490f5
--- /dev/null
+++ b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/TextRenderService.java
@@ -0,0 +1,18 @@
+package com.gentics.contentnode.object.parttype;
+
+import com.gentics.api.lib.exception.NodeException;
+import com.gentics.contentnode.object.Value;
+
+/**
+ * Interface for services which render text which is returned by {@link TextPartType#render(com.gentics.contentnode.render.RenderResult, String)}
+ */
+public interface TextRenderService {
+ /**
+ * Render the given text for the value
+ * @param value value which returns the text
+ * @param text text
+ * @return possibly modified text
+ * @throws NodeException
+ */
+ String render(Value value, String text) throws NodeException;
+}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/UnavailablePartType.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/UnavailablePartType.java
new file mode 100644
index 0000000000..05ac122f54
--- /dev/null
+++ b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/UnavailablePartType.java
@@ -0,0 +1,56 @@
+package com.gentics.contentnode.object.parttype;
+
+import com.gentics.api.lib.exception.NodeException;
+import com.gentics.contentnode.object.Value;
+import com.gentics.contentnode.render.RenderResult;
+import com.gentics.contentnode.rest.model.Property;
+import com.gentics.contentnode.rest.model.Property.Type;
+
+/**
+ * Replacement {@link PartType} implementation for optional parttypes, which are not available
+ */
+public class UnavailablePartType extends AbstractPartType implements PartType {
+
+ private static final long serialVersionUID = -493274421361002723L;
+
+ protected String originalClass;
+
+ public UnavailablePartType(Value value, String originalClass) throws NodeException {
+ super(value);
+ this.originalClass = originalClass;
+ }
+
+ @Override
+ public Type getPropertyType() {
+ return Type.UNKNOWN;
+ }
+
+ @Override
+ public void fromProperty(Property property) throws NodeException {
+ }
+
+ @Override
+ public boolean hasTemplate() throws NodeException {
+ return false;
+ }
+
+ @Override
+ public boolean isMandatoryAndNotFilledIn() throws NodeException {
+ return false;
+ }
+
+ @Override
+ public boolean hasSameContent(PartType other) throws NodeException {
+ return false;
+ }
+
+ @Override
+ protected void fillProperty(Property property) throws NodeException {
+ }
+
+ @Override
+ public String render(RenderResult renderResult, String template) throws NodeException {
+ logger.error("PartType implementation %s is not available".formatted(originalClass));
+ return null;
+ }
+}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/VelocityPartType.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/VelocityPartType.java
deleted file mode 100644
index 883d2dca2f..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/VelocityPartType.java
+++ /dev/null
@@ -1,287 +0,0 @@
-package com.gentics.contentnode.object.parttype;
-
-import java.io.IOException;
-import java.io.StringWriter;
-
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.api.lib.resolving.PropertyResolver;
-import com.gentics.api.lib.resolving.Resolvable;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.object.Tag;
-import com.gentics.contentnode.object.Value;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.contentnode.render.RenderableResolvable;
-import com.gentics.contentnode.render.RenderType.ParameterScope;
-import com.gentics.contentnode.rest.model.Property;
-import com.gentics.contentnode.rest.model.Property.Type;
-import com.gentics.lib.etc.StringUtils;
-import com.gentics.lib.log.NodeLogger;
-import com.gentics.lib.render.velocity.SerializableVelocityTemplateWrapper;
-
-/**
- * PartType 33 - Velocity
- */
-public class VelocityPartType extends AbstractVelocityPartType implements TransformablePartType, Resolvable {
-
- /**
- * Logger
- */
- protected static NodeLogger logger = NodeLogger.getNodeLogger(VelocityPartType.class);
-
- /**
- * Name of input parameter for template
- */
- public static final String INPUT_TEMPLATE = "template";
-
- /**
- * Name of input parameter for macros
- */
- public static final String INPUT_MACROS = "macros";
-
- /**
- * Name of the rendertype parameter, which is set to "true" while the part "template" is rendered.
- * This will make sure that the special VTL characters # and $ will be escaped when rendered from an inline editable part, which is included via <node>-Notation into the template part
- */
- public static final String SAFE_INLINE_RENDERING = "gtx.safe_inline_rendering";
-
- /**
- * Render the navigation. Gets all needed input parameters and starts
- * rendering at startpage.
- * @throws NodeException
- */
- public String render() throws NodeException {
- // create Velocity context, populate
- VelocityContext context = new VelocityContext(createContext(true));
- return render(context);
- }
-
- /**
- * Render with the given context
- * @param context context
- * @return rendered template
- * @throws NodeException
- */
- protected String render(VelocityContext context) throws NodeException {
- ConfigObject config = getInitParameters();
-
- context.put("ctx", context);
-
- StringWriter outwriter = new StringWriter();
- RenderType renderType = TransactionManager.getCurrentTransaction().getRenderType();
- int editMode = renderType.getEditMode();
- boolean editModeChanged = false;
-
- try {
- // when edit mode is edit or realedit, switch to preview mode
- if (editMode == RenderType.EM_ALOHA) {
- editModeChanged = true;
- renderType.setEditMode(RenderType.EM_ALOHA_READONLY);
- }
- if (editModeChanged) {
- renderType.setParameter(CMSResolver.ModeResolver.PARAM_OVERWRITE_EDITMODE, new Integer(editMode));
- }
-
- if (config.wrapper != null) {
- mergeTemplate(config.wrapper, context, outwriter);
- }
-
- } catch (ParseErrorException pee) {
- logger.error("ParseErrorException while merging velocity template for " + renderType.getStack().getUIReadableStack() + ". " + pee.getMessage());
- throw new NodeException("ParseErrorException while merging velocity template for " + renderType.getStack().getUIReadableStack() + ". " + pee.getMessage(), pee);
- } catch (ResourceNotFoundException rnfe) {
- logger.error("ResourceNotFoundException while merging velocity template for " + renderType.getStack().getUIReadableStack() + ". " + rnfe.getMessage());
- throw new NodeException("ResourceNotFoundException while merging velocity template for " + renderType.getStack().getUIReadableStack() + ". " + rnfe.getMessage(), rnfe);
- } catch (MethodInvocationException mie) {
- logger.error("MethodInvocationException while merging velocity template for " + renderType.getStack().getUIReadableStack() + ". " + mie.getMessage());
- throw new NodeException("MethodInvocationException while merging velocity template for " + renderType.getStack().getUIReadableStack() + ". " + mie.getMessage(), mie);
- } catch (IOException ioe) {
- logger.error("IOException while merging velocity template for " + renderType.getStack().getUIReadableStack() + ". " + ioe.getMessage());
- throw new NodeException("IOException while merging velocity template for " + renderType.getStack().getUIReadableStack() + ". " + ioe.getMessage(), ioe);
- } catch (Throwable e) {
- String message = e instanceof StackOverflowError ? "Stack overflow" : e.getMessage();
-
- logger.error("Exception while merging velocity template for " + renderType.getStack().getUIReadableStack() + ". " + message);
- throw new NodeException("Exception while merging velocity template for " + renderType.getStack().getUIReadableStack() + ". " + message, e);
- } finally {
- // when edit mode was changed, change it back
- if (editModeChanged) {
- renderType.setEditMode(editMode);
- if (editModeChanged) {
- renderType.setParameter(CMSResolver.ModeResolver.PARAM_OVERWRITE_EDITMODE, null);
- }
- }
- }
-
- return outwriter.toString();
- }
-
- /**
- * Read all needed init parameters using the resolve() method. Populates
- * instance variables.
- * @throws NodeException
- */
- protected ConfigObject getInitParameters() throws NodeException {
- ConfigObject config = new ConfigObject();
- // resolve the template
- RenderType renderType = TransactionManager.getCurrentTransaction().getRenderType();
- Tag topmostTag = renderType.getStack().getTopmostTag();
-
- if (topmostTag == null) {
- String message = "Couldn't get topmost tag from render stack";
-
- logger.error(message);
- throw new NodeException(message);
- }
-
- // We use the PropertyResolver because it doesn't check if the tag is enabled,
- // as it would cause a problem when the template part can't be resolved.
- PropertyResolver resolver = new PropertyResolver(topmostTag);
- try (ParameterScope p = renderType.withParameter(SAFE_INLINE_RENDERING, true)) {
- config.template = renderObjectWithoutRecursionCheck(resolver.resolve("parts." + INPUT_TEMPLATE), null);
- }
- // and the macros
- config.macros = renderObjectWithoutRecursionCheck(topmostTag.get(INPUT_MACROS), "");
-
- if (config.template == null) {
- logger.error("No template found.");
- throw new NodeException("No template found.");
- }
-
- // parse template
- config.wrapper = parseTemplate(config.template, config.macros);
-
- return config;
- }
-
- /**
- * Helper method to render Values without recursion test
- * @param object object to render
- * @param defaultValue default value
- * @return rendered object
- * @throws NodeException
- */
- protected String renderObjectWithoutRecursionCheck(Object object, String defaultValue) throws NodeException {
- // special behaviour for Values (disable the recursion test, since this
- // would prevent nested velocity tags with static templates)
- if (object instanceof Value) {
- // when the template is a value, we render it without recursion test
- return ((Value) object).render(TransactionManager.getCurrentTransaction().getRenderResult(), null, false, true);
- } else {
- // all other objects are normally rendered
- return ObjectTransformer.getString(object, defaultValue);
- }
- }
-
- /**
- * Parse the templates given by the parameters.
- *
- * Concatenate the input strings to generate the full template source (macros always come first)
- * Check whether the template has been cached (cache key is the md5 sum of the template source)
- * Let Velocity parse the template source into a Template object. Use the next value of {@link #templateNamePostfixSequence} in the template name, so that no two templates have the same template name
- * Wrap the Template object into a {@link SerializableVelocityTemplateWrapper} instance that is put in the cache and returned from this object
- *
- * @param inputTemplate The Velocity template of the navigation
- * @param macros The Velocity macros to include
- * @return A Template object.
- * @throws NodeException
- */
- protected SerializableVelocityTemplateWrapper parseTemplate(String inputTemplate, String macros) throws NodeException {
- String fullTemplate = inputTemplate;
-
- // when additional macros are given, we combine the macros with the template
- if (!StringUtils.isEmpty(macros)) {
- StringBuffer buffer = new StringBuffer(inputTemplate.length() + macros.length());
-
- // important: macros first!
- buffer.append(macros);
- buffer.append(inputTemplate);
- fullTemplate = buffer.toString();
- }
-
- return parseTemplate(fullTemplate);
- }
-
- @Override
- public Type getPropertyType() {
- return Type.VELOCITY;
- }
-
- @Override
- public void fromProperty(Property property) throws NodeException {
- }
-
- @Override
- public Property toProperty() throws NodeException {
- return null;
- }
-
- /**
- * Wrapper for the rendered velocity template
- */
- public class ConfigObject {
- /**
- * Template to use to render navigation.
- */
- protected String template;
-
- /**
- * Velocity macros used to render
- */
- protected String macros;
-
- /**
- * Store all templates read from XML input.
- */
- protected SerializableVelocityTemplateWrapper wrapper;
-
- /**
- * Create an empty instance
- */
- public ConfigObject() {
- this.template = null;
- this.macros = "";
- this.wrapper = null;
- }
- }
-
- @Override
- public Object getProperty(String key) {
- return get(key);
- }
-
- @Override
- public Object get(String key) {
- // create Velocity context, populate
- try {
- RenderType renderType = TransactionManager.getCurrentTransaction().getRenderType();
-
- try {
- renderType.createCMSResolver();
-
- VelocityContext context = new VelocityContext(createContext(true));
- render(context);
- Object value = context.get(key);
- if (value instanceof RenderableResolvable) {
- value = ((RenderableResolvable) value).getWrappedObject();
- }
- return value;
- } finally {
- renderType.popCMSResolver();
- }
- } catch (NodeException e) {
- logger.error(String.format("Error while getting %s", key), e);
- return null;
- }
- }
-
- @Override
- public boolean canResolve() {
- return true;
- }
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/imps/CMSLoaderImp.java b/cms-core/src/main/java/com/gentics/contentnode/object/parttype/imps/CMSLoaderImp.java
deleted file mode 100644
index cfb855ec08..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/object/parttype/imps/CMSLoaderImp.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * @author herbert
- * @date Jan 8, 2009
- * @version $Id: CMSLoaderImp.java,v 1.2 2009-12-16 16:12:13 herbert Exp $
- */
-package com.gentics.contentnode.object.parttype.imps;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.api.portalnode.imp.AbstractGenticsImp;
-import com.gentics.api.portalnode.imp.GenticsImpInterface;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionException;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.object.File;
-import com.gentics.contentnode.object.Folder;
-import com.gentics.contentnode.object.ImageFile;
-import com.gentics.contentnode.object.Node;
-import com.gentics.contentnode.object.NodeObject;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.render.RenderableResolvable;
-import com.gentics.lib.log.NodeLogger;
-
-/**
- * A simple loader imp which can be used to load content objects like pages, folders, images and files.
- * @author herbert
- */
-public class CMSLoaderImp extends AbstractGenticsImp implements GenticsImpInterface {
-
- private static NodeLogger logger = NodeLogger.getNodeLogger(CMSLoaderImp.class);
-
- public Object getObject(int type, Integer id) {
- try {
- Transaction t = TransactionManager.getCurrentTransaction();
- Class clazz = t.getClass(type);
- NodeObject obj = t.getObject(clazz, id);
-
- if (obj == null && type == File.TYPE_FILE) {
- // if we haven't found a file with the given id, try images ..
- return new RenderableResolvable(t.getObject(t.getClass(ImageFile.TYPE_IMAGE), id));
- }
- return new RenderableResolvable(obj);
- } catch (TransactionException e) {
- logger.error("Error while retrieving transaction.", e);
- return null;
- } catch (NodeException e) {
- logger.error("Error while retrieving object of type {" + type + "} with id {" + id + "}", e);
- return null;
- }
- }
-
- /**
- * get an object of the given type with the given id.
- * @param type - the type of the object, one of: page, folder, file, image, node
- * @param id the id of the content object
- * @return the content object or null if not found or an error occurred.
- */
- public Object getObject(String type, Integer id) {
- int typeId = 0;
-
- if ("page".equals(type)) {
- typeId = Page.TYPE_PAGE;
- } else if ("folder".equals(type)) {
- typeId = Folder.TYPE_FOLDER;
- } else if ("file".equals(type)) {
- typeId = File.TYPE_FILE;
- } else if ("image".equals(type)) {
- typeId = ImageFile.TYPE_IMAGE;
- } else if ("node".equals(type)) {
- typeId = Node.TYPE_NODE;
- } else {
- logger.warn("Requested invalid object type {" + type + "}");
- return null;
- }
- return getObject(typeId, id);
- }
-
- /**
- * load object by contentid. - for example 10007.1234
- */
- public Object getObject(String contentId) {
- int pos = contentId.indexOf(".");
- String typeString = contentId.substring(0, pos);
- String idString = contentId.substring(pos + 1);
-
- int type = Integer.parseInt(typeString);
- Integer id = new Integer(idString);
-
- return getObject(type, id);
- }
-
- public Object getFolder(Integer id) {
- return getObject(Folder.TYPE_FOLDER, id);
- }
-
- public Object getImage(Integer id) {
- return getObject(ImageFile.TYPE_IMAGE, id);
- }
-
- public Object getFile(Integer id) {
- return getObject(File.TYPE_FILE, id);
- }
-
- public Object getPage(Integer id) {
- return getObject(Page.TYPE_PAGE, id);
- }
-
- public Object getNode(Integer id) {
- return getObject(Node.TYPE_NODE, id);
- }
-
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/render/ChannelDirective.java b/cms-core/src/main/java/com/gentics/contentnode/render/ChannelDirective.java
deleted file mode 100644
index a990e0a21b..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/render/ChannelDirective.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.gentics.contentnode.render;
-
-import java.io.IOException;
-import java.io.Writer;
-
-import org.apache.velocity.context.InternalContextAdapter;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.runtime.directive.Directive;
-import org.apache.velocity.runtime.parser.node.Node;
-
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.factory.ChannelTrx;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-
-/**
- * Velocity directive that renders its body in the scope of the given channel.
- */
-public class ChannelDirective extends Directive {
-
- /*
- * (non-Javadoc)
- * @see org.apache.velocity.runtime.directive.Directive#getName()
- */
- @Override
- public String getName() {
- return "gtx_channel";
- }
-
- /*
- * (non-Javadoc)
- * @see org.apache.velocity.runtime.directive.Directive#getType()
- */
- @Override
- public int getType() {
- return BLOCK;
- }
-
- /**
- * This directive will render its body in the scope of the given channel.
- *
- * @see org.apache.velocity.runtime.directive.Directive#render(org.apache.velocity.context.InternalContextAdapter,
- * java.io.Writer, org.apache.velocity.runtime.parser.node.Node)
- * @see ChannelTrx
- */
- @Override
- public boolean render(final InternalContextAdapter context, final Writer writer, final Node node)
- throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
- final Node param = node.jjtGetChild(0);
- final Node body = node.jjtGetChild(node.jjtGetNumChildren() - 1);
-
- final Object nodeIdRaw = param.value(context);
- final String nodeIdString = ObjectTransformer.getString(nodeIdRaw, null);
-
- if (ObjectTransformer.isEmpty(nodeIdString)) {
- return body.render(context, writer);
- }
-
- com.gentics.contentnode.object.Node channel = getNodeFromIdOrThrowException(nodeIdString,
- context, param);
-
- try (final ChannelTrx trx = new ChannelTrx(channel)) {
- return body.render(context, writer);
- } catch (final NodeException e) {
- throw new IOException(e);
- }
- }
-
- private com.gentics.contentnode.object.Node getNodeFromIdOrThrowException(String nodeIdString,
- InternalContextAdapter context,
- Node param) {
- try {
- final Transaction currentTransaction = TransactionManager.getCurrentTransaction();
-
- com.gentics.contentnode.object.Node node = currentTransaction.getObject(
- com.gentics.contentnode.object.Node.class,
- nodeIdString,
- false,
- false);
-
- if (node == null) {
- throw new ResourceNotFoundException("Node with ID {" + nodeIdString + "} not found");
- }
-
- return node;
- } catch (final NodeException e) {
- throw new MethodInvocationException(
- "Could not load Node with ID {" + nodeIdString + "}",
- e,
- getName(),
- context.getCurrentTemplateName(),
- param.getLine(),
- param.getColumn());
- }
- }
-
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/render/EditDirective.java b/cms-core/src/main/java/com/gentics/contentnode/render/EditDirective.java
deleted file mode 100644
index f2ddfceca1..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/render/EditDirective.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.gentics.contentnode.render;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Optional;
-
-import org.apache.velocity.context.InternalContextAdapter;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.runtime.parser.node.Node;
-
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.api.lib.exception.UnknownPropertyException;
-import com.gentics.api.lib.resolving.PropertyResolver;
-import com.gentics.contentnode.factory.TransactionManager;
-
-/**
- * Velocity Directive for rendering objects in edit mode (if the page was
- * originally rendered in edit mode). When a page is rendered in one of the edit
- * modes, velocity tags will change the rendermode temporarily to preview,
- * because in general, velocity should not be rendered in edit mode. When
- * rendering this directive, the originally set rendermode will be restored
- * while rendering the object.
- */
-public class EditDirective extends RenderDirective {
- @Override
- public String getName() {
- return "gtx_edit";
- }
-
- @Override
- public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException,
- MethodInvocationException {
- RenderType renderType = null;
- boolean editModeSet = false;
- int currentEditMode = 0;
-
- try {
- // switch back to the original rendermode, if the rendermode was changed for rendering the velocity tag
- renderType = TransactionManager.getCurrentTransaction().getRenderType();
- // we do this by getting rendermde.editMode from the CMSResolver, which will also take into consideration, whether
- // we are rendering a foreign object or not (not edit mode for foreign objects)
- int editMode = Optional.ofNullable(renderType.getCMSResolver()).map(cms -> {
- try {
- return ObjectTransformer.getInt(PropertyResolver.resolve(cms, "rendermode.editMode", false), -1);
- } catch (UnknownPropertyException e) {
- return -1;
- }
- }).orElse(-1);
-
- currentEditMode = renderType.getEditMode();
-
- if (editMode > 0 && editMode != currentEditMode) {
- renderType.setEditMode(editMode);
- editModeSet = true;
- }
-
- return super.render(context, writer, node);
- } catch (NodeException e) {
- throw new MethodInvocationException("Error while rendering object", e, getName(), context.getCurrentTemplateName(), node.jjtGetChild(0).getLine(),
- node.jjtGetChild(0).getColumn());
- } finally {
- // if the original rendermode was restored for rendering the directive, we switch back to the rendermode,
- // that was chosen for rendering the velocity tag
- if (editModeSet) {
- renderType.setEditMode(currentEditMode);
- }
- }
- }
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/render/GisDirective.java b/cms-core/src/main/java/com/gentics/contentnode/render/GisDirective.java
deleted file mode 100644
index 7d4d618463..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/render/GisDirective.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package com.gentics.contentnode.render;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Map;
-
-import org.apache.velocity.context.InternalContextAdapter;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.exception.TemplateInitException;
-import org.apache.velocity.runtime.RuntimeServices;
-import org.apache.velocity.runtime.directive.Directive;
-import org.apache.velocity.runtime.parser.node.Node;
-
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.api.lib.resolving.Resolvable;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.object.ImageFile;
-import com.gentics.contentnode.render.GisRendering.CropInfo;
-import com.gentics.contentnode.render.GisRendering.ResizeInfo;
-
-/**
- * Directive for rendering GenticsImageStore URLs
- */
-public class GisDirective extends Directive {
- /**
- * First argument must be the image
- */
- public final static int ARGS_IMAGE = 0;
-
- /**
- * Second argument must be the resizeinfo
- */
- public final static int ARGS_RESIZE = 1;
-
- /**
- * Third argument may be the cropinfo
- */
- public final static int ARGS_CROP = 2;
-
- /**
- * Minimum number of arguments
- */
- public final static int MIN_ARGUMENTS = 2;
-
- /**
- * Maximum number of arguments
- */
- public final static int MAX_ARGUMENTS = 3;
-
- /* (non-Javadoc)
- * @see org.apache.velocity.runtime.directive.Directive#getName()
- */
- @Override
- public String getName() {
- return "gtx_gis";
- }
-
- /* (non-Javadoc)
- * @see org.apache.velocity.runtime.directive.Directive#getType()
- */
- @Override
- public int getType() {
- return LINE;
- }
-
- @Override
- public void init(RuntimeServices rs, InternalContextAdapter context, Node node) throws TemplateInitException {
- super.init(rs, context, node);
-
- int argCount = node.jjtGetNumChildren();
- if (argCount < MIN_ARGUMENTS || argCount > MAX_ARGUMENTS) {
- throw new TemplateInitException("#" + getName() + "() requires between " + MIN_ARGUMENTS + " and " + MAX_ARGUMENTS
- + " arguments, but was called with " + argCount + " arguments", context.getCurrentTemplateName(), node.getColumn(), node.getLine());
- }
- }
-
- /* (non-Javadoc)
- * @see org.apache.velocity.runtime.directive.Directive#render(org.apache.velocity.context.InternalContextAdapter, java.io.Writer, org.apache.velocity.runtime.parser.node.Node)
- */
- @Override
- public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException,
- MethodInvocationException {
- try {
- ImageFile image = getImage(context, node);
- ResizeInfo resizeInfo = getResizeInfo(context, node);
- CropInfo cropInfo = getCropInfo(context, node);
-
- return GisRendering.render(image, resizeInfo, cropInfo, writer);
- } catch (NodeException e) {
- throw new MethodInvocationException("Error while rendering object", e, getName(), context.getCurrentTemplateName(), node.jjtGetChild(0)
- .getLine(), node.jjtGetChild(0).getColumn());
- }
- }
-
- /**
- * Get the image to render
- * @param node node
- * @return image or null, if not found
- * @throws NodeException
- */
- protected ImageFile getImage(InternalContextAdapter context, Node node) throws NodeException {
- Transaction t = TransactionManager.getCurrentTransaction();
-
- Object imageChild = node.jjtGetChild(ARGS_IMAGE).value(context);
- if (imageChild instanceof Resolvable) {
- Resolvable resolvable = (Resolvable)imageChild;
- if (ObjectTransformer.getBoolean(resolvable.get("isimage"), false)) {
- return t.getObject(ImageFile.class, ObjectTransformer.getInt(resolvable.get("id"), 0));
- }
- } else {
- return t.getObject(ImageFile.class, ObjectTransformer.getInt(imageChild, 0));
- }
-
- return null;
- }
-
- /**
- * Get the resize info
- * @param context context
- * @param node node
- * @return resize info
- * @throws NodeException
- */
- @SuppressWarnings("unchecked")
- protected ResizeInfo getResizeInfo(InternalContextAdapter context, Node node) throws NodeException {
- return new ResizeInfo((Map)node.jjtGetChild(ARGS_RESIZE).value(context));
- }
-
- /**
- * Get the crop info (may be null)
- * @param context context
- * @param node node
- * @return crop info (or null)
- * @throws NodeException
- */
- @SuppressWarnings("unchecked")
- protected CropInfo getCropInfo(InternalContextAdapter context, Node node) throws NodeException {
- if (node.jjtGetNumChildren() > ARGS_CROP) {
- return new CropInfo((Map)node.jjtGetChild(ARGS_CROP).value(context));
- } else {
- return null;
- }
- }
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/render/GisRendering.java b/cms-core/src/main/java/com/gentics/contentnode/render/GisRendering.java
index aa77478c35..5624300665 100644
--- a/cms-core/src/main/java/com/gentics/contentnode/render/GisRendering.java
+++ b/cms-core/src/main/java/com/gentics/contentnode/render/GisRendering.java
@@ -5,8 +5,6 @@
import java.util.HashMap;
import java.util.Map;
-import org.apache.velocity.exception.MethodInvocationException;
-
import com.gentics.api.lib.etc.ObjectTransformer;
import com.gentics.api.lib.exception.NodeException;
import com.gentics.api.lib.resolving.PropertyResolver;
@@ -286,7 +284,7 @@ public static class ResizeInfo {
/**
* Create an instance, filled with data from the given map
* @param map map
- * @throws MethodInvocationException
+ * @throws NodeException
*/
public ResizeInfo(Map map) throws NodeException {
width = ObjectTransformer.getInt(map.get(WIDTH_ARG), width);
diff --git a/cms-core/src/main/java/com/gentics/contentnode/render/RenderDirective.java b/cms-core/src/main/java/com/gentics/contentnode/render/RenderDirective.java
deleted file mode 100644
index ae88b61dae..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/render/RenderDirective.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.gentics.contentnode.render;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.velocity.context.InternalContextAdapter;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.exception.TemplateInitException;
-import org.apache.velocity.runtime.RuntimeServices;
-import org.apache.velocity.runtime.directive.Directive;
-import org.apache.velocity.runtime.parser.ParserTreeConstants;
-import org.apache.velocity.runtime.parser.node.Node;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.aloha.AlohaRenderer;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.object.Tag;
-import com.gentics.contentnode.parser.ContentRenderer;
-import com.gentics.contentnode.parser.tag.ParserTag;
-import com.gentics.contentnode.parser.tag.struct.ParseStructRenderer;
-import com.gentics.contentnode.render.RenderableResolvable.Scope;
-import com.gentics.lib.render.Renderable;
-
-/**
- * Velocity Directive for rendering objects.
- * If a string is given, the system will try to resolve the string in the current scope and handle the resolved object afterwards.
- * For objects given to the directive that implement {@link Renderable},
- * the method {@link Renderable#render(com.gentics.contentnode.render.RenderResult)} will be called. Otherwise the method {@link #toString()} will be called.
- */
-public class RenderDirective extends Directive {
-
- /* (non-Javadoc)
- * @see org.apache.velocity.runtime.directive.Directive#getName()
- */
- @Override
- public String getName() {
- return "gtx_render";
- }
-
- /* (non-Javadoc)
- * @see org.apache.velocity.runtime.directive.Directive#getType()
- */
- @Override
- public int getType() {
- return LINE;
- }
-
- @Override
- public void init(RuntimeServices rs, InternalContextAdapter context, Node node) throws TemplateInitException {
- super.init(rs, context, node);
-
- int argCount = node.jjtGetNumChildren();
- if (argCount == 0) {
- throw new TemplateInitException("#" + getName() + "() requires exactly one argument", context.getCurrentTemplateName(), node.getColumn(),
- node.getLine());
- }
- if (argCount > 1) {
- // use line/col of second argument
- throw new TemplateInitException("#" + getName() + "() requires exactly one argument", context.getCurrentTemplateName(), node.jjtGetChild(1)
- .getColumn(), node.jjtGetChild(1).getLine());
- }
-
- Node childNode = node.jjtGetChild(0);
- if (childNode.getType() != ParserTreeConstants.JJTREFERENCE && childNode.getType() != ParserTreeConstants.JJTSTRINGLITERAL) {
- throw new TemplateInitException("#" + getName() + "() argument must be a reference or a string", context.getCurrentTemplateName(),
- childNode.getColumn(), childNode.getLine());
- }
- }
-
- /* (non-Javadoc)
- * @see org.apache.velocity.runtime.directive.Directive#render(org.apache.velocity.context.InternalContextAdapter, java.io.Writer, org.apache.velocity.runtime.parser.node.Node)
- */
- @Override
- public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException,
- MethodInvocationException {
- try {
- Transaction t = TransactionManager.getCurrentTransaction();
- RenderType renderType = t.getRenderType();
- RenderResult renderResult = t.getRenderResult();
- Object value = node.jjtGetChild(0).value(context);
- if (value instanceof String) {
- value = renderType.getStack().resolve((String)value);
- }
- if (value instanceof RenderableResolvable) {
- RenderableResolvable renderable = (RenderableResolvable)value;
- if (renderable.getWrappedObject() instanceof Tag) {
- try (Scope scope = renderable.scope()) {
- writer.write(renderTag((Tag)renderable.getWrappedObject(), renderType, renderResult));
- }
- } else {
- writer.write(renderable.toString());
- }
- } else if (value instanceof Tag) {
- writer.write(renderTag((Tag)value, renderType, renderResult));
- } else if (value instanceof GCNRenderable) {
- writer.write(((GCNRenderable) value).render(renderResult));
- } else if (value != null) {
- writer.write(value.toString());
- }
- return true;
- } catch (NodeException e) {
- throw new MethodInvocationException("Error while rendering object", e, getName(), context.getCurrentTemplateName(), node.jjtGetChild(0)
- .getLine(), node.jjtGetChild(0).getColumn());
- }
- }
-
- /**
- * Render the given tag in the current edit mode
- * @param tag tag to render
- * @param renderType rendertype
- * @param result render result
- * @return rendered tag
- * @throws NodeException
- */
- protected String renderTag(Tag tag, RenderType renderType, RenderResult result) throws NodeException {
- int editMode = renderType.getEditMode();
-
- if ((editMode == RenderType.EM_ALOHA) && tag.isEditable()) {
- StringBuffer source = new StringBuffer();
- List omitTags = new ArrayList();
- List omitTagsEdit = new ArrayList();
- ParseStructRenderer.renderEditableTag(source, tag.render(result), tag, omitTags, omitTagsEdit, result);
- return source.toString();
- } else if (editMode == RenderType.EM_ALOHA_READONLY) {
- AlohaRenderer alohaRenderer = (AlohaRenderer) RendererFactory.getRenderer(ContentRenderer.RENDERER_ALOHA);
- return alohaRenderer.block(tag.render(result), tag, result);
- } else {
- return tag.render(result);
-}
- }
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/render/RenderUtils.java b/cms-core/src/main/java/com/gentics/contentnode/render/RenderUtils.java
index b436e4206b..f7f3b8b36b 100644
--- a/cms-core/src/main/java/com/gentics/contentnode/render/RenderUtils.java
+++ b/cms-core/src/main/java/com/gentics/contentnode/render/RenderUtils.java
@@ -8,7 +8,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.net.ssl.SSLContext;
@@ -27,8 +26,6 @@
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
-import org.apache.velocity.context.InternalContextAdapter;
-
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gentics.api.lib.etc.ObjectTransformer;
import com.gentics.api.lib.exception.NodeException;
@@ -181,45 +178,6 @@ public static String getPreviewTemplate(Page page, int renderMode, String tag) t
return template;
}
- /**
- * Get parameter passed to a VTL Directive as object
- * @param object type
- * @param clazz expected object class
- * @param context vtl context
- * @param node vtl node
- * @param index index of the parameter (starting with 0)
- * @return object instance or null, if not found
- */
- public static T getVtlDirectiveObject(Class clazz, InternalContextAdapter context,
- org.apache.velocity.runtime.parser.node.Node node, int index) {
- return getVtlDirectiveObject(clazz, context, node, index, null);
- }
-
- /**
- * Get parameter passed to a VTL Directive as object
- * @param object type
- * @param clazz expected object class
- * @param context vtl context
- * @param node vtl node
- * @param index index of the parameter (starting with 0)
- * @param defaultSupplier supplier for the default value (null for no default value)
- * @return object instance or instance supplied by defaultSupplier or null
- */
- public static T getVtlDirectiveObject(Class clazz, InternalContextAdapter context,
- org.apache.velocity.runtime.parser.node.Node node, int index, Supplier defaultSupplier) {
- org.apache.velocity.runtime.parser.node.Node child = null;
- if (node.jjtGetNumChildren() > index) {
- child = node.jjtGetChild(index);
- }
- if (child != null) {
- return mapper.convertValue(child.value(context), clazz);
- } else if (defaultSupplier != null) {
- return defaultSupplier.get();
- } else {
- return null;
- }
- }
-
/**
* Get the parameters from handlebars options filled into an instance of the given class
* @param type of requested class
diff --git a/cms-core/src/main/java/com/gentics/contentnode/resolving/ResolvableMapWrapper.java b/cms-core/src/main/java/com/gentics/contentnode/resolving/ResolvableMapWrapper.java
index 060dc4c3d9..7989ddcd48 100644
--- a/cms-core/src/main/java/com/gentics/contentnode/resolving/ResolvableMapWrapper.java
+++ b/cms-core/src/main/java/com/gentics/contentnode/resolving/ResolvableMapWrapper.java
@@ -84,7 +84,7 @@ public Object get(int index) {
};
} else if (value instanceof Map, ?> mapValue) {
- Map wrappedMap = value instanceof SortedMap, ?> ? new LinkedHashMap<>(mapValue.size())
+ Map wrappedMap = value instanceof LinkedHashMap, ?> ? new LinkedHashMap<>(mapValue.size())
: new HashMap<>();
mapValue.forEach((k, v) -> {
wrappedMap.put(k, wrap(v, context, mother));
diff --git a/cms-core/src/main/java/com/gentics/contentnode/rest/RestrictiveDiffUberspector.java b/cms-core/src/main/java/com/gentics/contentnode/rest/RestrictiveDiffUberspector.java
deleted file mode 100644
index 171f273939..0000000000
--- a/cms-core/src/main/java/com/gentics/contentnode/rest/RestrictiveDiffUberspector.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.gentics.contentnode.rest;
-
-import org.apache.velocity.util.introspection.Info;
-import org.apache.velocity.util.introspection.Uberspect;
-import org.apache.velocity.util.introspection.UberspectImpl;
-import org.apache.velocity.util.introspection.VelMethod;
-
-/**
- * Implementation of an {@link Uberspect} that restricts access to methods.
- */
-public class RestrictiveDiffUberspector extends UberspectImpl {
-
- /* (non-Javadoc)
- * @see org.apache.velocity.util.introspection.UberspectImpl#getMethod(java.lang.Object, java.lang.String, java.lang.Object[], org.apache.velocity.util.introspection.Info)
- */
- public VelMethod getMethod(Object arg0, String arg1, Object[] arg2, Info arg3) throws Exception {
- throw new Exception("Illegal access to method");
- }
-}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/rest/resource/impl/DiffResourceImpl.java b/cms-core/src/main/java/com/gentics/contentnode/rest/resource/impl/DiffResourceImpl.java
index f4f3e572c1..fc89964608 100644
--- a/cms-core/src/main/java/com/gentics/contentnode/rest/resource/impl/DiffResourceImpl.java
+++ b/cms-core/src/main/java/com/gentics/contentnode/rest/resource/impl/DiffResourceImpl.java
@@ -2,33 +2,27 @@
import java.io.StringWriter;
import java.util.List;
-import java.util.Properties;
import java.util.regex.Pattern;
-import jakarta.ws.rs.POST;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.WebApplicationException;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.core.Response.Status;
-
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.VelocityEngine;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
-import org.apache.velocity.runtime.resource.util.StringResourceRepository;
-
import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.contentnode.rest.RestrictiveDiffUberspector;
import com.gentics.contentnode.rest.model.request.DaisyDiffRequest;
import com.gentics.contentnode.rest.model.request.DiffRequest;
import com.gentics.contentnode.rest.model.response.DiffResponse;
import com.gentics.contentnode.rest.resource.DiffResource;
import com.gentics.contentnode.string.CNStringUtils;
import com.gentics.lib.etc.StringUtils;
+import com.github.jknack.handlebars.Context;
+import com.github.jknack.handlebars.Handlebars;
+import com.github.jknack.handlebars.Template;
+import com.github.jknack.handlebars.io.StringTemplateSource;
+
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
/**
* This resource implements the diff tool in the REST API, which can be used to
@@ -39,32 +33,11 @@
public class DiffResourceImpl implements DiffResource {
/**
- * Shared instance of the VelocityEngine used in calls to
+ * Shared instance of Handlebars used in calls to
* {@link DiffResourceImpl#diffHTML(DiffRequest)} and
* {@link DiffResourceImpl#diffSource(DiffRequest)}.
*/
- protected static VelocityEngine diffEngine;
-
- /**
- * Get the shared instance of the VelocityEngine.
- * @return VelocityEngine
- * @throws Exception
- */
- protected static synchronized VelocityEngine getDiffEngine() throws Exception {
- if (diffEngine == null) {
- // initialize a new VelocityEngine, that has a very restrictive Uberspector and uses the StringResourceLoader
- Properties vtlProps = new Properties();
-
- vtlProps.setProperty("runtime.introspector.uberspect", RestrictiveDiffUberspector.class.getName());
- vtlProps.setProperty("resource.loader", "string");
- vtlProps.setProperty("string.resource.loader.description", "Velocity StringResource loader");
- vtlProps.setProperty("string.resource.loader.class", "org.apache.velocity.runtime.resource.loader.StringResourceLoader");
- vtlProps.setProperty("string.resource.loader.repository.class", "org.apache.velocity.runtime.resource.loader.StringResourceRepositoryImpl");
-
- diffEngine = new VelocityEngine(vtlProps);
- }
- return diffEngine;
- }
+ protected static Handlebars diffEngine = new Handlebars();
/* (non-Javadoc)
* @see com.gentics.contentnode.rest.api.DiffResource#daisyDiff(com.gentics.contentnode.rest.model.request.DaisyDiffRequest)
@@ -133,10 +106,8 @@ public DiffResponse diffSource(DiffRequest request) {
* html
* @return rendered diff
* @throws Exception
- * @throws ParseErrorException
- * @throws ResourceNotFoundException
*/
- protected String renderDiff(DiffRequest request, boolean diffSource) throws ResourceNotFoundException, ParseErrorException, Exception {
+ protected String renderDiff(DiffRequest request, boolean diffSource) throws Exception {
// first generate the diff
List diff = StringUtils.diffHTMLStrings(request.getContent1(), request.getContent2(), diffSource, request.getIgnoreRegex());
@@ -144,9 +115,12 @@ protected String renderDiff(DiffRequest request, boolean diffSource) throws Reso
StringWriter diffWriter = new StringWriter();
// initialize the templates
- Template changeTemplate = parseTemplate(ObjectTransformer.getString(request.getChangeTemplate(), DiffRequest.DEFAULT_CHANGE_TEMPLATE));
- Template insertTemplate = parseTemplate(ObjectTransformer.getString(request.getInsertTemplate(), DiffRequest.DEFAULT_INSERT_TEMPLATE));
- Template removeTemplate = parseTemplate(ObjectTransformer.getString(request.getRemoveTemplate(), DiffRequest.DEFAULT_REMOVE_TEMPALTE));
+ Template changeTemplate = diffEngine.compile(new StringTemplateSource("change",
+ ObjectTransformer.getString(request.getChangeTemplate(), DiffRequest.DEFAULT_CHANGE_TEMPLATE)));
+ Template insertTemplate = diffEngine.compile(new StringTemplateSource("insert",
+ ObjectTransformer.getString(request.getInsertTemplate(), DiffRequest.DEFAULT_INSERT_TEMPLATE)));
+ Template removeTemplate = diffEngine.compile(new StringTemplateSource("remove",
+ ObjectTransformer.getString(request.getRemoveTemplate(), DiffRequest.DEFAULT_REMOVE_TEMPALTE)));
int wordsBefore = ObjectTransformer.getInt(request.getWordsBefore(), DiffRequest.DEFAULT_WORDS_BEFORE);
int wordsAfter = ObjectTransformer.getInt(request.getWordsAfter(), DiffRequest.DEFAULT_WORDS_AFTER);
@@ -173,24 +147,24 @@ protected String renderDiff(DiffRequest request, boolean diffSource) throws Reso
String after = getWords(diff, i + 1, i + 1 + wordsAfter);
// populate the context
- VelocityContext ctx = new VelocityContext();
-
- ctx.put("insert", insert);
- ctx.put("remove", remove);
- ctx.put("before", before);
- ctx.put("after", after);
+ Context ctx = Context.newBuilder(null)
+ .combine("insert", insert)
+ .combine("remove", remove)
+ .combine("before", before)
+ .combine("after", after)
+ .build();
switch (diffPart.getDiffType()) {
case StringUtils.DiffPart.TYPE_CHANGE:
- changeTemplate.merge(ctx, diffWriter);
+ changeTemplate.apply(ctx, diffWriter);
break;
case StringUtils.DiffPart.TYPE_INSERT:
- insertTemplate.merge(ctx, diffWriter);
+ insertTemplate.apply(ctx, diffWriter);
break;
case StringUtils.DiffPart.TYPE_REMOVE:
- removeTemplate.merge(ctx, diffWriter);
+ removeTemplate.apply(ctx, diffWriter);
break;
default:
@@ -230,26 +204,4 @@ private String getWords(List diffList, int start, int end) {
return out.toString();
}
-
- /**
- * Parse the given source into a template
- *
- * @param source
- * source to parse into a template
- * @return Template
- * @throws ResourceNotFoundException
- * @throws ParseErrorException
- * @throws Exception
- */
- protected Template parseTemplate(String source) throws ResourceNotFoundException, ParseErrorException, Exception {
- VelocityEngine diffEngine = getDiffEngine();
- String templateName = "DiffResource-" + Thread.currentThread().getName();
- StringResourceRepository srr = StringResourceLoader.getRepository();
-
- srr.putStringResource(templateName, source);
- Template template = diffEngine.getTemplate(templateName);
-
- srr.removeStringResource(templateName);
- return template;
- }
}
diff --git a/cms-core/src/main/java/com/gentics/contentnode/rest/resource/impl/PartTypeResourceImpl.java b/cms-core/src/main/java/com/gentics/contentnode/rest/resource/impl/PartTypeResourceImpl.java
index a41189f3b9..b3b0f9fa4c 100644
--- a/cms-core/src/main/java/com/gentics/contentnode/rest/resource/impl/PartTypeResourceImpl.java
+++ b/cms-core/src/main/java/com/gentics/contentnode/rest/resource/impl/PartTypeResourceImpl.java
@@ -1,59 +1,76 @@
package com.gentics.contentnode.rest.resource.impl;
-import static com.gentics.contentnode.factory.Trx.supply;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import com.gentics.api.lib.exception.NodeException;
import com.gentics.contentnode.db.DBUtils;
-import com.gentics.contentnode.db.DBUtils.PrepareStatement;
+import com.gentics.contentnode.etc.ContentNodeHelper;
+import com.gentics.contentnode.factory.PartTypeFactory;
+import com.gentics.contentnode.factory.Trx;
+import com.gentics.contentnode.resolving.ResolvableWrapper;
import com.gentics.contentnode.rest.filters.Authenticated;
import com.gentics.contentnode.rest.model.PartType;
+import com.gentics.contentnode.rest.model.response.PartTypeListResponse;
import com.gentics.contentnode.rest.resource.PartTypeResource;
import com.gentics.contentnode.rest.resource.parameter.FilterParameterBean;
-import java.util.ArrayList;
-import java.util.List;
+import com.gentics.contentnode.rest.resource.parameter.PagingParameterBean;
+import com.gentics.contentnode.rest.resource.parameter.PartTypeListParameterBean;
+import com.gentics.contentnode.rest.resource.parameter.SortParameterBean;
+import com.gentics.contentnode.rest.util.Filter;
+import com.gentics.contentnode.rest.util.ListBuilder;
+import com.gentics.contentnode.rest.util.ResolvableComparator;
+import com.gentics.contentnode.rest.util.ResolvableFilter;
+
import jakarta.ws.rs.BeanParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
-import org.apache.commons.lang3.StringUtils;
-@Produces({MediaType.APPLICATION_JSON})
+@Produces({ MediaType.APPLICATION_JSON })
@Authenticated
@Path("/parttype")
public class PartTypeResourceImpl implements PartTypeResource {
+ @GET
+ public PartTypeListResponse list(@BeanParam FilterParameterBean filter, @BeanParam SortParameterBean sorting,
+ @BeanParam PagingParameterBean paging, @BeanParam PartTypeListParameterBean partTypeFilter) throws NodeException {
+ try (Trx trx = ContentNodeHelper.trx()) {
+ PartTypeFactory factory = PartTypeFactory.getInstance();
+ List> partTypes = DBUtils.select("SELECT * FROM `type`", rs -> {
+ List> types = new ArrayList<>();
+ while (rs.next()) {
+ PartType partType = new PartType()
+ .setId(rs.getInt("id"))
+ .setName(rs.getString("name"))
+ .setDescription(rs.getString("description"))
+ .setJavaClass(rs.getString("javaclass"))
+ .setDeprecated(rs.getBoolean("deprecated"));
- @GET
- public List list(
- @BeanParam FilterParameterBean filter) throws NodeException {
- return supply(() -> {
- PrepareStatement prepare = getPrepareStatement(filter);
- String filterQuery = prepare == null ? "" : " WHERE `deprecated` like ? OR name like ?";
-
- return DBUtils.select("SELECT * FROM `type`" + filterQuery, prepare, (resultSet) -> {
- List partTypes = new ArrayList<>();
+ if (factory.isAvailable(partType.getId())) {
+ types.add(new ResolvableWrapper<>(partType));
+ }
- while (resultSet.next()) {
- partTypes.add(new PartType().buildFromResultSet(resultSet));
- }
- return partTypes;
- });
- });
- }
+ }
+ return types;
+ });
- private PrepareStatement getPrepareStatement(FilterParameterBean filter){
- PrepareStatement prepare = null;
+ trx.success();
- if (filter != null && StringUtils.isNotEmpty(filter.query)) {
- prepare = (p) -> {
- p.setString(1, filter.query);
- p.setString(2, "%"+filter.query + "%");
- };
- }
-
- return prepare;
- }
+ Filter> deprecatedFilter = Optional.ofNullable(partTypeFilter)
+ .map(f -> f.deprecated).map(deprecated -> (Filter>) object -> object
+ .unwrap().isDeprecated() == deprecated)
+ .orElse(null);
+ return ListBuilder.from(partTypes, ResolvableWrapper::unwrap)
+ .filter(deprecatedFilter)
+ .filter(ResolvableFilter.get(filter, "name", "description", "javaClass"))
+ .sort(ResolvableComparator.get(sorting, "id", "name", "javaClass", "deprecated"))
+ .page(paging)
+ .to(new PartTypeListResponse());
+ }
+ }
}
-
diff --git a/cms-core/src/main/java/com/gentics/contentnode/runtime/NodeConfigRuntimeConfiguration.java b/cms-core/src/main/java/com/gentics/contentnode/runtime/NodeConfigRuntimeConfiguration.java
index 4857768ae5..3675b040ab 100644
--- a/cms-core/src/main/java/com/gentics/contentnode/runtime/NodeConfigRuntimeConfiguration.java
+++ b/cms-core/src/main/java/com/gentics/contentnode/runtime/NodeConfigRuntimeConfiguration.java
@@ -16,7 +16,6 @@
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
-import org.apache.velocity.app.Velocity;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -373,21 +372,4 @@ public static Map loadConfiguration() throws NodeException {
throw new NodeException(e);
}
}
-
- /**
- * initialize velocity
- * @throws Exception if there is a fatal error while initializing velocity
- */
- public static void initVelocity() throws Exception {
- NodePreferences prefs = getDefault().getNodeConfig().getDefaultPreferences();
-
- Map velocityConfig = prefs.getPropertyMap("velocity");
- for (Map.Entry entry : velocityConfig.entrySet()) {
- // we transform every value into a string, because some values, like the modificationCheckInterval
- // are expected to be Long, but will be provided by YAML config as Integer
- Velocity.setProperty(entry.getKey(), ObjectTransformer.getString(entry.getValue(), null));
- }
-
- Velocity.init();
- }
}
diff --git a/cms-core/src/main/resources/changelog/content.CHANGELOG b/cms-core/src/main/resources/changelog/content.CHANGELOG
index a427d9dedb..9db6390844 100644
--- a/cms-core/src/main/resources/changelog/content.CHANGELOG
+++ b/cms-core/src/main/resources/changelog/content.CHANGELOG
@@ -824,3 +824,4 @@
2026-03-27 CH-1741 NOP SQL ALTER TABLE node ADD COLUMN default_form_folder_id INT NOT NULL default 0;
2026-05-08 CH-1745 NOP SQL ALTER TABLE form ADD external_hash VARCHAR(255) after external_id; ## add column for external hash
2026-05-21 CH-1747 NOP SQL CREATE TABLE form_translations (formtype VARCHAR(255) NOT NULL, translations MEDIUMTEXT NOT NULL, PRIMARY KEY (formtype)); ## Add table for form translations
+2026-08-05 CH-1749 NOP SQL UPDATE type SET deprecated = 1 WHERE id IN (2, 3, 5, 9, 10, 11, 15, 16, 17, 18, 19, 20, 22, 23, 24, 26, 27, 33, 34, 35, 36, 37, 38, 39, 41);
diff --git a/cms-core/src/main/resources/packages/DefaultElements/constructs/velocity/gentics_structure.json b/cms-core/src/main/resources/packages/DefaultElements/constructs/velocity/gentics_structure.json
deleted file mode 100644
index 014fc736d5..0000000000
--- a/cms-core/src/main/resources/packages/DefaultElements/constructs/velocity/gentics_structure.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- "globalId" : "A547.69716",
- "keyword" : "velocity",
- "name" : {
- "de" : "Velocity",
- "en" : "Velocity"
- },
- "mayBeSubtag" : false,
- "mayContainsSubtags" : false,
- "editorControlStyle": "ASIDE",
- "autoEnable" : false,
- "parts" : [ {
- "globalId" : "A547.69722",
- "name" : {
- "de" : "Velocity",
- "en" : "Velocity"
- },
- "editable" : false,
- "typeId" : 33,
- "order" : 1,
- "mlId" : 0,
- "visible" : true,
- "required" : false,
- "inlineEditable" : false,
- "hideInEditor" : false,
- "regexId" : 0
- }, {
- "globalId" : "A547.69727",
- "name" : {
- "de" : "Template",
- "en" : "Template"
- },
- "keyword" : "template",
- "editable" : true,
- "typeId" : 21,
- "order" : 2,
- "mlId" : 0,
- "visible" : false,
- "required" : false,
- "inlineEditable" : false,
- "hideInEditor" : false,
- "regexId" : 0
- } ],
- "category" : {
- "globalId" : "3D6C.351d4688-4aee-11ed-9fbf-482ae36fb1c5",
- "name" : {
- "de" : "Gentics CMP Standard",
- "en" : "Gentics CMP Default"
- },
- "sortOrder" : 0
- }
-}
diff --git a/cms-core/src/main/resources/packages/DefaultElements/constructs/velocity/part.template.html b/cms-core/src/main/resources/packages/DefaultElements/constructs/velocity/part.template.html
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/cms-core/src/test/java/com/gentics/contentnode/formatter/CNDateFormatterImpTest.java b/cms-core/src/test/java/com/gentics/contentnode/formatter/CNDateFormatterImpTest.java
deleted file mode 100644
index c0234b9f94..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/formatter/CNDateFormatterImpTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package com.gentics.contentnode.formatter;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.TimeZone;
-
-import jakarta.xml.bind.JAXBException;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.api.portalnode.imp.ImpException;
-import com.gentics.contentnode.etc.ContentNodeDate;
-
-/**
- * The CNDateFormatterImpTest will test various public methods that can be
- * accessed using velocity within GCN
- *
- * @author johannes2
- *
- */
-public class CNDateFormatterImpTest {
-
- private static CNDateFormatterImp formatter;
- private final static String IMP_NAME = "bogus";
- private final static String DATE_FORMAT = "dd MMM yyyy HH:mm:ss";
- private final static String DATE_RESULT = "01 Jan 1970 01:00:00";
- private final static String DATE_RESULT_DE = "01 Jan. 1970 01:00:00";
- private final static long FIXED_DATE_IN_2014 = 1397478595585L;
-
- @BeforeClass
- public static void setupOnce() throws JAXBException, ImpException, NodeException {
- // The tests assume UTC+1 and english locale
- TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
- Locale.setDefault(new Locale("en", "US"));
-
- formatter = new CNDateFormatterImp();
- formatter.init(IMP_NAME, new HashMap());
- }
-
- @Test
- public void testIntegerFormat() {
- String dateString = formatter.format(new Integer(2), DATE_FORMAT);
- assertEquals("01 Jan 1970 01:00:00", dateString);
- }
-
- @Test
- public void testFormatCNDates() {
- ContentNodeDate cnDate = new ContentNodeDate(0);
- assertEquals("01 Jan 1970 01:00:00", formatter.format(cnDate, DATE_FORMAT));
- }
-
- @Test
- public void simpleFormatterTest() throws ImpException, JAXBException {
- assertNotNull(formatter.format(DATE_FORMAT));
- assertEquals("The result should match the expected format", DATE_RESULT, formatter.format((Object) new Date(1), DATE_FORMAT));
- assertNotNull(formatter.format(DATE_FORMAT, "DE"));
- assertEquals("The result should match the expected format", DATE_RESULT_DE, formatter.format(new Date(1), DATE_FORMAT, "DE"));
- assertEquals("The result should match the expected format", DATE_RESULT_DE, formatter.format((Object) new Date(1), DATE_FORMAT, "DE"));
- }
-
- @Test
- public void testFormatDate() {
- String input = "1.1.2014 12:30";
- assertEquals("Input should match the output.", input, formatter.format(input));
-
- assertEquals("The dates should match.", DATE_RESULT, formatter.format(new Date(1), DATE_FORMAT));
- assertEquals("The dates should match.", DATE_RESULT, formatter.format((Object) new Date(1), DATE_FORMAT));
- assertNotNull(formatter.format(DATE_FORMAT, "EN"));
- assertEquals("The dates should match.", DATE_RESULT, formatter.format(new Date(1), DATE_FORMAT, "EN"));
- assertEquals("The dates should match.", DATE_RESULT, formatter.format((Object) new Date(1), DATE_FORMAT, "EN"));
- }
-
- @Test
- public void testFromTimestamp() {
- Date date = formatter.fromTimestamp(1000);
- assertEquals("Both dates should match", new Date(1000 * 1000).getTime(), date.getTime());
- date = formatter.fromTimestamp("1000");
- assertEquals("Both dates should match", new Date(1000 * 1000).getTime(), date.getTime());
- }
-
- /**
- * Test a common usecase for the dateformatter imp.
- */
- @Test
- public void testFormatterUsecase() {
- String date = formatter.format(formatter.fromTimestamp(1000), "MMMM dd, yyyy", "en");
- assertEquals("January 01, 1970", date);
- }
-
- @Test
- public void testParseDate() {
- String inputDate = "2014-03-12 12:30";
- Date date = formatter.parse(inputDate, DATE_FORMAT, "EN");
- assertNull("The given datestring should not be parseable by the given pattern", date);
-
- date = formatter.parse(inputDate, DATE_FORMAT, "DE");
- assertNull("The given datestring should not be parseable by the given pattern", date);
-
- date = formatter.parse("22 MAR 1984 12:30:00", "dd MMM yyyy HH:mm:ss", "EN");
- assertNotNull("The given datestring should be parsable", date);
-
- }
-
- @Test
- public void testDateDiff() {
- long diff = formatter.dateDiff(new Date(0), new Date(1));
- assertEquals("Diff does not match", 1, diff);
- diff = formatter.dateDiff((Object) new Date(1), (Object) new Date(2));
- assertEquals("diff does not match", 1, diff);
-
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "y");
- assertEquals("Years since 1970 do not match", 44, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "M");
- assertEquals("Months since 1970 do not match", 531, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "w");
- assertEquals("Weeks since 1970 do not match", 2310, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "d");
- assertEquals("Days since 1970 do not match", 16174, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "h");
- assertEquals("Hours since 1970 do not match", 388188, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "m");
- assertEquals("Minutes since 1970 do not match", 23291309, diff);
- diff = formatter.dateDiff(new Date(1), new Date(FIXED_DATE_IN_2014), "s");
- assertEquals("Seconds since 1970 do not match", 1397478595, diff);
- diff = formatter.dateDiff((Object) new Date(0), (Object) new Date(FIXED_DATE_IN_2014), "M");
- assertEquals("Months since 1970 do not match.", 531, diff);
- diff = formatter.dateDiff((Object) new Date(0), (Object) new Date(FIXED_DATE_IN_2014), "y");
- assertEquals("44 Years have past since 1970.", 44, diff);
- }
-
- /**
- * Test various other methods of the date formatter imp
- */
- @Test
- public void testMisc() {
- assertEquals("The impname should match the name we choose during init.", IMP_NAME, formatter.getImpId());
-
- if (isDST(new Date())) {
- assertEquals("+02:00", formatter.getRfc3339Timezone());
- assertEquals("+02:00", formatter.getRfc3339Timezone(new Date()));
- } else {
- assertEquals("+01:00", formatter.getRfc3339Timezone());
- assertEquals("+01:00", formatter.getRfc3339Timezone(new Date()));
- }
- assertFalse("The given object is not a date object", formatter.isDate("1.1.2014"));
- assertTrue("The given object is a date", formatter.isDate(new Date(1)));
- assertFalse("The given object is not a date", formatter.isDate(new Integer(1)));
- }
-
- /**
- * Check whether the given date is within the daylight saving time frame
- *
- * @param date
- * @return when the date is within dst, otherwise false.
- */
- private boolean isDST(Date date) {
- Calendar c = Calendar.getInstance();
- c.setTime(date);
- int offset = c.get(Calendar.DST_OFFSET);
- if (offset == 0) {
- return false;
- }
- return true;
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/render/GisDirectiveCalculateFpCropInfoTest.java b/cms-core/src/test/java/com/gentics/contentnode/render/GisDirectiveCalculateFpCropInfoTest.java
deleted file mode 100644
index 9345583c4a..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/render/GisDirectiveCalculateFpCropInfoTest.java
+++ /dev/null
@@ -1,361 +0,0 @@
-package com.gentics.contentnode.render;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.object.ImageFile;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-import org.mockito.invocation.InvocationOnMock;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
-
-/**
- * Test cases for the {@link GisDirective#calculateFpCropInfo(ImageFile, GisDirective.ResizeInfo)} method,
- * which handles CropInfo calculation for the "fpsmart" resize mode of the #gtx_gis directive.
- */
-@RunWith(Parameterized.class)
-public class GisDirectiveCalculateFpCropInfoTest {
-
- /**
- * Since GisDirective.CropInfo is not publicly accessible and not
- * easily constructible without a HashMap, we use this class.
- */
- protected static class CropRectangle {
- int x;
- int y;
- int width;
- int height;
-
- public CropRectangle(int x, int y, int width, int height) {
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- }
-
- @Override
- public String toString() {
- return "(x: " + x + " y: " + y + " width: " + width + " height: " + height + ")";
- }
- }
-
- /**
- * Provides access to the protected {@link GisDirective#calculateFpCropInfo(ImageFile, ResizeInfo)} method.
- */
- protected static class GisDirectiveAdapter extends GisDirective {
-
- /**
- * Calls the {@link GisDirective#calculateFpCropInfo(ImageFile, ResizeInfo)} method and returns
- * the result as a CropRectangle.
- */
- public CropRectangle calculateFpCropInfo(ImageFile image, int resizeWidth, int resizeHeight) throws NodeException {
- Map resizeInfoMap = new HashMap<>();
- resizeInfoMap.put(GisRendering.WIDTH_ARG, resizeWidth);
- resizeInfoMap.put(GisRendering.HEIGHT_ARG, resizeHeight);
- resizeInfoMap.put(GisRendering.MODE_ARG, GisRendering.Mode.fpsmart.toString());
- resizeInfoMap.put(GisRendering.TYPE_ARG, GisRendering.Type.url.toString());
- GisRendering.ResizeInfo resizeInfo = new GisRendering.ResizeInfo(resizeInfoMap);
-
- GisRendering.CropInfo cropInfo = GisRendering.calculateFpCropInfo(image, resizeInfo);
- return new CropRectangle(cropInfo.x, cropInfo.y, cropInfo.width, cropInfo.height);
- }
-
- }
-
- /**
- * Provides a toString() for mocked images.
- */
- protected static String imageFileToString(InvocationOnMock invocation) {
- ImageFile image = (ImageFile) invocation.getMock();
- return "(width: " + image.getSizeX() + " height: " + image.getSizeY() + " fpX: " + image.getFpX() + " fpY: " + image.getFpY() + ")";
- }
-
- /**
- * Get the test parameters
- * @return collection of test parameter sets
- */
- @Parameters(name = "{index}: image: {0}, resizeWidth: {1}, resizeHeight: {2}, expectedCropRect: {3}")
- public static Collection data() {
- Collection data = new ArrayList<>();
-
- ImageFile image;
- int resizeWidth, resizeHeight;
- CropRectangle expectedCropRect;
-
- // Shrink 4:3 image to 16:9 with focal point at center.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(4000);
- when(image.getSizeY()).thenReturn(3000);
- when(image.getFpX()).thenReturn(0.5f);
- when(image.getFpY()).thenReturn(0.5f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1600;
- resizeHeight = 900;
- expectedCropRect = new CropRectangle(0, 375, 4000, 2250);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Shrink 4:3 image to 9:16 with focal point at center.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(4000);
- when(image.getSizeY()).thenReturn(3000);
- when(image.getFpX()).thenReturn(0.5f);
- when(image.getFpY()).thenReturn(0.5f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 900;
- resizeHeight = 1600;
- expectedCropRect = new CropRectangle(1157, 0, 1687, 3000);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Shrink 4:3 image to 1:1 with focal point at center.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(4000);
- when(image.getSizeY()).thenReturn(3000);
- when(image.getFpX()).thenReturn(0.5f);
- when(image.getFpY()).thenReturn(0.5f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1000;
- resizeHeight = 1000;
- expectedCropRect = new CropRectangle(500, 0, 3000, 3000);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Enlarge 4:3 image to 16:9 with focal point at center.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(400);
- when(image.getSizeY()).thenReturn(300);
- when(image.getFpX()).thenReturn(0.5f);
- when(image.getFpY()).thenReturn(0.5f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1600;
- resizeHeight = 900;
- expectedCropRect = new CropRectangle(0, 38, 400, 225);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Enlarge 4:3 image to 9:16 with focal point at center.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(400);
- when(image.getSizeY()).thenReturn(300);
- when(image.getFpX()).thenReturn(0.5f);
- when(image.getFpY()).thenReturn(0.5f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 900;
- resizeHeight = 1600;
- expectedCropRect = new CropRectangle(116, 0, 168, 300);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Enlarge 4:3 image to 1:1 with focal point at center.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(400);
- when(image.getSizeY()).thenReturn(300);
- when(image.getFpX()).thenReturn(0.5f);
- when(image.getFpY()).thenReturn(0.5f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1000;
- resizeHeight = 1000;
- expectedCropRect = new CropRectangle(50, 0, 300, 300);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Shrink 16:9 image to 4:3 with focal point at top left.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(1600);
- when(image.getSizeY()).thenReturn(900);
- when(image.getFpX()).thenReturn(0.1f);
- when(image.getFpY()).thenReturn(0.1f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 400;
- resizeHeight = 300;
- expectedCropRect = new CropRectangle(0, 0, 1200, 900);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Shrink 16:9 image to 4:3 with focal point at top right.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(1600);
- when(image.getSizeY()).thenReturn(900);
- when(image.getFpX()).thenReturn(0.9f);
- when(image.getFpY()).thenReturn(0.1f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 400;
- resizeHeight = 300;
- expectedCropRect = new CropRectangle(400, 0, 1200, 900);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Shrink 16:9 image to 4:3 with focal point at bottom right.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(1600);
- when(image.getSizeY()).thenReturn(900);
- when(image.getFpX()).thenReturn(0.9f);
- when(image.getFpY()).thenReturn(0.9f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 400;
- resizeHeight = 300;
- expectedCropRect = new CropRectangle(400, 0, 1200, 900);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Shrink 16:9 image to 4:3 with focal point at bottom left.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(1600);
- when(image.getSizeY()).thenReturn(900);
- when(image.getFpX()).thenReturn(0.1f);
- when(image.getFpY()).thenReturn(0.9f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 400;
- resizeHeight = 300;
- expectedCropRect = new CropRectangle(0, 0, 1200, 900);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Shrink 4:3 image to 16:9 with focal point at top left.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(4000);
- when(image.getSizeY()).thenReturn(3000);
- when(image.getFpX()).thenReturn(0.1f);
- when(image.getFpY()).thenReturn(0.1f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1600;
- resizeHeight = 900;
- expectedCropRect = new CropRectangle(0, 0, 4000, 2250);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Shrink 4:3 image to 16:9 with focal point at top right.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(4000);
- when(image.getSizeY()).thenReturn(3000);
- when(image.getFpX()).thenReturn(0.9f);
- when(image.getFpY()).thenReturn(0.1f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1600;
- resizeHeight = 900;
- expectedCropRect = new CropRectangle(0, 0, 4000, 2250);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Shrink 4:3 image to 16:9 with focal point at bottom right.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(4000);
- when(image.getSizeY()).thenReturn(3000);
- when(image.getFpX()).thenReturn(0.9f);
- when(image.getFpY()).thenReturn(0.9f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1600;
- resizeHeight = 900;
- expectedCropRect = new CropRectangle(0, 750, 4000, 2250);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Shrink 4:3 image to 16:9 with focal point at bottom left.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(4000);
- when(image.getSizeY()).thenReturn(3000);
- when(image.getFpX()).thenReturn(0.1f);
- when(image.getFpY()).thenReturn(0.9f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1600;
- resizeHeight = 900;
- expectedCropRect = new CropRectangle(0, 750, 4000, 2250);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Enlarge 4:3 image to 1:1 with focal point at top left.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(400);
- when(image.getSizeY()).thenReturn(300);
- when(image.getFpX()).thenReturn(0.0f);
- when(image.getFpY()).thenReturn(0.0f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1000;
- resizeHeight = 1000;
- expectedCropRect = new CropRectangle(0, 0, 300, 300);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Enlarge 4:3 image to 1:1 with focal point at top right.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(400);
- when(image.getSizeY()).thenReturn(300);
- when(image.getFpX()).thenReturn(1.0f);
- when(image.getFpY()).thenReturn(0.0f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1000;
- resizeHeight = 1000;
- expectedCropRect = new CropRectangle(100, 0, 300, 300);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Enlarge 4:3 image to 1:1 with focal point at bottom right.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(400);
- when(image.getSizeY()).thenReturn(300);
- when(image.getFpX()).thenReturn(1.0f);
- when(image.getFpY()).thenReturn(1.0f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1000;
- resizeHeight = 1000;
- expectedCropRect = new CropRectangle(100, 0, 300, 300);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- // Enlarge 4:3 image to 1:1 with focal point at bottom left.
- image = mock(ImageFile.class);
- when(image.getSizeX()).thenReturn(400);
- when(image.getSizeY()).thenReturn(300);
- when(image.getFpX()).thenReturn(0.0f);
- when(image.getFpY()).thenReturn(1.0f);
- when(image.toString()).then(GisDirectiveCalculateFpCropInfoTest::imageFileToString);
- resizeWidth = 1000;
- resizeHeight = 1000;
- expectedCropRect = new CropRectangle(0, 0, 300, 300);
- data.add(new Object[] { image, resizeWidth, resizeHeight, expectedCropRect });
-
- return data;
- }
-
-
- /**
- * Create a test instance
- * @param image the image, on which the cropping calculation should be tested
- * @param resizeWidth the width, to which the image should be resized
- * @param resizeHeight the height, to which the image should be resized
- * @param expectedCropRect the expected result
- */
- public GisDirectiveCalculateFpCropInfoTest(ImageFile image, int resizeWidth, int resizeHeight, CropRectangle expectedCropRect) {
- this.image = image;
- this.resizeWidth = resizeWidth;
- this.resizeHeight = resizeHeight;
- this.expectedCropRect = expectedCropRect;
- }
-
- /**
- * the image, on which the cropping calculation should be tested
- */
- protected ImageFile image;
-
- /**
- * the width, to which the image should be resized
- */
- protected int resizeWidth;
-
- /**
- * the height, to which the image should be resized
- */
- protected int resizeHeight;
-
- /**
- * the expected result
- */
- protected CropRectangle expectedCropRect;
-
-
- /**
- * Test calculation of CropInfo with a focal point.
- * @throws Exception
- */
- @Test
- public void testCalculateFpCropInfo() throws Exception {
- GisDirectiveAdapter gisDirective = new GisDirectiveAdapter();
- CropRectangle actualCropRect = gisDirective.calculateFpCropInfo(image, resizeWidth, resizeHeight);
- assertEquals("CropInfo.x does not match the expected value", expectedCropRect.x, actualCropRect.x);
- assertEquals("CropInfo.y does not match the expected value", expectedCropRect.y, actualCropRect.y);
- assertEquals("CropInfo.width does not match the expected value", expectedCropRect.width, actualCropRect.width);
- assertEquals("CropInfo.height does not match the expected value", expectedCropRect.height, actualCropRect.height);
- }
-
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/dirting/AbstractPageDirtingTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/dirting/AbstractPageDirtingTest.java
index 49f3a76d76..ab66ba4047 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/dirting/AbstractPageDirtingTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/dirting/AbstractPageDirtingTest.java
@@ -10,6 +10,7 @@
import java.util.List;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Rule;
import com.gentics.api.lib.etc.ObjectTransformer;
@@ -30,8 +31,11 @@
import com.gentics.contentnode.object.parttype.OverviewPartType;
import com.gentics.contentnode.object.parttype.PageTagPartType;
import com.gentics.contentnode.object.parttype.PageURLPartType;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
import com.gentics.contentnode.testutils.DBTestContext;
+import com.gentics.contentnode.testutils.LoaderHelperSource;
+import com.gentics.contentnode.testutils.TestHelpersHandlebarsService;
import com.gentics.lib.db.SQLExecutor;
public class AbstractPageDirtingTest {
@@ -45,9 +49,7 @@ public class AbstractPageDirtingTest {
protected static final String URL_PARTNAME = "url";
- protected static final String VTL_PARTNAME = "vtl";
-
- protected static final String TEMPLATE_PARTNAME = "template";
+ protected static final String HBS_PARTNAME = "hbs";
protected static final String OVERVIEW_PARTNAME = "ds";
@@ -92,19 +94,19 @@ public class AbstractPageDirtingTest {
protected int pagetagPageId;
/**
- * ID of the page rendering a vtl list
+ * ID of the page rendering a hbs list
*/
- protected int vtlListPage;
+ protected int hbsListPage;
/**
* ID of the page rendering another page after loading it
*/
- protected int vtlLoaderPage;
+ protected int hbsLoaderPage;
/**
* ID of the page rendering the publishdate of another page after loading it
*/
- protected int vtlPdatePage;
+ protected int hbsPdatePage;
/**
* ID of the page rendering a manual page overview
@@ -126,6 +128,11 @@ public class AbstractPageDirtingTest {
*/
protected List pdateDependentPages;
+ @BeforeClass
+ public static void setupOnce() {
+ TestHelpersHandlebarsService.addHelper(LoaderHelperSource.class);
+ }
+
@Before
public void setUp() throws Exception {
@@ -175,7 +182,7 @@ public void setUp() throws Exception {
targetPageId = createTargetPage(targetFolder, template);
Page targetPage = t.getObject(Page.class, targetPageId);
- int vtlConstructId = ContentNodeTestDataUtils.createVelocityConstruct(node, VTL_PARTNAME, VTL_PARTNAME);
+ int hbsConstructId = ContentNodeTestDataUtils.createConstruct(node, HandlebarsPartType.class, HBS_PARTNAME, HBS_PARTNAME);
int overviewConstructId = ContentNodeTestDataUtils.createConstruct(node, OverviewPartType.class, OVERVIEW_PARTNAME, OVERVIEW_PARTNAME);
Construct c = t.getObject(Construct.class, overviewConstructId, true);
@@ -185,16 +192,16 @@ public void setUp() throws Exception {
urlPageId = createUrlPage(folder, template, targetPage);
pagetagPageId = createPageTagPage(folder, template, targetPage);
- vtlListPage = createVtlListPage(folder, template, targetPage, vtlConstructId);
- vtlLoaderPage = createVtlLoaderPage(folder, template, targetPage, vtlConstructId);
- vtlPdatePage = createVtlPdatePage(folder, template, targetPage, vtlConstructId);
+ hbsListPage = createHbsListPage(folder, template, targetPage, hbsConstructId);
+ hbsLoaderPage = createHbsLoaderPage(folder, template, targetPage, hbsConstructId);
+ hbsPdatePage = createHbsPdatePage(folder, template, targetPage, hbsConstructId);
manualOverviewPage = createManualOverviewPage(folder, template, targetPage, overviewConstructId);
folderOverviewPage = createFolderOverviewPage(folder, template, targetPage, overviewConstructId);
// Note: the page rendering the page tag is not dependent on the
// targetpage being online
- dependentPages = Arrays.asList(urlPageId, vtlListPage, vtlLoaderPage, vtlPdatePage, manualOverviewPage, folderOverviewPage);
- pdateDependentPages = Arrays.asList(vtlPdatePage);
+ dependentPages = Arrays.asList(urlPageId, hbsListPage, hbsLoaderPage, hbsPdatePage, manualOverviewPage, folderOverviewPage);
+ pdateDependentPages = Arrays.asList(hbsPdatePage);
// run the publish process
testContext.publish(initialPublishTime);
@@ -280,7 +287,7 @@ protected int createPageTagPage(Folder folder, Template template, Page targetPag
}
/**
- * Create test page that renders a velocity list of pages
+ * Create test page that renders a handlebars list of pages
*
* @param folder
* folder
@@ -288,21 +295,22 @@ protected int createPageTagPage(Folder folder, Template template, Page targetPag
* template
* @param targetPage
* target page
- * @param vtlConstructId
- * velocity construct id
+ * @param hbsConstructId
+ * handlebars construct id
* @return test page id
* @throws NodeException
*/
- protected int createVtlListPage(Folder folder, Template template, Page targetPage, int vtlConstructId) throws NodeException {
+ protected int createHbsListPage(Folder folder, Template template, Page targetPage, int hbsConstructId) throws NodeException {
Transaction t = TransactionManager.getCurrentTransaction();
Page page = t.createObject(Page.class);
- page.setName("Vtl list page");
+ page.setName("Hbs list page");
page.setTemplateId(template.getId());
page.setFolderId(folder.getId());
- ContentTag tag = page.getContent().addContentTag(vtlConstructId);
+ ContentTag tag = page.getContent().addContentTag(hbsConstructId);
Folder targetFolder = targetPage.getFolder();
- ContentNodeTestDataUtils.getPartType(LongHTMLPartType.class, tag, TEMPLATE_PARTNAME).getValueObject().setValueText(
- "#set($folder = $cms.imps.loader.getFolder(" + targetFolder.getId() + "))#foreach($page in $folder.pages)#if($page.online)Page [$page.name]\n#end#end");
+ ContentNodeTestDataUtils.getPartType(HandlebarsPartType.class, tag, HBS_PARTNAME).getValueObject().setValueText(
+ "{{#with (gtx_test_folder %d)}}{{#each pages}}{{#if online}}Page [{{name}}]\n{{/if}}{{/each}}{{/with}}".formatted(targetFolder.getId())
+ );
page.getContentTag(CONTENT_TAGNAME).getValues().getByKeyname(TEXT_PARTNAME).setValueText("");
page.save();
page.publish();
@@ -319,20 +327,22 @@ protected int createVtlListPage(Folder folder, Template template, Page targetPag
* template
* @param targetPage
* target page
- * @param vtlConstructId
- * velocity construct id
+ * @param hbsConstructId
+ * handlebars construct id
* @return test page id
* @throws NodeException
*/
- protected int createVtlLoaderPage(Folder folder, Template template, Page targetPage, int vtlConstructId) throws NodeException {
+ protected int createHbsLoaderPage(Folder folder, Template template, Page targetPage, int hbsConstructId) throws NodeException {
Transaction t = TransactionManager.getCurrentTransaction();
Page page = t.createObject(Page.class);
- page.setName("Vtl loader page");
+ page.setName("Hbs loader page");
page.setTemplateId(template.getId());
page.setFolderId(folder.getId());
- ContentTag tag = page.getContent().addContentTag(vtlConstructId);
- ContentNodeTestDataUtils.getPartType(LongHTMLPartType.class, tag, TEMPLATE_PARTNAME).getValueObject()
- .setValueText("#set($page = $cms.imps.loader.getPage(" + targetPage.getId() + "))#if($page.online)$page.name#end");
+ ContentTag tag = page.getContent().addContentTag(hbsConstructId);
+ ContentNodeTestDataUtils.getPartType(HandlebarsPartType.class, tag, HBS_PARTNAME).getValueObject()
+ .setValueText(
+ "{{#with (gtx_test_page %d)}}{{#if online}}{{name}}{{/if}}{{/with}}".formatted(targetPage.getId())
+ );
page.getContentTag(CONTENT_TAGNAME).getValues().getByKeyname(TEXT_PARTNAME).setValueText("");
page.save();
page.publish();
@@ -350,20 +360,22 @@ protected int createVtlLoaderPage(Folder folder, Template template, Page targetP
* template
* @param targetPage
* target page
- * @param vtlConstructId
- * velocity construct id
+ * @param hbsConstructId
+ * handlebars construct id
* @return test page id
* @throws NodeException
*/
- protected int createVtlPdatePage(Folder folder, Template template, Page targetPage, int vtlConstructId) throws NodeException {
+ protected int createHbsPdatePage(Folder folder, Template template, Page targetPage, int hbsConstructId) throws NodeException {
Transaction t = TransactionManager.getCurrentTransaction();
Page page = t.createObject(Page.class);
- page.setName("Vtl pdate page");
+ page.setName("Hbs pdate page");
page.setTemplateId(template.getId());
page.setFolderId(folder.getId());
- ContentTag tag = page.getContent().addContentTag(vtlConstructId);
- ContentNodeTestDataUtils.getPartType(LongHTMLPartType.class, tag, TEMPLATE_PARTNAME).getValueObject()
- .setValueText("#set($page = $cms.imps.loader.getPage(" + targetPage.getId() + "))#if($page.online)$page.name - $page.publishtimestamp#end");
+ ContentTag tag = page.getContent().addContentTag(hbsConstructId);
+ ContentNodeTestDataUtils.getPartType(HandlebarsPartType.class, tag, HBS_PARTNAME).getValueObject()
+ .setValueText(
+ "{{#with (gtx_test_page %d)}}{{#if online}}{{name}} - {{publishtimestamp}}{{/if}}{{/with}}".formatted(targetPage.getId())
+ );
page.getContentTag(CONTENT_TAGNAME).getValues().getByKeyname(TEXT_PARTNAME).setValueText("");
page.save();
page.publish();
@@ -465,9 +477,9 @@ protected void assertPublishedContents(boolean expectOnline, int expectedPdate)
assertPublishedContent(targetPageId, "Target page: [Target content]");
assertPublishedContent(urlPageId, "Url page: [/Content.Node/Target-page.html]");
assertPublishedContent(pagetagPageId, "Pagetag page: [Target content]");
- assertPublishedContent(vtlListPage, "Vtl list page: [Page [Target page]\n]");
- assertPublishedContent(vtlLoaderPage, "Vtl loader page: [Target page]");
- assertPublishedContent(vtlPdatePage, "Vtl pdate page: [Target page - " + expectedPdate + "]");
+ assertPublishedContent(hbsListPage, "Hbs list page: [Page [Target page]\n]");
+ assertPublishedContent(hbsLoaderPage, "Hbs loader page: [Target page]");
+ assertPublishedContent(hbsPdatePage, "Hbs pdate page: [Target page - " + expectedPdate + "]");
assertPublishedContent(manualOverviewPage, "Manual overview page: [Target page]");
assertPublishedContent(folderOverviewPage, "Folder overview page: [Target page]");
} else {
@@ -481,9 +493,9 @@ protected void assertPublishedContents(boolean expectOnline, int expectedPdate)
// pages
// as
// well
- assertPublishedContent(vtlListPage, "Vtl list page: []");
- assertPublishedContent(vtlLoaderPage, "Vtl loader page: []");
- assertPublishedContent(vtlPdatePage, "Vtl pdate page: []");
+ assertPublishedContent(hbsListPage, "Hbs list page: []");
+ assertPublishedContent(hbsLoaderPage, "Hbs loader page: []");
+ assertPublishedContent(hbsPdatePage, "Hbs pdate page: []");
assertPublishedContent(manualOverviewPage, "Manual overview page: []");
assertPublishedContent(folderOverviewPage, "Folder overview page: []");
}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/edit/AbstractEditSandboxTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/edit/AbstractEditSandboxTest.java
new file mode 100644
index 0000000000..eb96f8fbd2
--- /dev/null
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/edit/AbstractEditSandboxTest.java
@@ -0,0 +1,92 @@
+package com.gentics.contentnode.tests.edit;
+
+import static com.gentics.contentnode.factory.Trx.supply;
+import static com.gentics.contentnode.tests.utils.Builder.update;
+import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createConstruct;
+import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartType;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.gentics.api.lib.exception.NodeException;
+import com.gentics.contentnode.db.DBUtils;
+import com.gentics.contentnode.object.ContentTag;
+import com.gentics.contentnode.object.Node;
+import com.gentics.contentnode.object.Page;
+import com.gentics.contentnode.object.parttype.LongHTMLPartType;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
+
+/**
+ * Abstract base class for some editing tests that test dirting with the help of pages containing vtl tags.
+ * Since vtl does not exist any more, those pages are migrated to tags containing hbs via the method {@link AbstractEditSandboxTest#migrateVtlPagesToHbsPages()}.
+ */
+public abstract class AbstractEditSandboxTest {
+ protected static Pattern FILE_LOADER = Pattern.compile("\\$cms\\.imps\\.loader\\.getFile\\((\\d+)\\)\\.(.*)");
+
+ protected static Pattern FOLDER_LOADER = Pattern.compile("\\$cms\\.imps\\.loader\\.getFolder\\((\\d+)\\)\\.(.*)");
+
+ public final static int NODE_ID = 1;
+
+ public final static int VTL_CONSTRUCT_ID = 2;
+
+ /**
+ * Migrate the pages to containing hbs tags
+ * @throws NodeException
+ */
+ protected void migrateVtlPagesToHbsPages() throws NodeException {
+ Node node = supply(t -> t.getObject(Node.class, NODE_ID));
+ int hbsConstructId = supply(() -> createConstruct(node, HandlebarsPartType.class, "hbs", "hbs"));
+
+ List pageIds = supply(() -> DBUtils.select("SELECT id FROM page WHERE folder_id IN (?, ?, ?) AND deleted = 0", pst -> {
+ pst.setInt(1, 14);
+ pst.setInt(2, 15);
+ pst.setInt(3, 17);
+ }, DBUtils.IDLIST));
+
+ // modify the target pages to replace the vtl tag by a hbs tag
+ for (int pageId : pageIds) {
+ Page page = supply(t -> t.getObject(Page.class, pageId));
+ update(page, upd -> {
+ String hbsTemplate = null;
+ String tagName = null;
+
+ for (ContentTag tag : upd.getContentTags().values()) {
+ if (Objects.equals(tag.getConstructId(), VTL_CONSTRUCT_ID)) {
+ String template = getPartType(LongHTMLPartType.class, tag, "template").getText();
+
+ Matcher fileLoaderMatcher = FILE_LOADER.matcher(template);
+ Matcher folderLoaderMatcher = FOLDER_LOADER.matcher(template);
+ if (fileLoaderMatcher.matches()) {
+ int fileId = Integer.parseInt(fileLoaderMatcher.group(1));
+ String prop = fileLoaderMatcher.group(2);
+ hbsTemplate = "{{#with (gtx_test_file %d)}}{{gtx_render %s}}{{/with}}".formatted(fileId, prop);
+ tagName = tag.getName();
+ break;
+ } else if (folderLoaderMatcher.matches()) {
+ int folderId = Integer.parseInt(folderLoaderMatcher.group(1));
+ String prop = folderLoaderMatcher.group(2);
+ hbsTemplate = "{{#with (gtx_test_folder %d)}}{{gtx_render %s}}{{/with}}".formatted(folderId, prop);
+ tagName = tag.getName();
+ break;
+ }
+ }
+ }
+
+ if (StringUtils.isNoneBlank(hbsTemplate, tagName)) {
+ // remove the old vtl tag
+ upd.getContentTags().remove(tagName);
+
+ // create a new hbs tag instead
+ ContentTag hbsTag = upd.getContent().addContentTag(hbsConstructId);
+ hbsTag.setName(tagName);
+ getPartType(HandlebarsPartType.class, hbsTag, "hbs").setText(hbsTemplate);
+ }
+
+ }).publish().build();
+ }
+ }
+}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/edit/FileEditSandboxTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/edit/FileEditSandboxTest.java
index 97d0c73096..0aa0338ba6 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/edit/FileEditSandboxTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/edit/FileEditSandboxTest.java
@@ -26,11 +26,8 @@
import java.util.concurrent.Future;
import java.util.stream.Collectors;
-import jakarta.servlet.ReadListener;
-import jakarta.servlet.ServletInputStream;
-import jakarta.servlet.http.HttpServletRequestWrapper;
-
import org.glassfish.jersey.media.multipart.MultiPart;
+import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
@@ -55,15 +52,21 @@
import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
import com.gentics.contentnode.tests.utils.ContentNodeTestUtils;
import com.gentics.contentnode.testutils.DBTestContext;
+import com.gentics.contentnode.testutils.LoaderHelperSource;
+import com.gentics.contentnode.testutils.TestHelpersHandlebarsService;
import com.gentics.lib.i18n.CNI18nString;
+import jakarta.servlet.ReadListener;
+import jakarta.servlet.ServletInputStream;
+import jakarta.servlet.http.HttpServletRequestWrapper;
+
/**
* Test case for testing editing of files
*
* @author johannes2
*/
-public class FileEditSandboxTest {
+public class FileEditSandboxTest extends AbstractEditSandboxTest {
@Rule
public DBTestContext testContext = new DBTestContext();
@@ -83,6 +86,11 @@ public class FileEditSandboxTest {
*/
public final static int FOLDER_ID = 7;
+ @BeforeClass
+ public static void setupOnce() {
+ TestHelpersHandlebarsService.addHelper(LoaderHelperSource.class);
+ }
+
/**
* Test editing meta data of a file
*
@@ -239,6 +247,8 @@ public void testCopyFileWithNewFilename() throws Exception {
*/
@Test
public void testDirtPageByFilename() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -265,6 +275,8 @@ public void testDirtPageByFilename() throws Exception {
*/
@Test
public void testDirtPageByDescription() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -295,6 +307,8 @@ public void testDirtPageByDescription() throws Exception {
*/
@Test
public void testDirtPageByFolder() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -327,6 +341,8 @@ public void testDirtPageByFolder() throws Exception {
*/
@Test
public void testDirtPageByFiletype() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -359,6 +375,8 @@ public void testDirtPageByFiletype() throws Exception {
*/
@Test
public void testDirtPageBySize() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/edit/FolderEditSandboxTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/edit/FolderEditSandboxTest.java
index 0fb59cd7a8..ccc784ee08 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/edit/FolderEditSandboxTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/edit/FolderEditSandboxTest.java
@@ -15,6 +15,8 @@
import java.util.Collections;
import java.util.List;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@@ -40,13 +42,19 @@
import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.PublishTarget;
import com.gentics.contentnode.testutils.DBTestContext;
+import com.gentics.contentnode.testutils.LoaderHelperSource;
+import com.gentics.contentnode.testutils.TestHelpersHandlebarsService;
/**
* Testcase for editing folders
* TODO: migrate all tests to use the REST API (if possible)
* @author norbert
*/
-public class FolderEditSandboxTest {
+public class FolderEditSandboxTest extends AbstractEditSandboxTest {
+ @BeforeClass
+ public static void setupOnce() {
+ TestHelpersHandlebarsService.addHelper(LoaderHelperSource.class);
+ }
@Rule
public DBTestContext testContext = new DBTestContext();
@@ -398,6 +406,8 @@ public void testUpdateFolderObjectProperty() throws Exception {
*/
@Test
public void testDirtPageByName() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -425,6 +435,8 @@ public void testDirtPageByName() throws Exception {
*/
@Test
public void testDirtPageByDescription() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -453,6 +465,8 @@ public void testDirtPageByDescription() throws Exception {
*/
@Test
public void testDirtPageByPubDir() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -481,6 +495,8 @@ public void testDirtPageByPubDir() throws Exception {
*/
@Test
public void testDirtPageByObjectProperty() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -509,7 +525,10 @@ public void testDirtPageByObjectProperty() throws Exception {
* @throws Exception
*/
@Test
+ @Ignore("Fails because the necessary dependency is not written for handlebars. See SUP-20138")
public void testDirtPageByNewObjectProperty() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/edit/ImageFileEditSandboxTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/edit/ImageFileEditSandboxTest.java
index 5b855dec34..86871eecc4 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/edit/ImageFileEditSandboxTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/edit/ImageFileEditSandboxTest.java
@@ -10,6 +10,7 @@
import java.io.InputStream;
import java.sql.ResultSet;
+import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
@@ -21,6 +22,8 @@
import com.gentics.contentnode.object.Page;
import com.gentics.contentnode.publish.PublishQueue;
import com.gentics.contentnode.testutils.DBTestContext;
+import com.gentics.contentnode.testutils.LoaderHelperSource;
+import com.gentics.contentnode.testutils.TestHelpersHandlebarsService;
import com.gentics.testutils.GenericTestUtils;
/**
@@ -29,7 +32,11 @@
* @author johannes2
*
*/
-public class ImageFileEditSandboxTest {
+public class ImageFileEditSandboxTest extends AbstractEditSandboxTest {
+ @BeforeClass
+ public static void setupOnce() {
+ TestHelpersHandlebarsService.addHelper(LoaderHelperSource.class);
+ }
@Rule
public DBTestContext testContext = new DBTestContext(false);
@@ -296,6 +303,8 @@ private ImageFile createAndSaveImage(String fileName) throws Exception {
*/
@Test
public void testDirtPageByBinaryupdate() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -337,6 +346,8 @@ public void testDirtPageByBinaryupdate() throws Exception {
*/
@Test
public void testDirtPageByDpiX() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -369,6 +380,8 @@ public void testDirtPageByDpiX() throws Exception {
*/
@Test
public void testDirtPageByDpiY() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -401,6 +414,8 @@ public void testDirtPageByDpiY() throws Exception {
*/
@Test
public void testDirtPageByHeight() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -431,6 +446,8 @@ public void testDirtPageByHeight() throws Exception {
*/
@Test
public void testDirtPageByWidth() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
@@ -462,6 +479,8 @@ public void testDirtPageByWidth() throws Exception {
*/
@Test
public void testDirtPageByBinaryupdate2() throws Exception {
+ migrateVtlPagesToHbsPages();
+
// republish everything to build dependencies
testContext.publish(true);
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/migration/TagTypeMigrationTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/migration/TagTypeMigrationTest.java
index a3ba758267..9420383d13 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/migration/TagTypeMigrationTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/migration/TagTypeMigrationTest.java
@@ -46,7 +46,7 @@
import com.gentics.contentnode.object.TemplateTag;
import com.gentics.contentnode.object.Value;
import com.gentics.contentnode.object.parttype.LongHTMLPartType;
-import com.gentics.contentnode.object.parttype.VelocityPartType;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
import com.gentics.contentnode.rest.model.Reference;
import com.gentics.contentnode.rest.model.migration.MigrationPartMapping;
import com.gentics.contentnode.rest.model.migration.MigrationPostProcessor;
@@ -843,8 +843,8 @@ public void testMigrationOfNonEditableParts() throws Exception {
Node node = ContentNodeTestDataUtils.createNode("Migration Node", "mignode", "/", null, false, false);
// create source and target constructs
- int sourceConstructId = createVelocityConstruct(node, "migrationsource", "source template $cms.parts.text");
- int targetConstructId = createVelocityConstruct(node, "migrationtarget", "target template $cms.parts.text");
+ int sourceConstructId = createHandlebarsConstruct(node, "migrationsource", "source template {{gtx_render cms.tag.parts.text}}");
+ int targetConstructId = createHandlebarsConstruct(node, "migrationtarget", "target template {{gtx_render cms.tag.parts.text}}");
Construct sourceConstruct = t.getObject(Construct.class, sourceConstructId);
Construct targetConstruct = t.getObject(Construct.class, targetConstructId);
@@ -890,8 +890,8 @@ public void testMigrationOfNonEditableParts() throws Exception {
// migrate source part "template" to target part "template"
partMapping = new MigrationPartMapping();
- partMapping.setFromPartId(ObjectTransformer.getInt(getPartByKeyname(sourceConstruct, "template").getId(), 0));
- partMapping.setToPartId(ObjectTransformer.getInt(getPartByKeyname(targetConstruct, "template").getId(), 0));
+ partMapping.setFromPartId(ObjectTransformer.getInt(getPartByKeyname(sourceConstruct, "hbs").getId(), 0));
+ partMapping.setToPartId(ObjectTransformer.getInt(getPartByKeyname(targetConstruct, "hbs").getId(), 0));
partMappings.add(partMapping);
// Create list of objects to apply mappings to
@@ -926,14 +926,14 @@ public void testMigrationOfNonEditableParts() throws Exception {
sourceConstruct = t.getObject(Construct.class, sourceConstruct.getId());
targetConstruct = t.getObject(Construct.class, targetConstruct.getId());
for (Part part : sourceConstruct.getParts()) {
- if ("template".equals(part.getKeyname())) {
- assertEquals("Check part template on source construct after migration", "source template $cms.parts.text", part.getDefaultValue()
+ if ("hbs".equals(part.getKeyname())) {
+ assertEquals("Check part template on source construct after migration", "source template {{gtx_render cms.tag.parts.text}}", part.getDefaultValue()
.getValueText());
}
}
for (Part part : targetConstruct.getParts()) {
- if ("template".equals(part.getKeyname())) {
- assertEquals("Check part template on target construct after migration", "target template $cms.parts.text", part.getDefaultValue()
+ if ("hbs".equals(part.getKeyname())) {
+ assertEquals("Check part template on target construct after migration", "target template {{gtx_render cms.tag.parts.text}}", part.getDefaultValue()
.getValueText());
}
}
@@ -949,8 +949,8 @@ public void testTemplateWithPostProcessor() throws Exception {
Node node = ContentNodeTestDataUtils.createNode("Migration Node", "mignode", "/", null, false, false);
// create source and target constructs
- Integer sourceConstructId = createVelocityConstruct(node, "migrationsource", "source template $cms.parts.text");
- Integer targetConstructId = createVelocityConstruct(node, "migrationtarget", "target template $cms.parts.text");
+ Integer sourceConstructId = createHandlebarsConstruct(node, "migrationsource", "source template {{gtx_render cms.tag.parts.text}}");
+ Integer targetConstructId = createHandlebarsConstruct(node, "migrationtarget", "target template {{gtx_render cms.tag.parts.text}}");
Construct sourceConstruct = t.getObject(Construct.class, sourceConstructId);
Construct targetConstruct = t.getObject(Construct.class, targetConstructId);
@@ -987,8 +987,8 @@ public void testTemplateWithPostProcessor() throws Exception {
// migrate source part "template" to target part "template"
partMapping = new MigrationPartMapping();
- partMapping.setFromPartId(ObjectTransformer.getInt(getPartByKeyname(sourceConstruct, "template").getId(), 0));
- partMapping.setToPartId(ObjectTransformer.getInt(getPartByKeyname(targetConstruct, "template").getId(), 0));
+ partMapping.setFromPartId(ObjectTransformer.getInt(getPartByKeyname(sourceConstruct, "hbs").getId(), 0));
+ partMapping.setToPartId(ObjectTransformer.getInt(getPartByKeyname(targetConstruct, "hbs").getId(), 0));
partMappings.add(partMapping);
// Create list of objects to apply mappings to
@@ -1058,8 +1058,8 @@ private void runMigrationByTemplate(boolean handlePagesByTemplate, boolean handl
Node migrationNode2 = ContentNodeTestDataUtils.createNode("migration2", "Migration Node 2", PublishTarget.NONE);
// create source and target constructs
- Integer sourceConstructId = createVelocityConstruct(migrationNode1, "migrationsource", "source template $cms.parts.text");
- Integer targetConstructId = createVelocityConstruct(migrationNode1, "migrationtarget", "target template $cms.parts.text");
+ Integer sourceConstructId = createHandlebarsConstruct(migrationNode1, "migrationsource", "source template {{gtx_render cms.tag.parts.text}}");
+ Integer targetConstructId = createHandlebarsConstruct(migrationNode1, "migrationtarget", "target template {{gtx_render cms.tag.parts.text}}");
Construct sourceConstruct = t.getObject(Construct.class, sourceConstructId);
Construct targetConstruct = t.getObject(Construct.class, targetConstructId);
@@ -1101,8 +1101,8 @@ private void runMigrationByTemplate(boolean handlePagesByTemplate, boolean handl
// migrate source part "template" to target part "template"
partMapping = new MigrationPartMapping();
- partMapping.setFromPartId(getPartByKeyname(sourceConstruct, "template").getId());
- partMapping.setToPartId(getPartByKeyname(targetConstruct, "template").getId());
+ partMapping.setFromPartId(getPartByKeyname(sourceConstruct, "hbs").getId());
+ partMapping.setToPartId(getPartByKeyname(targetConstruct, "hbs").getId());
partMappings.add(partMapping);
// Create list of objects to apply mappings to
@@ -1200,7 +1200,7 @@ private Part getPartByKeyname(Construct construct, String partKeyname) throws No
}
/**
- * Create a velocity construct
+ * Create a handlebars construct
*
* @param node
* node to which the construct shall be assigned
@@ -1211,7 +1211,7 @@ private Part getPartByKeyname(Construct construct, String partKeyname) throws No
* @return id of the construct
* @throws NodeException
*/
- private int createVelocityConstruct(Node node, String keyword, String template) throws NodeException {
+ private int createHandlebarsConstruct(Node node, String keyword, String template) throws NodeException {
Transaction t = TransactionManager.getCurrentTransaction();
Construct construct = t.createObject(Construct.class);
@@ -1220,13 +1220,15 @@ private int createVelocityConstruct(Node node, String keyword, String template)
construct.setName(keyword, 1);
construct.getNodes().add(node);
- // create velocity part
+ // create handlebars part
Part part = t.createObject(Part.class);
part.setEditable(0);
part.setHidden(false);
- part.setKeyname("vtl");
- part.setName("vtl", 1);
- part.setPartTypeId(getPartTypeId(VelocityPartType.class));
+ part.setKeyname("hbs");
+ part.setName("hbs", 1);
+ part.setPartTypeId(getPartTypeId(HandlebarsPartType.class));
+ part.setDefaultValue(t.createObject(Value.class));
+ part.getDefaultValue().setValueText(template);
construct.getParts().add(part);
// create editable part
@@ -1239,17 +1241,6 @@ private int createVelocityConstruct(Node node, String keyword, String template)
part.setDefaultValue(t.createObject(Value.class));
construct.getParts().add(part);
- // create template part
- part = t.createObject(Part.class);
- part.setEditable(0);
- part.setHidden(true);
- part.setKeyname("template");
- part.setName("template", 1);
- part.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- part.setDefaultValue(t.createObject(Value.class));
- part.getDefaultValue().setValueText(template);
- construct.getParts().add(part);
-
construct.save();
t.commit(false);
return ObjectTransformer.getInt(construct.getId(), 0);
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/overview/OverviewSettingsRenderTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/overview/OverviewSettingsRenderTest.java
index f9fd65094a..b3970c2cb9 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/overview/OverviewSettingsRenderTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/overview/OverviewSettingsRenderTest.java
@@ -3,15 +3,14 @@
import static com.gentics.contentnode.factory.Trx.execute;
import static com.gentics.contentnode.factory.Trx.operate;
import static com.gentics.contentnode.factory.Trx.supply;
-import static com.gentics.contentnode.tests.assertj.GCNAssertions.assertThat;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.TEMPLATE_PARTNAME;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.create;
+import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createConstruct;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createNode;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createPage;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createVelocityConstruct;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartType;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartTypeId;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.update;
+import static org.assertj.core.api.Assertions.assertThat;
import org.junit.BeforeClass;
import org.junit.ClassRule;
@@ -30,8 +29,8 @@
import com.gentics.contentnode.object.Part;
import com.gentics.contentnode.object.Template;
import com.gentics.contentnode.object.TemplateTag;
-import com.gentics.contentnode.object.parttype.LongHTMLPartType;
import com.gentics.contentnode.object.parttype.OverviewPartType;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
import com.gentics.contentnode.render.RenderType;
import com.gentics.contentnode.testutils.DBTestContext;
@@ -41,6 +40,8 @@
public class OverviewSettingsRenderTest {
public final static String TAG_NAME = "tag";
+ public final static String HBS_PARTNAME = "hbs";
+
@ClassRule
public static DBTestContext testContext = new DBTestContext(true);
private static Node node;
@@ -53,7 +54,7 @@ public static void setup() throws NodeException {
node = supply(() -> createNode());
- final Integer constructId = supply(() -> createVelocityConstruct(node, "vtl", "vtl"));
+ final Integer constructId = supply(() -> createConstruct(node, HandlebarsPartType.class, HBS_PARTNAME, HBS_PARTNAME));
Trx.consume(id -> {
Transaction t = TransactionManager.getCurrentTransaction();
@@ -87,8 +88,8 @@ public static void setup() throws NodeException {
}));
page = supply(() -> update(createPage(node.getFolder(), template, "Page"), upd -> {
- getPartType(LongHTMLPartType.class, upd.getTag(TAG_NAME), TEMPLATE_PARTNAME).setText(
- "listType: $cms.tag.parts.ds.listType, selectType: $cms.tag.parts.ds.selectType, orderBy: $cms.tag.parts.ds.orderBy, orderDirection: $cms.tag.parts.ds.orderDirection, maxItems: $cms.tag.parts.ds.maxItems, recursive: $cms.tag.parts.ds.recursive");
+ getPartType(HandlebarsPartType.class, upd.getTag(TAG_NAME), HBS_PARTNAME).setText(
+ "{{#with cms.tag.parts.ds}}listType: {{gtx_render listType}}, selectType: {{gtx_render selectType}}, orderBy: {{gtx_render orderBy}}, orderDirection: {{gtx_render orderDirection}}, maxItems: {{gtx_render maxItems}}, recursive: {{gtx_render recursive}}{{/with}}");
}));
}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/parttype/DatasourcePartTypeTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/parttype/DatasourcePartTypeTest.java
index 7c44fba763..66b9b60d3a 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/parttype/DatasourcePartTypeTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/parttype/DatasourcePartTypeTest.java
@@ -28,14 +28,14 @@
import com.gentics.contentnode.object.DatasourceEntry;
import com.gentics.contentnode.object.Folder;
import com.gentics.contentnode.object.Node;
+import com.gentics.contentnode.object.NodeObjectVersion;
import com.gentics.contentnode.object.ObjectTag;
import com.gentics.contentnode.object.ObjectTagDefinition;
import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.object.NodeObjectVersion;
import com.gentics.contentnode.object.Template;
import com.gentics.contentnode.object.TemplateTag;
import com.gentics.contentnode.object.parttype.DatasourcePartType;
-import com.gentics.contentnode.object.parttype.LongHTMLPartType;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
import com.gentics.contentnode.publish.PublishQueue;
import com.gentics.contentnode.render.RenderResult;
import com.gentics.contentnode.render.RenderType;
@@ -65,9 +65,14 @@ public class DatasourcePartTypeTest {
private static final String TEMPLATETAG_NAME = "datasource";
/**
- * Name of the velocity templatetag
+ * Name of the handlebars templatetag
+ */
+ private static final String HANDLEBARS_NAME = "handlebars";
+
+ /**
+ * Name of the handlebars part
*/
- private static final String VELOCITY_NAME = "velocity";
+ private static final String HANDLEBARS_PARTNAME = "hbs";
/**
* Keyword of the construct
@@ -93,9 +98,9 @@ public class DatasourcePartTypeTest {
protected static Construct datasourceConstruct;
/**
- * Velocity construct
+ * Handlebars construct
*/
- protected static Construct velocityConstruct;
+ protected static Construct handlebarsConstruct;
/**
* Object Property Definition
@@ -112,9 +117,9 @@ public static void setupOnce() throws Exception {
Transaction t = TransactionManager.getCurrentTransaction();
node = ContentNodeTestDataUtils.createNode("testnode", "Test Node", PublishTarget.NONE);
- // create a velocity construct
- int velocityConstructId = ContentNodeTestDataUtils.createVelocityConstruct(node, "Velocity", "vtl");
- velocityConstruct = t.getObject(Construct.class, velocityConstructId);
+ // create a handlebars construct
+ int handlebarsConstructId = ContentNodeTestDataUtils.createConstruct(node, HandlebarsPartType.class, HANDLEBARS_NAME, HANDLEBARS_PARTNAME);
+ handlebarsConstruct = t.getObject(Construct.class, handlebarsConstructId);
// create a datasource construct
int datasourceConstructId = ContentNodeTestDataUtils.createConstruct(node, DatasourcePartType.class, CONSTRUCT_KEYWORD, PART_KEYWORD);
@@ -144,7 +149,7 @@ public static void setupOnce() throws Exception {
template = t.createObject(Template.class);
template.setMlId(1);
template.setName("Template");
- template.setSource("");
+ template.setSource("");
template.addFolder(node.getFolder());
TemplateTag templateTag = t.createObject(TemplateTag.class);
@@ -155,11 +160,11 @@ public static void setupOnce() throws Exception {
template.getTemplateTags().put(templateTag.getName(), templateTag);
templateTag = t.createObject(TemplateTag.class);
- templateTag.setConstructId(velocityConstruct.getId());
+ templateTag.setConstructId(handlebarsConstruct.getId());
templateTag.setEnabled(true);
- templateTag.setName(VELOCITY_NAME);
+ templateTag.setName(HANDLEBARS_NAME);
templateTag.setPublic(true);
- ContentNodeTestDataUtils.getPartType(LongHTMLPartType.class, templateTag, "template").getValueObject().setValueText("$!{cms.page.tags." + TEMPLATETAG_NAME + "}");
+ ContentNodeTestDataUtils.getPartType(HandlebarsPartType.class, templateTag, HANDLEBARS_PARTNAME).getValueObject().setValueText("{{gtx_render cms.page.tags." + TEMPLATETAG_NAME + "}}");
template.getTemplateTags().put(templateTag.getName(), templateTag);
template.save();
@@ -517,8 +522,8 @@ public void testDirting() throws Exception {
Page targetPage = t.createObject(Page.class);
targetPage.setFolderId(node.getFolder().getId());
targetPage.setTemplateId(template.getId());
- ContentNodeTestDataUtils.getPartType(LongHTMLPartType.class, targetPage.getContentTag(VELOCITY_NAME), "template").getValueObject()
- .setValueText("#foreach($page in $cms.folder.pages)$page.tags." + TEMPLATETAG_NAME + "#end");
+ ContentNodeTestDataUtils.getPartType(HandlebarsPartType.class, targetPage.getContentTag(HANDLEBARS_NAME), HANDLEBARS_PARTNAME).getValueObject()
+ .setValueText("{{#each cms.folder.pages}}{{gtx_render tags." + TEMPLATETAG_NAME + "}}{{/each}}");
targetPage.save();
targetPage.publish();
t.commit(false);
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/parttype/NavigationPartTypeRenderingTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/parttype/NavigationPartTypeRenderingTest.java
deleted file mode 100644
index fc8aad49b4..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/parttype/NavigationPartTypeRenderingTest.java
+++ /dev/null
@@ -1,285 +0,0 @@
-package com.gentics.contentnode.tests.parttype;
-
-import static com.gentics.contentnode.factory.Trx.operate;
-import static com.gentics.contentnode.factory.Trx.supply;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.create;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createFile;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createFolder;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createImage;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createNode;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createObjectPropertyDefinition;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createPage;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartTypeId;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.update;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.factory.RenderTypeTrx;
-import com.gentics.contentnode.factory.Trx;
-import com.gentics.contentnode.object.Construct;
-import com.gentics.contentnode.object.File;
-import com.gentics.contentnode.object.Folder;
-import com.gentics.contentnode.object.ImageFile;
-import com.gentics.contentnode.object.Node;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.object.Part;
-import com.gentics.contentnode.object.Template;
-import com.gentics.contentnode.object.TemplateTag;
-import com.gentics.contentnode.object.Value;
-import com.gentics.contentnode.object.parttype.CheckboxPartType;
-import com.gentics.contentnode.object.parttype.LongHTMLPartType;
-import com.gentics.contentnode.object.parttype.NavigationPartType;
-import com.gentics.contentnode.object.parttype.ShortTextPartType;
-import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.PublishTarget;
-import com.gentics.contentnode.testutils.DBTestContext;
-import com.gentics.lib.util.FileUtil;
-import com.gentics.testutils.GenericTestUtils;
-
-/**
- * Tests for rendering different settings of the navigation parttype
- */
-@RunWith(value = Parameterized.class)
-public class NavigationPartTypeRenderingTest {
- @ClassRule
- public static DBTestContext testContext = new DBTestContext();
-
- private static Construct navconst;
-
- private static Node node;
-
- private static Template template;
-
- private static Page page;
-
- private static Construct checkBoxConstruct;
-
- @BeforeClass
- public static void setupOnce() throws NodeException, IOException {
- testContext.getContext().getTransaction().commit();
-
- String navTemplate = com.gentics.lib.etc.StringUtils.readStream(NavigationPartTypeRenderingTest.class.getResourceAsStream("navigation.vm"));
-
- navconst = supply(() -> {
- return create(Construct.class, navconst -> {
- navconst.setName("navconst", 1);
- navconst.setAutoEnable(true);
- navconst.setKeyword("navconst");
-
- navconst.getParts().add(create(Part.class, navpart -> {
- navpart.setPartTypeId(getPartTypeId(NavigationPartType.class));
- navpart.setKeyname("nav");
- navpart.setHidden(false);
- }, false));
- navconst.getParts().add(create(Part.class, objectsPart -> {
- objectsPart.setPartTypeId(getPartTypeId(ShortTextPartType.class));
- objectsPart.setKeyname("objects");
- objectsPart.setHidden(true);
- objectsPart.setDefaultValue(create(Value.class, v -> {
- v.setValueText("");
- }, false));
- }, false));
- navconst.getParts().add(create(Part.class, templatePart -> {
- templatePart.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- templatePart.setKeyname("template");
- templatePart.setHidden(true);
- templatePart.setDefaultValue(create(Value.class, v -> {
- v.setValueText(navTemplate);
- }, false));
- }, false));
- navconst.getParts().add(create(Part.class, sitemapPart -> {
- sitemapPart.setPartTypeId(getPartTypeId(CheckboxPartType.class));
- sitemapPart.setKeyname("sitemap");
- sitemapPart.setHidden(true);
- sitemapPart.setDefaultValue(create(Value.class, v -> {
- v.setValueText("1");
- }, false));
- }, false));
- navconst.getParts().add(create(Part.class, disableHiddenPart -> {
- disableHiddenPart.setPartTypeId(getPartTypeId(CheckboxPartType.class));
- disableHiddenPart.setKeyname("disable_hidden");
- disableHiddenPart.setHidden(true);
- disableHiddenPart.setDefaultValue(create(Value.class, v -> {
- v.setValueText("0");
- }, false));
- }, false));
- });
- });
-
- checkBoxConstruct = supply(() -> {
- return create(Construct.class, booleanConstruct -> {
- booleanConstruct.setName("check", 1);
- booleanConstruct.setAutoEnable(true);
- booleanConstruct.setKeyword("check");
-
- booleanConstruct.getParts().add(create(Part.class, checkpart -> {
- checkpart.setPartTypeId(getPartTypeId(CheckboxPartType.class));
- checkpart.setKeyname("check");
- checkpart.setHidden(false);
- checkpart.setEditable(1);
- }, false));
- });
- });
-
- operate(() -> createObjectPropertyDefinition(Folder.TYPE_FOLDER, checkBoxConstruct.getId(), "navhidden", "navhidden"));
- operate(() -> createObjectPropertyDefinition(Page.TYPE_PAGE, checkBoxConstruct.getId(), "navhidden", "navhidden"));
- operate(() -> createObjectPropertyDefinition(File.TYPE_FILE, checkBoxConstruct.getId(), "navhidden", "navhidden"));
- operate(() -> createObjectPropertyDefinition(ImageFile.TYPE_IMAGE, checkBoxConstruct.getId(), "navhidden", "navhidden"));
-
- node = supply(() -> createNode("hostname", "Node Name", PublishTarget.NONE));
- template = supply(() -> create(Template.class, template -> {
- template.setFolderId(node.getFolder().getId());
- template.setName("Template");
- template.setSource("");
-
- template.getTemplateTags().put("navigation", create(TemplateTag.class, tt -> {
- tt.setConstructId(navconst.getId());
- tt.setName("navigation");
- tt.setEnabled(true);
- tt.setPublic(false);
- }, false));
- }));
-
- // create folder structure
- Folder root = supply(() -> node.getFolder());
- Folder folder1 = supply(() -> createFolder(node.getFolder(), "Folder 1"));
- Folder folder1_1 = supply(() -> createFolder(folder1, "Folder 1.1"));
- Folder folder1_2 = supply(() -> createFolder(folder1, "Folder 1.2"));
- Folder folder2 = supply(() -> createFolder(node.getFolder(), "Folder 2"));
- Folder folder2_1 = supply(() -> createFolder(folder2, "Folder 2.1"));
- Folder folder2_2 = supply(() -> createFolder(folder2, "Folder 2.2"));
- Folder hidden = supply(() -> update(createFolder(node.getFolder(), "Hidden"), upd -> {
- upd.getObjectTag("navhidden").setEnabled(true);
- upd.getObjectTag("navhidden").getValues().getByKeyname("check").setValueText("1");
- }));
-
- // create rendered page
- page = supply(() -> update(createPage(node.getFolder(), template, "NavPage"), Page::publish));
-
- // create other objects in the folders
- for (Folder f : Arrays.asList(root, folder1, folder1_1, folder1_2, folder2, folder2_1, folder2_2, hidden)) {
- // pages
- operate(() -> update(createPage(f, template, "Page 1"), Page::publish));
- operate(() -> update(createPage(f, template, "Page 2"), Page::publish));
- operate(() -> createPage(f, template, "Offline Page"));
- operate(() -> update(createPage(f, template, "Hidden Page"), upd -> {
- upd.getObjectTag("navhidden").setEnabled(true);
- upd.getObjectTag("navhidden").getValues().getByKeyname("check").setValueText("1");
- }));
-
- // images
- ByteArrayOutputStream data = new ByteArrayOutputStream();
- FileUtil.inputStreamToOutputStream(GenericTestUtils.getPictureResource("blume.jpg"), data);
- byte[] imageBytes = data.toByteArray();
- operate(() -> createImage(f, "image1.jpg", imageBytes));
- operate(() -> createImage(f, "image2.jpg", imageBytes));
- operate(() -> update(createImage(f, "hidden_image.jpg", imageBytes), upd -> {
- upd.getObjectTag("navhidden").setEnabled(true);
- upd.getObjectTag("navhidden").getValues().getByKeyname("check").setValueText("1");
- }));
-
- // files
- operate(() -> createFile(f, "file1.txt", "File data".getBytes()));
- operate(() -> createFile(f, "file2.txt", "File data".getBytes()));
- operate(() -> update(createFile(f, "hidden_file.txt", "File data".getBytes()), upd -> {
- upd.getObjectTag("navhidden").setEnabled(true);
- upd.getObjectTag("navhidden").getValues().getByKeyname("check").setValueText("1");
- }));
- }
- }
-
- @Parameters(name = "{index}: all: {0}, folders: {1}, pages: {2}, images: {3}, files: {4}, disable_hidden: {5}")
- public static Collection data() {
- Collection data = new ArrayList<>();
- for (boolean all : Arrays.asList(true, false)) {
- for (boolean folders : Arrays.asList(true, false)) {
- for (boolean pages : Arrays.asList(true, false)) {
- for (boolean images : Arrays.asList(true, false)) {
- for (boolean files : Arrays.asList(true, false)) {
- if (all && (folders || pages || images || files)) {
- continue;
- }
- for (boolean disableHidden : Arrays.asList(true, false)) {
- data.add(new Object[] {all, folders, pages, images, files, disableHidden});
- }
- }
- }
- }
- }
- }
- return data;
- }
-
- @Parameter(0)
- public boolean all;
-
- @Parameter(1)
- public boolean folders;
-
- @Parameter(2)
- public boolean pages;
-
- @Parameter(3)
- public boolean images;
-
- @Parameter(4)
- public boolean files;
-
- @Parameter(5)
- public boolean disableHidden;
-
- private String expected;
-
- @Before
- public void setup() throws NodeException, IOException {
- List objects = new ArrayList<>();
- if (all) {
- objects.add("all");
- }
- if (folders) {
- objects.add("folders");
- }
- if (pages) {
- objects.add("pages");
- }
- if (images) {
- objects.add("images");
- }
- if (files) {
- objects.add("files");
- }
- String objectsString = objects.isEmpty() ? "none" : StringUtils.join(objects, ",");
- String filename = String.format("nav_%s%s.txt", objectsString.replaceAll(",", "_"), disableHidden ? "_disable_hidden" : "");
- expected = com.gentics.lib.etc.StringUtils
- .readStream(NavigationPartTypeRenderingTest.class.getResourceAsStream(filename));
-
- navconst = Trx.execute(c -> update(c, upd -> {
- upd.getValues().getByKeyname("objects").setValueText(objectsString);
- upd.getValues().getByKeyname("disable_hidden").setValueText(disableHidden ? "1" : "0");
- }), navconst);
- }
-
- @Test
- public void testRender() throws NodeException {
- try (Trx trx = new Trx(); RenderTypeTrx rTrx = RenderTypeTrx.publish()) {
- assertThat(page.render()).as("Rendered navigation").isEqualTo(expected);
- trx.success();
- }
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/parttype/NavigationPartTypeTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/parttype/NavigationPartTypeTest.java
deleted file mode 100644
index 423bf10117..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/parttype/NavigationPartTypeTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.gentics.contentnode.tests.parttype;
-
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.create;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createNode;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createPage;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.update;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.db.DBUtils;
-import com.gentics.contentnode.factory.Trx;
-import com.gentics.contentnode.object.Construct;
-import com.gentics.contentnode.object.Node;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.object.Part;
-import com.gentics.contentnode.object.Template;
-import com.gentics.contentnode.object.TemplateTag;
-import com.gentics.contentnode.object.Value;
-import com.gentics.contentnode.testutils.DBTestContext;
-import com.gentics.lib.db.SQLExecutor;
-
-/**
- * Tests concerning the NavigationPartType class
- */
-public class NavigationPartTypeTest {
- @ClassRule
- public static DBTestContext testContext = new DBTestContext();
-
- @BeforeClass
- public static void setupOnce() throws NodeException {
- testContext.getContext().getTransaction().commit();
- }
-
- /**
- * test whether new and offline pages are removed from the navigation
- * when listing and counting them
- * @throws Exception
- */
- @Test
- public void testOfflinePages() throws Exception {
- // Create navigation construct
- Construct nav = Trx.supply(t -> {
- t.setTimestamp(1000L);
- return create(Construct.class, navconst -> {
- navconst.setName("navconst", 1);
- navconst.setAutoEnable(true);
- navconst.setKeyword("navconst");
-
- navconst.getParts().add(create(Part.class, navpart -> {
- navpart.setPartTypeId(35); // ID of NavigationPartType
- navpart.setKeyname("nav");
- navpart.setHidden(false);
- }, false));
- navconst.getParts().add(create(Part.class, objectsPart -> {
- objectsPart.setPartTypeId(1); // Normal text
- objectsPart.setKeyname("objects");
- objectsPart.setHidden(true);
- objectsPart.setDefaultValue(create(Value.class, v -> {
- v.setValueText("pages,folders");
- }, false));
- }, false));
- navconst.getParts().add(create(Part.class, templatePart -> {
- templatePart.setPartTypeId(1);
- templatePart.setKeyname("template");
- templatePart.setHidden(true);
- templatePart.setDefaultValue(create(Value.class, v -> {
- v.setValueText("$nav.object.name#if($nav.object.isfolder)($nav.subtree)#else{$nav.relativecount}#end");
- }, false));
- }, false));
- });
- });
-
- // Create Node with root folder
- Node node = Trx.supply(() -> createNode("My Node", "test", "/", "/", false, false));
-
- // Create template with navigation tag
- Template tpl = Trx.supply(() -> create(Template.class, template -> {
- template.setName("navtemplate");
- template.setSource("");
- template.getTags().put("navtag", create(TemplateTag.class, tt -> {
- tt.setConstructId(nav.getId());
- tt.setName("navtag");
- tt.setEnabled(true);
- }, false));
- template.setFolderId(node.getFolder().getId());
- }));
-
- // Create page with navigation to look at
- Page lookatPage = Trx.supply(() -> update(createPage(node.getFolder(), tpl, "Online Page"), Page::publish));
-
- // Create page contained in the navigation and take it offline
- Page offlinePage = Trx.supply(() -> createPage(node.getFolder(), tpl, "Offline Page"));
- // publish page
- Trx.consume(p -> update(p, Page::publish), offlinePage);
- // take offline
- Trx.consume(p -> update(p, Page::takeOffline), offlinePage);
-
- // Create page contained in the navigation and don't publish it
- Page newPage = Trx.supply(() -> createPage(node.getFolder(), tpl, "Unpublished Page"));
-
- try (Trx trx = new Trx()) {
- testContext.publish(2);
- trx.success();
- }
-
- // Check page contents
- try (Trx trx = new Trx()) {
- DBUtils.executeStatement("select source from publish where page_id = ? and node_id = ? and active = 1", new SQLExecutor() {
- @Override
- public void prepareStatement(PreparedStatement stmt) throws SQLException {
- stmt.setInt(1, lookatPage.getId());
- stmt.setInt(2, node.getId());
- }
- @Override
- public void handleResultSet(ResultSet rs) throws SQLException, NodeException {
- assertTrue("Result expected", rs.next());
- assertEquals("Render result doesn't match", "My Node(Online Page{1})", rs.getString(1));
- assertFalse("Only one result expected", rs.next());
- }
- });
- trx.success();
- }
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/LargePagePublishTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/LargePagePublishTest.java
index 48fc4b3d07..6673c5cca5 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/LargePagePublishTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/LargePagePublishTest.java
@@ -17,6 +17,7 @@
import com.gentics.contentnode.db.DBUtils;
import com.gentics.contentnode.etc.Feature;
import com.gentics.contentnode.etc.NodePreferences;
+import com.gentics.contentnode.factory.RenderTypeTrx;
import com.gentics.contentnode.factory.Transaction;
import com.gentics.contentnode.factory.TransactionManager;
import com.gentics.contentnode.factory.Trx;
@@ -24,9 +25,11 @@
import com.gentics.contentnode.object.Page;
import com.gentics.contentnode.object.Template;
import com.gentics.contentnode.object.TemplateTag;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
import com.gentics.contentnode.publish.PublishInfo;
import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
import com.gentics.contentnode.testutils.DBTestContext;
+import com.gentics.contentnode.testutils.TestHelpersHandlebarsService;
/**
* Test case for publishing pages that have more the !6MB of content
@@ -62,22 +65,25 @@ public static Collection data() {
*/
@BeforeClass
public static void setupOnce() throws Exception {
+ TestHelpersHandlebarsService.addHelper(RangeHelperSource.class);
+
try (Trx trx = new Trx(null, 1)) {
DBUtils.executeUpdate("UPDATE node SET disable_publish = ?", new Object[] {1});
Transaction t = TransactionManager.getCurrentTransaction();
Node node = ContentNodeTestDataUtils.createNode();
- int vtlConstructId = ContentNodeTestDataUtils.createVelocityConstruct(node, "vtl", "vtl");
+ int hbsConstructId = ContentNodeTestDataUtils.createConstruct(node, HandlebarsPartType.class, "hbs", "hbs");
page = ContentNodeTestDataUtils.createTemplateAndPage(node.getFolder(), "Test");
Template template = t.getObject(Template.class, page.getTemplate().getId(), true);
- // add a template tag that renders more the 16M of content, so that inserting the rendered page into the publish table must fail
- TemplateTag vtlTag = ContentNodeTestDataUtils.createTemplateTag(vtlConstructId, "content", false, false);
- template.getTemplateTags().put(vtlTag.getName(), vtlTag);
- vtlTag.getValues().getByKeyname("template").setValueText("#foreach($i in [1..1700000])0123456789#end");
- template.setSource("");
+ // add a template tag that renders more than 16M of content, so that inserting the rendered page into the publish table must fail
+ TemplateTag hbsTag = ContentNodeTestDataUtils.createTemplateTag(hbsConstructId, "content", false, false);
+ template.getTemplateTags().put(hbsTag.getName(), hbsTag);
+ hbsTag.getValues().getByKeyname("hbs")
+ .setValueText("{{#each (gtx_test_range 1700000)}}0123456789{{/each}}");
+ template.setSource("");
template.save();
trx.success();
}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/RangeHelperSource.java b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/RangeHelperSource.java
new file mode 100644
index 0000000000..0716fbde0f
--- /dev/null
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/RangeHelperSource.java
@@ -0,0 +1,24 @@
+package com.gentics.contentnode.tests.publish;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import com.github.jknack.handlebars.helper.HelperFunction;
+
+/**
+ * Helper Source for the gtx_test_range
+ */
+public class RangeHelperSource {
+ /**
+ * Helper to get a list containing the integers from 0 to the given length
+ * @param length length of the integer list
+ * @return integer list
+ */
+ @HelperFunction("gtx_test_range")
+ public static Object getRange(Integer length) {
+ List list = new ArrayList<>();
+ IntStream.range(0, length).forEach(i -> list.add(i));
+ return list;
+ }
+}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/attributes/AttributeFilesystemPublishTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/attributes/AttributeFilesystemPublishTest.java
index 3cc12b2772..0e9537fddc 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/attributes/AttributeFilesystemPublishTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/attributes/AttributeFilesystemPublishTest.java
@@ -1,6 +1,7 @@
package com.gentics.contentnode.tests.publish.attributes;
import static com.gentics.contentnode.factory.Trx.supply;
+import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createConstruct;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createNode;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createTemplate;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getLanguage;
@@ -25,14 +26,16 @@
import com.gentics.contentnode.object.Page;
import com.gentics.contentnode.object.Template;
import com.gentics.contentnode.object.TemplateTag;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
import com.gentics.contentnode.rest.model.PageLanguageCode;
import com.gentics.contentnode.tests.publish.filesystem.FilesystemPublishTest;
import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.PublishTarget;
-import com.gentics.contentnode.tests.utils.CountDirective;
+import com.gentics.contentnode.tests.utils.CountHelperSource;
import com.gentics.contentnode.tests.utils.TestedType;
import com.gentics.contentnode.testutils.DBTestContext;
import com.gentics.contentnode.testutils.GCNFeature;
+import com.gentics.contentnode.testutils.TestHelpersHandlebarsService;
/**
* Test cases for publishing into the filesystem with attribute dirting (these tests only make sense for pages)
@@ -41,14 +44,13 @@
@GCNFeature(set = { Feature.MULTITHREADED_PUBLISHING, Feature.ATTRIBUTE_DIRTING })
public class AttributeFilesystemPublishTest extends FilesystemPublishTest {
/**
- * Template for the vtl construct that counts, how often it is rendered
+ * Template for the hbs construct that counts, how often it is rendered
*/
- public final static String VTL = "value of $cms.tag.name: [#gtx_test_count($cms.tag.name)]";
+ // FIXME
+ public final static String HBS = "value of {{cms.tag.name}}: [{{gtx_test_count cms.tag.name}}]";
@ClassRule
- public static DBTestContext testContext = new DBTestContext().config(prefs -> {
- prefs.set("contentnode.velocity.userdirective", CountDirective.class.getName());
- });
+ public static DBTestContext testContext = new DBTestContext();
/**
* Tagname
@@ -80,6 +82,8 @@ public static Collection data() {
@BeforeClass
public static void setupOnce() throws NodeException {
+ TestHelpersHandlebarsService.addHelper(CountHelperSource.class);
+
testContext.getContext().getTransaction().commit();
node = supply(() -> createNode("hostname", "Node name", PublishTarget.FILESYSTEM, getLanguage("de"), getLanguage("en")));
@@ -96,17 +100,18 @@ public DBTestContext getTestContext() {
@Override
public void prepareData() throws Exception {
super.prepareData();
- CountDirective.reset();
+ CountHelperSource.reset();
}
@Override
protected void preparePage(Page page) throws NodeException {
super.preparePage(page);
Transaction t = TransactionManager.getCurrentTransaction();
- Construct construct = ContentNodeTestDataUtils.createVelocityConstruct(node);
- construct.getParts().stream().filter(part -> "template".equals(part.getKeyname())).forEach(part -> {
+ int hbsConstructId = createConstruct(node, HandlebarsPartType.class, "hbs", "hbs");
+ Construct construct = t.getObject(Construct.class, hbsConstructId, true);
+ construct.getParts().stream().filter(part -> "hbs".equals(part.getKeyname())).forEach(part -> {
try {
- part.getDefaultValue().setValueText(VTL);
+ part.getDefaultValue().setValueText(HBS);
} catch (Exception e) {
e.printStackTrace();
fail("Setup of construct failed");
@@ -124,7 +129,7 @@ protected void preparePage(Page page) throws NodeException {
@Test
public void testChangeFilename() throws Exception {
// the page will be republished -> content will be rendered
- try (AutoCloseable asserter = CountDirective.asserter(TAGNAME, 1)) {
+ try (AutoCloseable asserter = CountHelperSource.asserter(TAGNAME, 1)) {
super.testChangeFilename();
}
}
@@ -133,7 +138,7 @@ public void testChangeFilename() throws Exception {
@Test
public void testChangeFolderPubdir() throws Exception {
// page will be dirted as dependency -> content not rendered
- try (AutoCloseable asserter = CountDirective.asserter(TAGNAME, 0)) {
+ try (AutoCloseable asserter = CountHelperSource.asserter(TAGNAME, 0)) {
super.testChangeFolderPubdir();
}
}
@@ -142,7 +147,7 @@ public void testChangeFolderPubdir() throws Exception {
@Test
public void testChangeHostname() throws Exception {
// page will be dirted as dependency -> content not rendered
- try (AutoCloseable asserter = CountDirective.asserter(TAGNAME, 0)) {
+ try (AutoCloseable asserter = CountHelperSource.asserter(TAGNAME, 0)) {
super.testChangeHostname();
}
}
@@ -151,7 +156,7 @@ public void testChangeHostname() throws Exception {
@Test
public void testMoveFolderToNode() throws Exception {
// page will be dirted as as a whole -> content will be rendered
- try (AutoCloseable asserter = CountDirective.asserter(TAGNAME, 1)) {
+ try (AutoCloseable asserter = CountHelperSource.asserter(TAGNAME, 1)) {
super.testMoveFolderToNode();
}
}
@@ -160,7 +165,7 @@ public void testMoveFolderToNode() throws Exception {
@Test
public void testMoveToFolder() throws Exception {
// move dirts page as a whole
- try (AutoCloseable asserter = CountDirective.asserter(TAGNAME, 1)) {
+ try (AutoCloseable asserter = CountHelperSource.asserter(TAGNAME, 1)) {
super.testMoveToFolder();
}
}
@@ -169,7 +174,7 @@ public void testMoveToFolder() throws Exception {
@Test
public void testMoveToNode() throws Exception {
// move dirts page as a whole
- try (AutoCloseable asserter = CountDirective.asserter(TAGNAME, 1)) {
+ try (AutoCloseable asserter = CountHelperSource.asserter(TAGNAME, 1)) {
super.testMoveToNode();
}
}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/cr/CrRenderTagmapTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/cr/CrRenderTagmapTest.java
index 15c08e953e..3ed70b97de 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/cr/CrRenderTagmapTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/cr/CrRenderTagmapTest.java
@@ -4,7 +4,6 @@
import static com.gentics.contentnode.factory.Trx.execute;
import static com.gentics.contentnode.factory.Trx.operate;
import static com.gentics.contentnode.factory.Trx.supply;
-import static com.gentics.contentnode.tests.assertj.GCNAssertions.assertThat;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.addTagmapEntry;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.clear;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.create;
@@ -13,10 +12,10 @@
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createNode;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createObjectTagDefinition;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createPage;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createVelocityConstruct;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartType;
import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.update;
import static com.gentics.contentnode.tests.utils.ContentNodeTestUtils.assertPublishCR;
+import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -48,7 +47,7 @@
import com.gentics.contentnode.object.Template;
import com.gentics.contentnode.object.TemplateTag;
import com.gentics.contentnode.object.parttype.LongHTMLPartType;
-import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.PublishTarget;
import com.gentics.contentnode.testutils.DBTestContext;
import com.gentics.contentnode.testutils.GCNFeature;
@@ -69,7 +68,7 @@ public class CrRenderTagmapTest {
private static Integer htmlConstructId;
- private static Integer vtlConstructId;
+ private static Integer hbsConstructId;
private static Template template;
@@ -95,7 +94,7 @@ public static void setupOnce() throws Exception {
node = supply(() -> createNode("host", "Node", PublishTarget.CONTENTREPOSITORY));
htmlConstructId = supply(() -> createConstruct(node, LongHTMLPartType.class, TAGTYPENAME, TAGTYPENAME));
- vtlConstructId = supply(() -> createVelocityConstruct(node, "vtl", "vtl"));
+ hbsConstructId = supply(() -> createConstruct(node, HandlebarsPartType.class, "hbs", "hbs"));
template = supply(() -> create(Template.class, tmpl -> {
tmpl.setName("Template");
@@ -171,13 +170,13 @@ public static Collection data() {
return update(page, upd -> {
ContentTag cTag = create(ContentTag.class, tag -> {
- tag.setConstructId(vtlConstructId);
+ tag.setConstructId(hbsConstructId);
tag.setEnabled(true);
tag.setName("overview");
}, false);
- getPartType(LongHTMLPartType.class, cTag, ContentNodeTestDataUtils.TEMPLATE_PARTNAME).getValueObject()
+ getPartType(HandlebarsPartType.class, cTag, "hbs").getValueObject()
.setValueText(
- "#set($pages = $cms.folder.pages)##\n#set($pages = $cms.imps.sorter.sort($pages, \"page.name\"))##\n#foreach($page in $pages)##\n$page.name ($page.online)\n#end##");
+ "{{#each (gtx_sort cms.folder.pages \"name\")}}{{name}} ({{online}})\n{{/each}}");
upd.getContentTags().put("overview", cTag);
});
}, res -> {
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/gis/GenticsImageStorePublishTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/gis/GenticsImageStorePublishTest.java
index f18467aab6..77d4b4a3aa 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/gis/GenticsImageStorePublishTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/gis/GenticsImageStorePublishTest.java
@@ -55,8 +55,7 @@
import com.gentics.contentnode.object.TemplateTag;
import com.gentics.contentnode.object.Value;
import com.gentics.contentnode.object.parttype.ImageURLPartType;
-import com.gentics.contentnode.object.parttype.LongHTMLPartType;
-import com.gentics.contentnode.object.parttype.VelocityPartType;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
import com.gentics.contentnode.publish.mesh.MeshPublisher;
import com.gentics.contentnode.tests.category.MeshTest;
import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.PublishTarget;
@@ -156,28 +155,17 @@ public static void setupOnce() throws NodeException {
}, false));
}, false));
- // template part
- construct.getParts().add(create(Part.class, part -> {
- part.setEditable(0);
- part.setHidden(true);
- part.setKeyname("template");
- part.setName("template", 1);
- part.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- part.setDefaultValue(create(Value.class, v -> {
- v.setValueText("#gtx_gis($cms.tag.parts.image.target, {\"width\": 50, \"mode\": \"smart\"})"
- + " #gtx_gis($cms.tag.parts.image.target, {\"height\": 100, \"mode\": \"prop\"})"
- + " $cms.tag.parts.image");
- }, false));
- }, false));
-
- // vtl part
+ // hbs part
construct.getParts().add(create(Part.class, part -> {
part.setEditable(0);
part.setHidden(false);
- part.setKeyname("vtl");
- part.setName("vtl", 1);
- part.setPartTypeId(getPartTypeId(VelocityPartType.class));
+ part.setKeyname("hbs");
+ part.setName("hbs", 1);
+ part.setPartTypeId(getPartTypeId(HandlebarsPartType.class));
part.setDefaultValue(create(Value.class, v -> {
+ v.setValueText("{{gtx_gis cms.tag.parts.image.target width=50 mode=\"smart\"}}"
+ + " {{gtx_gis cms.tag.parts.image.target height=100 mode=\"prop\"}}"
+ + " {{gtx_render cms.tag.parts.image}}");
}, false));
}, false));
}));
@@ -284,7 +272,7 @@ public void testPublishGISFile() throws Exception {
String gisUrl2 = getExpectedUrl(gisFile2);
String imageUrl = getExpectedUrl(imageFile);
- assertThat(gisUrl1 + " " + gisUrl2 + " " + imageUrl).as("URLs").isEqualTo(source);
+ assertThat(source).as("URLs").isEqualTo(gisUrl1 + " " + gisUrl2 + " " + imageUrl);
if (mesh && publishImageVariants) {
List params = new ArrayList<>(2);
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/gis/GenticsImageStorePublishingSandboxTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/gis/GenticsImageStorePublishingSandboxTest.java
deleted file mode 100644
index 7a517e6bdc..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/gis/GenticsImageStorePublishingSandboxTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-package com.gentics.contentnode.tests.publish.gis;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.commons.io.FileUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.db.DBUtils;
-import com.gentics.contentnode.factory.object.FolderFactory;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.publish.PublishInfo;
-import com.gentics.contentnode.tests.rendering.ContentNodeTestContext;
-import com.gentics.contentnode.testutils.DBTestContext;
-import com.gentics.contentnode.testutils.TestAppender;
-import com.gentics.lib.log.NodeLogger;
-
-public class GenticsImageStorePublishingSandboxTest {
-
- @Rule
- public DBTestContext testContext = new DBTestContext(false);
-
- private static final String HOST_A = "www.hosta.tdl";
- private static final int PAGE_ID_IN_NODE_A = 65;
-
- private static final String HOST_B = "www.hostb.tdl";
- private static final int PAGE_ID_IN_NODE_B = 64;
-
- private static final String HOST_C = "www.hostc.tdl";
- private static final int PAGE_ID_IN_NODE_C = 63;
-
- private static final String HOST_D = "www.hostd.tdl";
- private static final int PAGE_ID_IN_NODE_D = 66;
-
- private static final String PUBDIR_NAME = "/Content.Node/";
- private static final String IMAGESTORE_PATH_WITHIN_NODE = "/GenticsImageStore/300/auto/prop/Content.Node/";
-
- private static final TestAppender testAppender = new TestAppender();
-
- private PublishInfo invokePublish() throws Exception {
- ContentNodeTestContext context = testContext.getContext();
- PublishInfo info = context.publish(false);
- return info;
- }
-
- /**
- * Publishes the given page and clears the publish table before doing so
- *
- * @param pageId
- * @throws Exception
- */
- private void publishPage(int pageId) throws Exception {
- DBUtils.executeUpdate("DELETE FROM imagestoreimage", null);
- DBUtils.executeUpdate("DELETE FROM publish", null);
- DBUtils.executeUpdate("DELETE FROM publishqueue", null);
-
- testContext.markAllPagesAsPublished();
- Page page = testContext.getContext().getTransaction().getObject(Page.class, pageId, true);
- page.setDescription("lulu");
- page.save(true);
- page.publish();
- testContext.getContext().getTransaction().commit();
- PublishInfo info = invokePublish();
-
- // Publish should be successful
- assertEquals("The publish run should terminate with a success code. Messages: " + info.getMessages(), PublishInfo.RETURN_CODE_SUCCESS,
- info.getReturnCode());
- }
-
- /**
- * This method contains some asserts on the original files that should be published
- * @throws NodeException
- */
- public void checkNormalFilePublish() throws NodeException {
- // Check that the original files exist as expected
- File originalImageInNodeA = new File(testContext.getContext().getPubDir(), HOST_A + PUBDIR_NAME + "node_a.jpeg");
-
- assertTrue("The original image should be published. {" + originalImageInNodeA + "}", originalImageInNodeA.exists());
-
- File originalImageInNodeB = new File(testContext.getContext().getPubDir(), HOST_B + PUBDIR_NAME + "node_b.jpg");
-
- assertTrue("The original image should be published. {" + originalImageInNodeB + "}", originalImageInNodeB.exists());
-
- File originalImageInNodeC = new File(testContext.getContext().getPubDir(), HOST_C + PUBDIR_NAME + "node_c.jpg");
-
- assertTrue("The original image should be published. {" + originalImageInNodeC + "}", originalImageInNodeC.exists());
-
- File originalImageInNodeD = new File(testContext.getContext().getPubDir(), HOST_D + PUBDIR_NAME + "node_d.jpg");
-
- assertTrue("The original image {" + originalImageInNodeD + "} should not exist because node d is not publishing in the filesystem.",
- !originalImageInNodeD.exists());
-
- }
-
- @BeforeClass
- public static void setupOnce() {
- NodeLogger logger = NodeLogger.getNodeLogger(FolderFactory.class.getCanonicalName() + "$FactoryFolder");
-
- logger.removeAllAppenders();
- logger.addAppender(testAppender);
- }
-
- @Before
- public void setup() throws IOException, NodeException {
- FileUtils.deleteDirectory(testContext.getContext().getPubDir());
- testContext.getContext().getNodeConfig().getDefaultPreferences().setFeature("tag_image_resizer", true);
-
- testAppender.reset();
- }
-
- @After
- public void tearDown() throws Exception {
- FileUtils.deleteDirectory(testContext.getContext().getPubDir());
- }
-
- /**
- * This test publishes a page in node A which is a node that publishes into the filesystem. The page contains references to Node B, C, D
- *
- * @throws Exception
- */
- @Test
- public void testGISPublishNodeA() throws Exception {
- publishPage(PAGE_ID_IN_NODE_A);
- checkNormalFilePublish();
- boolean[] assertConfig = { true, true, true, false };
-
- assertResizedImages(assertConfig);
- assertThat(testAppender.getMessages())
- .as("Log messages must be empty")
- .isEmpty();
- }
-
- /**
- * This test publishes a page in node B which is a node that publishes into the filesystem
- *
- * @throws Exception
- */
- @Test
- public void testGISPublishNodeB() throws Exception {
- publishPage(PAGE_ID_IN_NODE_B);
- checkNormalFilePublish();
- boolean[] assertConfig = { true, true, true, false };
-
- assertResizedImages(assertConfig);
- assertThat(testAppender.getMessages())
- .as("Log messages must be empty")
- .isEmpty();
- }
-
- /**
- * This test publishes a page in a node that only publishes into a CR
- *
- * @throws Exception
- */
- @Test
- public void testGISPublishNodeD() throws Exception {
- publishPage(PAGE_ID_IN_NODE_D);
- checkNormalFilePublish();
- // GIS does not work for nodes that publish only in CR
- boolean[] assertConfig = { false, false, false, false };
- assertResizedImages(assertConfig);
- assertThat(testAppender.getMessages())
- .as("Log messages must be empty")
- .isEmpty();
- }
-
- /**
- * Check that the resized images exist or were omitted due to node specific settings
- *
- * @param imagesPerNode
- * @throws Exception
- */
- public void assertResizedImages(boolean[] imagesPerNode) throws Exception {
-
- File resizedImageInNodeA = new File(testContext.getContext().getPubDir(), HOST_A + IMAGESTORE_PATH_WITHIN_NODE + "node_a.jpeg");
-
- assertEquals("The resized image {" + resizedImageInNodeA + "} was not written into the FS.", imagesPerNode[0], resizedImageInNodeA.exists());
-
- File resizedImageInNodeB = new File(testContext.getContext().getPubDir(), HOST_B + IMAGESTORE_PATH_WITHIN_NODE + "node_b.jpg");
-
- assertEquals("The resized image {" + resizedImageInNodeB + "} was not written into the FS.", imagesPerNode[1], resizedImageInNodeB.exists());
-
- File resizedImageInNodeC = new File(testContext.getContext().getPubDir(), HOST_C + IMAGESTORE_PATH_WITHIN_NODE + "node_c.jpg");
-
- assertEquals("The resized image {" + resizedImageInNodeC + "} was not written into the FS.", imagesPerNode[2], resizedImageInNodeC.exists());
-
- File resizedImageInNodeD = new File(testContext.getContext().getPubDir(), HOST_D + IMAGESTORE_PATH_WITHIN_NODE + "node_d.jpg");
-
- assertEquals("The resized image {" + resizedImageInNodeD + "} was not written into the FS.", imagesPerNode[3], resizedImageInNodeD.exists());
-
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/mesh/MeshPublishRolesTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/mesh/MeshPublishRolesTest.java
index 8780cf6455..6b38e7d877 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/mesh/MeshPublishRolesTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/mesh/MeshPublishRolesTest.java
@@ -50,14 +50,12 @@
import com.gentics.contentnode.object.Folder;
import com.gentics.contentnode.object.Node;
import com.gentics.contentnode.object.NodeObject;
-import com.gentics.contentnode.object.ObjectTag;
import com.gentics.contentnode.object.ObjectTagContainer;
import com.gentics.contentnode.object.ObjectTagDefinition;
import com.gentics.contentnode.object.Page;
import com.gentics.contentnode.object.Part;
import com.gentics.contentnode.object.Template;
import com.gentics.contentnode.object.Value;
-import com.gentics.contentnode.object.parttype.LongHTMLPartType;
import com.gentics.contentnode.object.parttype.MultiSelectPartType;
import com.gentics.contentnode.publish.PublishQueue;
import com.gentics.contentnode.publish.PublishQueue.Action;
@@ -69,7 +67,6 @@
import com.gentics.contentnode.rest.util.MiscUtils;
import com.gentics.contentnode.tests.category.MeshTest;
import com.gentics.contentnode.tests.utils.ContentNodeRESTUtils;
-import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.PublishTarget;
import com.gentics.contentnode.tests.utils.ExceptionChecker;
import com.gentics.contentnode.tests.utils.Expected;
@@ -107,10 +104,6 @@ public class MeshPublishRolesTest {
*/
public final static List ROLES = Arrays.asList("role_a", "role_b", "role_c");
- private final static String VTL_OBJECT_TAG_KEYWORD = "vtlroles";
- private final static String VTL_PART_KEYWORD = "vtl";
- private final static String VTL_ROLES_FIELD = "roles";
-
@ClassRule
public static DBTestContext context = new DBTestContext();
@@ -172,10 +165,7 @@ public static void setupOnce() throws Exception {
}, false));
}));
- int velocityRolesConstructId = Trx.supply(t -> ContentNodeTestDataUtils.createVelocityConstruct(node, "roleConstruct", VTL_PART_KEYWORD));
-
rolesProperty = createObjectPropertyDefinition(Folder.TYPE_FOLDER, rolesConstruct.getId(), "Roles", "roles");
- velocityRolesProperty = createObjectPropertyDefinition(Folder.TYPE_FOLDER, velocityRolesConstructId, "VTLRoles", VTL_OBJECT_TAG_KEYWORD);
}
@Before
@@ -712,133 +702,6 @@ public void testDefaultFilePermissions() throws Exception {
assertNodePermission(MESH_PROJECT_NAME, file, Permission.READ_PUBLISHED, "role_b");
}
- /**
- * Test the permissions on a folder when using values from a Velocity context.
- * @throws Exception
- */
- @Test
- public void testFolderPermissionsWithoutDs() throws Exception {
- Folder folder = Trx.supply(() -> createFolder(node.getFolder(), "Folder"));
-
- setVelocityPermissionProperty();
-
- try (Trx trx = new Trx()) {
- context.publish(false);
- trx.success();
- }
-
- // Assert that the page has the default permission set.
- assertNodePermission(MESH_PROJECT_NAME, folder, Permission.READ_PUBLISHED, "role_b");
-
- Trx.operate(() -> update(folder, f -> setVelocityRoles(f, "role_a", "role_c")));
-
- try (Trx trx = new Trx()) {
- context.publish(false);
- trx.success();
- }
-
- assertNodePermission(MESH_PROJECT_NAME, folder, Permission.READ_PUBLISHED, "role_a", "role_c");
- }
-
- /**
- * Test the permissions on a page when using values from a Velocity context.
- * @throws Exception
- */
- @Test
- public void testPagePermissionsWithoutDs() throws Exception {
- Folder folder = Trx.supply(() -> createFolder(node.getFolder(), "Folder"));
- Page page = Trx.supply(() -> update(createPage(folder, template, "testpage"), Page::publish));
-
- setVelocityPermissionProperty();
-
- try (Trx trx = new Trx()) {
- context.publish(false);
- trx.success();
- }
-
- // Assert that the page has the default permission set.
- assertNodePermission(MESH_PROJECT_NAME, page, Permission.READ_PUBLISHED, "role_b");
-
- update(folder, f -> setVelocityRoles(f, "role_a", "role_c"));
- update(page, Page::publish);
-
- try (Trx trx = new Trx()) {
- context.publish(false);
- trx.success();
- }
-
- assertNodePermission(MESH_PROJECT_NAME, page, Permission.READ_PUBLISHED, "role_a", "role_c");
- }
-
- /**
- * Test the permissions on a file when using values from a Velocity context.
- * @throws Exception
- */
- @Test
- public void testFilePermissionsWithoutDs() throws Exception {
- Folder folder = Trx.supply(() -> createFolder(node.getFolder(), "Folder"));
- File file = Trx.supply(() -> createFile(folder, "file.txt", "File contents".getBytes()));
-
- setVelocityPermissionProperty();
-
- try (Trx trx = new Trx()) {
- context.publish(false);
- trx.success();
- }
-
- // Assert that the page has the default permission set.
- assertNodePermission(MESH_PROJECT_NAME, file, Permission.READ_PUBLISHED, "role_b");
-
- Trx.operate(() -> update(folder, f -> setVelocityRoles(f, "role_a", "role_c")));
-
- try (Trx trx = new Trx()) {
- context.publish(false);
- trx.success();
- }
-
- assertNodePermission(MESH_PROJECT_NAME, file, Permission.READ_PUBLISHED, "role_a", "role_c");
- }
-
-
- /**
- * Test that permissions on project are set
- * @throws Exception
- */
- @Test
- public void testProjectPermissionsWithoutDs() throws Exception {
- setVelocityPermissionProperty();
- setVelocityRoles(node.getFolder(), "anonymous", "role_b");
-
- try (Trx trx = new Trx()) {
- context.publish(false);
- trx.success();
- }
-
- assertProjectPermission(MESH_PROJECT_NAME, Permission.READ, "anonymous", "role_b");
- List branches = mesh.client().findBranches(MESH_PROJECT_NAME).blockingGet().getData();
- Optional optionalDefaultBranch = branches.stream().filter(isDefaultBranch()).findFirst();
- assertThat(optionalDefaultBranch).isPresent();
- assertBranchPermission(MESH_PROJECT_NAME, optionalDefaultBranch.get().getUuid(), Permission.READ, "anonymous", "role_b");
- }
-
- /**
- * Test permissions on root node
- * @throws Exception
- */
- @Test
- public void testProjectRootNodePermissionsWithoutDs() throws Exception {
- setVelocityPermissionProperty();
- setVelocityRoles(node.getFolder(), "anonymous", "role_b");
-
- try (Trx trx = new Trx()) {
- context.publish(false);
- trx.success();
- }
-
- String rootNodeUuid = mesh.client().findProjectByName(MESH_PROJECT_NAME).blockingGet().getRootNode().getUuid();
- assertRoles(param -> mesh.client().findNodeByUuid(MESH_PROJECT_NAME, rootNodeUuid, param), Permission.READ_PUBLISHED, "anonymous", "role_b");
- }
-
/**
* Get the expected datasource entries for the roles datasource (only keys and values filled)
* @return list of expected datasource entries
@@ -881,42 +744,6 @@ protected List getExpectedEntries(String...roles) throws NodeEx
return entries;
}
- /**
- * The the {@link ContentRepository#setPermissionProperty(String) permission property} of the Mesh Contentrepository
- * to the {@code roles} field in the Velocity context of the object tag.
- */
- protected void setVelocityPermissionProperty() throws NodeException {
- Trx.operate(t -> {
- ContentRepository cr = t.getObject(ContentRepository.class, crId, true);
-
- cr.setPermissionProperty(String.format("object.%s.parts.%s.%s", VTL_OBJECT_TAG_KEYWORD, VTL_PART_KEYWORD, VTL_ROLES_FIELD));
- cr.save();
- });
- }
-
- /**
- * Set the given roles via the velocity object tag.
- *
- * @param container The container to set the roles for.
- * @param roles The roles to set.
- */
- protected void setVelocityRoles(ObjectTagContainer container, String... roles) throws NodeException {
- ObjectTag objTag = container.getObjectTag(VTL_OBJECT_TAG_KEYWORD);
- StringBuilder valueText = new StringBuilder(String.format("#set($%s = [])\n", VTL_ROLES_FIELD));
-
- for (String role : roles) {
- valueText.append(String.format("$%s.add(\"%s\")\n", VTL_ROLES_FIELD, role));
- }
-
- update(objTag, tag -> {
- tag.setEnabled(true);
-
- getPartType(LongHTMLPartType.class, tag, ContentNodeTestDataUtils.TEMPLATE_PARTNAME)
- .getValueObject()
- .setValueText(valueText.toString());
- });
- }
-
/**
* Set the given roles into the roles object property of the container.
* This method expects an open transaction and that the container is editable
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/wrapper/PublishablePageRenderTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/wrapper/PublishablePageRenderTest.java
index bd0fa916b4..683eca6dd0 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/wrapper/PublishablePageRenderTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/wrapper/PublishablePageRenderTest.java
@@ -1,9 +1,12 @@
package com.gentics.contentnode.tests.publish.wrapper;
+import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createConstruct;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import java.io.InputStream;
+
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
@@ -19,6 +22,7 @@
import com.gentics.contentnode.object.Page;
import com.gentics.contentnode.object.Template;
import com.gentics.contentnode.object.TemplateTag;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
import com.gentics.contentnode.publish.wrapper.PublishablePage;
import com.gentics.contentnode.render.RenderResult;
import com.gentics.contentnode.render.RenderType;
@@ -41,7 +45,7 @@ public class PublishablePageRenderTest {
*/
private static Node node;
- private static int vtlConstructId;
+ private static int hbsConstructId;
private static Template template;
@@ -62,7 +66,7 @@ public static void setUpOnce() throws Exception {
renderType.setFrontEnd(true);
node = ContentNodeTestDataUtils.createNode("Test", "test", "/", null, false, false);
- vtlConstructId = ContentNodeTestDataUtils.createVelocityConstruct(node, "velocity", "vtl");
+ hbsConstructId = createConstruct(node, HandlebarsPartType.class, "hbs", "hbs");
de = t.createObject(ContentLanguage.class);
de.setCode("de");
@@ -84,7 +88,7 @@ public static void setUpOnce() throws Exception {
template.setSource("");
template.getFolders().add(node.getFolder());
TemplateTag templateTag = t.createObject(TemplateTag.class);
- templateTag.setConstructId(vtlConstructId);
+ templateTag.setConstructId(hbsConstructId);
templateTag.setEnabled(true);
templateTag.setName(TEMPLATE_TAG_NAME);
templateTag.setPublic(true);
@@ -100,8 +104,10 @@ public static void setUpOnce() throws Exception {
*/
@Test
public void testRenderPageProperties() throws Exception {
- String vtl = FileUtil.stream2String(getClass().getResourceAsStream("page_props.vm"), "UTF-8");
- assertRender(createVelocityPage(vtl));
+ try (InputStream in = getClass().getResourceAsStream("page_props.hbs")) {
+ String hbs = FileUtil.stream2String(in, "UTF-8");
+ assertRender(createHandlebarsPage(hbs));
+ }
}
/**
@@ -110,8 +116,10 @@ public void testRenderPageProperties() throws Exception {
*/
@Test
public void testRenderTags() throws Exception {
- String vtl = FileUtil.stream2String(getClass().getResourceAsStream("tags.vm"), "UTF-8");
- assertRender(createVelocityPage(vtl));
+ try (InputStream in = getClass().getResourceAsStream("tags.hbs")) {
+ String hbs = FileUtil.stream2String(in, "UTF-8");
+ assertRender(createHandlebarsPage(hbs));
+ }
}
/**
@@ -120,16 +128,18 @@ public void testRenderTags() throws Exception {
*/
@Test
public void testRenderLanguageVariants() throws Exception {
- String vtl = FileUtil.stream2String(getClass().getResourceAsStream("language_variants.vm"), "UTF-8");
- Page page = createVelocityPage(vtl);
- Page englishVariant = (Page)page.copy();
- englishVariant.setContentsetId(page.getContentsetId());
- englishVariant.setLanguage(en);
- englishVariant.save();
- TransactionManager.getCurrentTransaction().commit(false);
-
- assertRender(page);
- assertRender(englishVariant);
+ try (InputStream in = getClass().getResourceAsStream("language_variants.hbs")) {
+ String hbs = FileUtil.stream2String(in, "UTF-8");
+ Page page = createHandlebarsPage(hbs);
+ Page englishVariant = (Page)page.copy();
+ englishVariant.setContentsetId(page.getContentsetId());
+ englishVariant.setLanguage(en);
+ englishVariant.save();
+ TransactionManager.getCurrentTransaction().commit(false);
+
+ assertRender(page);
+ assertRender(englishVariant);
+ }
}
/**
@@ -138,8 +148,10 @@ public void testRenderLanguageVariants() throws Exception {
*/
@Test
public void testRenderPagePropertiesProxy() throws Exception {
- String vtl = FileUtil.stream2String(getClass().getResourceAsStream("page_props.vm"), "UTF-8");
- assertRenderProxy(createVelocityPage(vtl));
+ try (InputStream in = getClass().getResourceAsStream("page_props.hbs")) {
+ String hbs = FileUtil.stream2String(in, "UTF-8");
+ assertRenderProxy(createHandlebarsPage(hbs));
+ }
}
/**
@@ -148,8 +160,10 @@ public void testRenderPagePropertiesProxy() throws Exception {
*/
@Test
public void testRenderTagsProxy() throws Exception {
- String vtl = FileUtil.stream2String(getClass().getResourceAsStream("tags.vm"), "UTF-8");
- assertRenderProxy(createVelocityPage(vtl));
+ try (InputStream in = getClass().getResourceAsStream("tags.hbs")) {
+ String hbs = FileUtil.stream2String(in, "UTF-8");
+ assertRenderProxy(createHandlebarsPage(hbs));
+ }
}
/**
@@ -158,16 +172,18 @@ public void testRenderTagsProxy() throws Exception {
*/
@Test
public void testRenderLanguageVariantsProxy() throws Exception {
- String vtl = FileUtil.stream2String(getClass().getResourceAsStream("language_variants.vm"), "UTF-8");
- Page page = createVelocityPage(vtl);
- Page englishVariant = (Page)page.copy();
- englishVariant.setContentsetId(page.getContentsetId());
- englishVariant.setLanguage(en);
- englishVariant.save();
- TransactionManager.getCurrentTransaction().commit(false);
-
- assertRenderProxy(page);
- assertRenderProxy(englishVariant);
+ try (InputStream in = getClass().getResourceAsStream("language_variants.hbs")) {
+ String hbs = FileUtil.stream2String(in, "UTF-8");
+ Page page = createHandlebarsPage(hbs);
+ Page englishVariant = (Page)page.copy();
+ englishVariant.setContentsetId(page.getContentsetId());
+ englishVariant.setLanguage(en);
+ englishVariant.save();
+ TransactionManager.getCurrentTransaction().commit(false);
+
+ assertRenderProxy(page);
+ assertRenderProxy(englishVariant);
+ }
}
/**
@@ -176,8 +192,10 @@ public void testRenderLanguageVariantsProxy() throws Exception {
*/
@Test
public void testRenderPagePropertiesPublishableProxy() throws Exception {
- String vtl = FileUtil.stream2String(getClass().getResourceAsStream("page_props.vm"), "UTF-8");
- assertRenderPublishablePageProxy(createVelocityPage(vtl));
+ try (InputStream in = getClass().getResourceAsStream("page_props.hbs")) {
+ String hbs = FileUtil.stream2String(in, "UTF-8");
+ assertRenderPublishablePageProxy(createHandlebarsPage(hbs));
+ }
}
/**
@@ -186,8 +204,10 @@ public void testRenderPagePropertiesPublishableProxy() throws Exception {
*/
@Test
public void testRenderTagsPublishableProxy() throws Exception {
- String vtl = FileUtil.stream2String(getClass().getResourceAsStream("tags.vm"), "UTF-8");
- assertRenderPublishablePageProxy(createVelocityPage(vtl));
+ try (InputStream in = getClass().getResourceAsStream("tags.hbs")) {
+ String hbs = FileUtil.stream2String(in, "UTF-8");
+ assertRenderPublishablePageProxy(createHandlebarsPage(hbs));
+ }
}
/**
@@ -196,32 +216,34 @@ public void testRenderTagsPublishableProxy() throws Exception {
*/
@Test
public void testRenderLanguageVariantsPublishableProxy() throws Exception {
- String vtl = FileUtil.stream2String(getClass().getResourceAsStream("language_variants.vm"), "UTF-8");
- Page page = createVelocityPage(vtl);
- Page englishVariant = (Page)page.copy();
- englishVariant.setContentsetId(page.getContentsetId());
- englishVariant.setLanguage(en);
- englishVariant.save();
- TransactionManager.getCurrentTransaction().commit(false);
-
- assertRenderPublishablePageProxy(page);
- assertRenderPublishablePageProxy(englishVariant);
+ try (InputStream in = getClass().getResourceAsStream("language_variants.hbs")) {
+ String hbs = FileUtil.stream2String(in, "UTF-8");
+ Page page = createHandlebarsPage(hbs);
+ Page englishVariant = (Page)page.copy();
+ englishVariant.setContentsetId(page.getContentsetId());
+ englishVariant.setLanguage(en);
+ englishVariant.save();
+ TransactionManager.getCurrentTransaction().commit(false);
+
+ assertRenderPublishablePageProxy(page);
+ assertRenderPublishablePageProxy(englishVariant);
+ }
}
/**
- * Create a page rendering the given vtl code
- * @param vtl vtl code
+ * Create a page rendering the given hbs code
+ * @param hbs hbs code
* @return page instance
* @throws Exception
*/
- protected Page createVelocityPage(String vtl) throws Exception {
+ protected Page createHandlebarsPage(String hbs) throws Exception {
Transaction t = TransactionManager.getCurrentTransaction();
Page page = t.createObject(Page.class);
page.setDescription("Rendering test page");
page.setTemplateId(template.getId());
page.setFolderId(node.getFolder().getId());
page.setLanguage(de);
- page.getContentTag(TEMPLATE_TAG_NAME).getValues().getByKeyname("template").setValueText(vtl);
+ page.getContentTag(TEMPLATE_TAG_NAME).getValues().getByKeyname("hbs").setValueText(hbs);
page.save();
page.publish();
t.commit(false);
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/wrapper/PublishablePageTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/wrapper/PublishablePageTest.java
index d2b6cd932f..9b218c284b 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/publish/wrapper/PublishablePageTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/publish/wrapper/PublishablePageTest.java
@@ -33,7 +33,6 @@
import com.gentics.contentnode.object.Template;
import com.gentics.contentnode.object.TemplateTag;
import com.gentics.contentnode.object.Value;
-import com.gentics.contentnode.object.parttype.BreadcrumbPartType;
import com.gentics.contentnode.object.parttype.ChangeableListPartType;
import com.gentics.contentnode.object.parttype.CheckboxPartType;
import com.gentics.contentnode.object.parttype.DHTMLPartType;
@@ -51,7 +50,6 @@
import com.gentics.contentnode.object.parttype.LongHTMLPartType;
import com.gentics.contentnode.object.parttype.LongHTMLTextPartType;
import com.gentics.contentnode.object.parttype.MultiSelectPartType;
-import com.gentics.contentnode.object.parttype.NavigationPartType;
import com.gentics.contentnode.object.parttype.NodePartType;
import com.gentics.contentnode.object.parttype.NormalTextPartType;
import com.gentics.contentnode.object.parttype.OrderedListPartType;
@@ -66,7 +64,6 @@
import com.gentics.contentnode.object.parttype.TablePartType;
import com.gentics.contentnode.object.parttype.TemplateTagPartType;
import com.gentics.contentnode.object.parttype.UnorderedListPartType;
-import com.gentics.contentnode.object.parttype.VelocityPartType;
import com.gentics.contentnode.publish.wrapper.PublishablePage;
import com.gentics.contentnode.render.RenderResult;
import com.gentics.contentnode.render.RenderType;
@@ -341,19 +338,6 @@ protected void fillContentTag(Page page, ContentTag tag) throws Exception {
protected void fillContentTag(Page page, ContentTag tag) throws Exception {
tag.getValues().iterator().next().setValueText(TEST_CONTENT);
}
- }, new PartTypeTest(ExtensiblePartTypeWrapper.class, VelocityPartType.class, null) {
- @Override
- protected void fillContentTag(Page page, ContentTag tag) throws Exception {
- tag.getValues().getByKeyname("template").setValueText("$page.name");
- }
- }, new PartTypeTest(ExtensiblePartTypeWrapper.class, BreadcrumbPartType.class, null) {
- @Override
- protected void fillContentTag(Page page, ContentTag tag) throws Exception {
- }
- }, new PartTypeTest(ExtensiblePartTypeWrapper.class, NavigationPartType.class, null) {
- @Override
- protected void fillContentTag(Page page, ContentTag tag) throws Exception {
- }
}, new PartTypeTest(OverviewPartType.class, "single page") {
@Override
protected void fillContentTag(Page page, ContentTag tag) throws Exception {
@@ -484,11 +468,7 @@ public PublishablePageTest(PartTypeTest test) {
@Before
public void setUp() throws Exception {
Transaction t = TransactionManager.getCurrentTransaction();
- if (test.wrappedClazz != null) {
- constructId = ContentNodeTestDataUtils.createExtensibleConstruct(node, test.wrappedClazz, CONSTRUCT_KEYWORD, PART_KEYWORD);
- } else {
- constructId = ContentNodeTestDataUtils.createConstruct(node, test.clazz, CONSTRUCT_KEYWORD, PART_KEYWORD);
- }
+ constructId = ContentNodeTestDataUtils.createConstruct(node, test.clazz, CONSTRUCT_KEYWORD, PART_KEYWORD);
// for selectparttypes, set the datasource id
if (SelectPartType.class.isAssignableFrom(test.clazz)) {
@@ -544,11 +524,6 @@ protected static abstract class PartTypeTest {
*/
protected Class extends PartType> clazz;
- /**
- * Wrapped Parttype class, if {@link #clazz} is {@link ExtensiblePartTypeWrapper}
- */
- protected Class extends ExtensiblePartType> wrappedClazz;
-
/**
* Description to be shown in the test overview
*/
@@ -560,18 +535,7 @@ protected static abstract class PartTypeTest {
* @param description description
*/
protected PartTypeTest(Class extends PartType> clazz, String description) {
- this(clazz, null, description);
- }
-
- /**
- * Create an instance for testing the clazz with a description
- * @param clazz tested class
- * @param wrappedClazz wrapped class
- * @param description description
- */
- protected PartTypeTest(Class extends PartType> clazz, Class extends ExtensiblePartType> wrappedClazz, String description) {
this.clazz = clazz;
- this.wrappedClazz = wrappedClazz;
this.description = description;
}
@@ -586,11 +550,7 @@ protected PartTypeTest(Class extends PartType> clazz, Class extends Extensib
@Override
public String toString() {
StringBuilder str = new StringBuilder();
- if (wrappedClazz != null) {
- str.append(wrappedClazz.getSimpleName());
- } else {
- str.append(clazz.getSimpleName());
- }
+ str.append(clazz.getSimpleName());
if (!ObjectTransformer.isEmpty(description)) {
str.append(" - ").append(description);
}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/AbstractVelocityRenderingTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/AbstractVelocityRenderingTest.java
deleted file mode 100644
index 229ea9d1d7..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/AbstractVelocityRenderingTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package com.gentics.contentnode.tests.rendering;
-
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.object.Construct;
-import com.gentics.contentnode.object.ContentTag;
-import com.gentics.contentnode.object.Folder;
-import com.gentics.contentnode.object.Node;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.object.Part;
-import com.gentics.contentnode.object.Template;
-import com.gentics.contentnode.object.TemplateTag;
-import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
-import com.gentics.contentnode.testutils.DBTestContext;
-
-public class AbstractVelocityRenderingTest {
-
- @ClassRule
- public static DBTestContext testContext = new DBTestContext();
-
- /**
- * Node
- */
- protected static Node node;
-
- /**
- * Template
- */
- protected static Template template;
-
- /**
- * Construct
- */
- protected static Construct construct;
-
- /**
- * Page
- */
- protected static Page page;
- /**
- * Name of the editable tag
- */
- public final static String VTL_TAGNAME = "vtltag";
-
- @BeforeClass
- public static void setupOnce() throws Exception {
- String sessionToken = testContext.getContext().login("node", "node");
- TransactionManager.getCurrentTransaction().commit();
-
- testContext.getContext().getContentNodeFactory()
- .startTransaction(sessionToken, true);
-
- // Create node
- node = ContentNodeTestDataUtils.createNode();
- //
- // Create velocity construct that renders the given template
- construct = ContentNodeTestDataUtils.createVelocityConstruct(node);
- //
- // // Create template using the construct
- template = createTemplate(node.getFolder(), construct);
- //
- // // Create a page
- page = createPage(node.getFolder(), template);
-
- }
-
- /**
- * Update the construct by setting the velocity template
- *
- * @param vtl
- * template
- * @throws Exception
- */
- protected static void updateConstruct(String vtl) throws Exception {
- Transaction t = TransactionManager.getCurrentTransaction();
-
- for (Part part : construct.getParts()) {
- if ("template".equals(part.getKeyname())) {
- part.getDefaultValue().setValueText(vtl);
- }
- }
-
- construct.save();
- t.commit(false);
- }
-
- /**
- * Create a test template rendering a single tag of the construct
- *
- * @param folder
- * folder to which the template is assigned
- * @param construct
- * construct of the template tag
- * @return template
- * @throws Exception
- */
- protected static Template createTemplate(Folder folder, Construct construct)
- throws Exception {
- Transaction t = TransactionManager.getCurrentTransaction();
-
- Template template = t.createObject(Template.class);
- template.setName("hallo");
- template.setFolderId(folder.getId());
- template.setSource("");
- TemplateTag tt = t.createObject(TemplateTag.class);
- tt.setConstructId(construct.getId());
- tt.setEnabled(true);
- tt.setName(VTL_TAGNAME);
- tt.setPublic(true);
- template.getTags().put(VTL_TAGNAME, tt);
- template.save();
-
- return template;
- }
-
- /**
- * Create a test page
- *
- * @param folder
- * folder of the page
- * @param template
- * template of the page
- * @return page
- * @throws Exception
- */
- protected static Page createPage(Folder folder, Template template)
- throws Exception {
- Transaction t = TransactionManager.getCurrentTransaction();
-
- Page page = t.createObject(Page.class);
- page.setFolderId(folder.getId());
- page.setTemplateId(template.getId());
-
- ContentTag tag = page.getContentTag(VTL_TAGNAME);
- tag.getValues().getByKeyname("text")
- .setValueText("This is the test content");
-
- page.save();
-
- return page;
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/ContentNodeTestContext.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/ContentNodeTestContext.java
index 10f91e27c8..df475cb6c9 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/ContentNodeTestContext.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/ContentNodeTestContext.java
@@ -166,9 +166,6 @@ protected void init(boolean startTransaction, boolean force) throws NodeExceptio
NodeConfig nodeConfig = NodeConfigRuntimeConfiguration.getDefault().getNodeConfig();
NodePreferences nodePreferences = nodeConfig.getDefaultPreferences();
- // initialize velocity
- NodeConfigRuntimeConfiguration.initVelocity();
-
factory = ContentNodeFactory.getInstance();
// initialize the permission store
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/GisDirectiveRenderTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/GisDirectiveRenderTest.java
deleted file mode 100644
index cc7b783036..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/GisDirectiveRenderTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-package com.gentics.contentnode.tests.rendering;
-
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.update;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.regex.Pattern;
-
-import org.apache.commons.io.IOUtils;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.etc.Feature;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.factory.url.DynamicUrlFactory;
-import com.gentics.contentnode.factory.url.StaticUrlFactory;
-import com.gentics.contentnode.object.File;
-import com.gentics.contentnode.object.Folder;
-import com.gentics.contentnode.render.RenderResult;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.contentnode.render.RenderUrl;
-import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
-import com.gentics.contentnode.testutils.GCNFeature;
-import com.gentics.testutils.GenericTestUtils;
-
-/**
- * Test cases for rendering the #gtx_gis directive
- */
-@RunWith(value = Parameterized.class)
-@GCNFeature(set = Feature.PUB_DIR_SEGMENT)
-public class GisDirectiveRenderTest extends AbstractVelocityRenderingTest {
- /**
- * Folder
- */
- protected static Folder folder;
-
- /**
- * Image
- */
- protected static File image;
-
- /**
- * SVG Image
- */
- protected static File svgImage;
-
- /**
- * Tested templates
- */
- public final static String[] TEMPLATES = {
- "#gtx_gis($cms.imps.loader.getImage(#IMAGEID#), {\"width\": 100})",
- "#set($image = $cms.imps.loader.getImage(#IMAGEID#))##\n#set($resize = {\"height\": 50, \"mode\": \"smart\"})##\n#set($crop = {\"x\": 10, \"y\": 15, \"width\": 30, \"height\": 35})##\n ",
- "#gtx_gis($cms.imps.loader.getImage(#IMAGEID#), {\"width\": 100, \"type\": \"phpwidget\"})",
- "#set($image = $cms.imps.loader.getImage(#IMAGEID#))##\n#set($resize = {\"type\": \"phpwidget\", \"height\": 50, \"mode\": \"smart\"})##\n#set($crop = {\"x\": 10, \"y\": 15, \"width\": 30, \"height\": 35})##\n ",
- "#gtx_gis($cms.imps.loader.getImage(#IMAGEID#), {\"width\": 80, \"height\": 80, \"mode\": \"force\"})",
- "#gtx_gis($cms.imps.loader.getImage(#IMAGEID#), {\"width\": 100, \"height\": 100, \"mode\": \"fpsmart\"})",
- "#gtx_gis($cms.imps.loader.getImage(#IMAGEID#), {\"width\": 100, \"height\": 1000, \"mode\": \"fpsmart\"})"
- };
-
- /**
- * Prefix
- */
- public final static String PREFIX = "gis_";
-
- /**
- * Tested render modes
- */
- public final static String[] EDIT_MODE = {
- "publish",
- "preview",
- "aloha_readonly",
- "aloha"
- };
-
- /**
- * Get the test parameters
- * @return collection of test parameter sets
- */
- @Parameters(name = "{index}: rendertype: {0}, template: {1}, pub_dir_segment: {2}, svg: {3}")
- public static Collection data() {
- Collection data = new ArrayList();
-
- for (int t = 0; t < TEMPLATES.length; t++) {
- for (int e = 0; e < EDIT_MODE.length; e++) {
- for (boolean pubDirSegment : Arrays.asList(true, false)) {
- for (boolean svg : Arrays.asList(false, true)) {
- data.add(new Object[] { EDIT_MODE[e], t, pubDirSegment, svg });
- }
- }
- }
- }
-
- return data;
- }
-
- @BeforeClass
- public static void setupOnce() throws Exception {
- AbstractVelocityRenderingTest.setupOnce();
-
- Folder mother = update(ContentNodeTestDataUtils.createFolder(node.getFolder(), "Motherfolder"), f -> {
- f.setPublishDir("mother");
- });
-
- folder = update(ContentNodeTestDataUtils.createFolder(mother, "Folder"), f -> {
- f.setPublishDir("/bla");
- });
-
- image = ContentNodeTestDataUtils.createImage(folder, "blume.jpg", IOUtils.toByteArray(GenericTestUtils.getPictureResource("blume.jpg")));
- svgImage = ContentNodeTestDataUtils.createImage(folder, "Cat_silhouette.svg", IOUtils.toByteArray(GisDirectiveRenderTest.class.getResourceAsStream("Cat_silhouette.svg")));
- }
-
- /**
- * Edit mode
- */
- protected int editMode;
-
- /**
- * Expected content
- */
- protected String expectedContent;
-
- /**
- * Create a test instance
- * @param editMode edit mode
- * @param templateIndex template index
- * @param pubDirSegment true for publish directory segments
- * @param svg true for testing svg image
- */
- public GisDirectiveRenderTest(String editMode, int templateIndex, boolean pubDirSegment, boolean svg) throws Exception {
- this.editMode = RenderType.parseEditMode(editMode);
- assertTrue("Given edit mode is unknown", editMode.equals(RenderType.renderEditMode(this.editMode)));
- updateConstruct(fillPlaceholders(TEMPLATES[templateIndex], svg ? svgImage : image));
-
- String fileName = String.format("%s%s_%s%s%s.txt", PREFIX, templateIndex, editMode, (editMode == "publish" && pubDirSegment) ? "_seg" : "", svg ? "_svg" : "");
- expectedContent = fillPlaceholders(IOUtils.toString(getClass().getResourceAsStream(fileName)), svg ? svgImage : image);
-
- node = update(node, n -> {
- n.setPubDirSegment(pubDirSegment);
- });
- }
-
- /**
- * Test rendering
- * @throws Exception
- */
- @Test
- public void testRender() throws Exception {
- Transaction t = TransactionManager.getCurrentTransaction();
-
- // set the render type
- RenderType renderType = RenderType.getDefaultRenderType(testContext.getContext().getNodeConfig().getDefaultPreferences(), editMode, "sid", -1);
- t.setRenderType(renderType);
- // set the url factory
- switch (editMode) {
- case RenderType.EM_PUBLISH:
- renderType.setRenderUrlFactory(new StaticUrlFactory(RenderUrl.LINKWAY_AUTO, RenderUrl.LINKWAY_AUTO, ""));
- break;
- default:
- renderType.setRenderUrlFactory(new DynamicUrlFactory(t.getSessionId()));
- break;
- }
-
- RenderResult renderResult = new RenderResult();
- String content = page.render(renderResult);
-
- // strip away the head, which probably was rendered for aloha editor (we don't want to test it, because it contains
- // JSON and the order of the properties might vary on different systems)
- Pattern pattern = Pattern.compile(".*", Pattern.DOTALL | Pattern.MULTILINE);
- content = pattern.matcher(content).replaceAll("");
-
- assertEquals("Check rendered content", expectedContent, content);
- assertEquals("Check render result", "OK", renderResult.getReturnCode());
- }
-
- /**
- * Fill the placeholders in the given string and return the result
- *
- * #PAGEID# : page ID
- * #IMAGEID# : image ID
- * #TAGID# : tag ID
- *
- * @param string string containing placeholders
- * @param testImage tested image
- * @return string with placeholders filled
- * @throws NodeException
- */
- protected String fillPlaceholders(String string, File testImage) throws NodeException {
- return string.replaceAll("#PAGEID#", Integer.toString(page.getId()))
- .replaceAll("#IMAGEID#", Integer.toString(testImage.getId()))
- .replaceAll("#TAGID#", Integer.toString(page.getTag(VTL_TAGNAME).getId()))
- .replaceAll("#IMAGENAME#", testImage.getFilename()).replaceAll("#IMAGEMD5#", testImage.getMd5()).replaceAll("#NODEID#", Integer.toString(node.getId()));
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/MeshPortalPreviewTestBase.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/MeshPortalPreviewTestBase.java
index b155431668..df51019acc 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/MeshPortalPreviewTestBase.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/MeshPortalPreviewTestBase.java
@@ -18,10 +18,6 @@
import java.util.Map;
import java.util.Set;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.Velocity;
-import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
-import org.apache.velocity.runtime.resource.util.StringResourceRepository;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -54,6 +50,8 @@
import com.gentics.contentnode.testutils.RESTAppContext;
import com.gentics.lib.content.GenticsContentAttribute;
import com.gentics.mesh.core.rest.common.RestModel;
+import com.github.jknack.handlebars.Handlebars;
+import com.github.jknack.handlebars.io.StringTemplateSource;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
@@ -390,15 +388,16 @@ public String render(@PathParam("path") String path, String body) throws Excepti
ObjectMapper objectMapper = new ObjectMapper();
Map, ?> sentNode = objectMapper.readValue(body, Map.class);
- VelocityContext context = new VelocityContext();
- context.put("node", sentNode);
-
- StringResourceRepository srr = StringResourceLoader.getRepository();
- srr.putStringResource("portaltemplate", "$node.fields.tag
$node.fields.live
");
+ com.github.jknack.handlebars.Context context = com.github.jknack.handlebars.Context.newBuilder(null)
+ .combine("node", sentNode)
+ .build();
+ Handlebars handlebars = new Handlebars();
StringWriter outwriter = new StringWriter();
-
- Velocity.getTemplate("portaltemplate").merge(context, outwriter);
+ com.github.jknack.handlebars.Template template = handlebars.compile(new StringTemplateSource(
+ "portaltemplate",
+ "{{{node.fields.tag}}}
{{{node.fields.live}}}
"));
+ template.apply(context, outwriter);
return outwriter.toString();
}
@@ -416,15 +415,16 @@ public String renderPlain(@PathParam("path") String path, String body) throws Ex
ObjectMapper objectMapper = new ObjectMapper();
Map, ?> sentNode = objectMapper.readValue(body, Map.class);
- VelocityContext context = new VelocityContext();
- context.put("node", sentNode);
-
- StringResourceRepository srr = StringResourceLoader.getRepository();
- srr.putStringResource("portaltemplate", "tag: $node.fields.tag, live: $node.fields.live");
+ com.github.jknack.handlebars.Context context = com.github.jknack.handlebars.Context.newBuilder(null)
+ .combine("node", sentNode)
+ .build();
+ Handlebars handlebars = new Handlebars();
StringWriter outwriter = new StringWriter();
-
- Velocity.getTemplate("portaltemplate").merge(context, outwriter);
+ com.github.jknack.handlebars.Template template = handlebars.compile(new StringTemplateSource(
+ "portaltemplate",
+ "tag: {{{node.fields.tag}}}, live: {{{node.fields.live}}}"));
+ template.apply(context, outwriter);
return outwriter.toString();
}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/RenderDirectiveReferenceTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/RenderDirectiveReferenceTest.java
deleted file mode 100644
index 4043a43262..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/RenderDirectiveReferenceTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.gentics.contentnode.tests.rendering;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import com.gentics.contentnode.factory.RenderTypeTrx;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.factory.Trx;
-import com.gentics.contentnode.object.Construct;
-import com.gentics.contentnode.object.Node;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.object.Part;
-import com.gentics.contentnode.object.Template;
-import com.gentics.contentnode.object.parttype.HTMLPartType;
-import com.gentics.contentnode.object.parttype.LongHTMLPartType;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
-import com.gentics.contentnode.testutils.DBTestContext;
-
-/**
- * Test cases for rendering other pages or tags of other pages using the render directive, when the other pages reference objects
- */
-public class RenderDirectiveReferenceTest {
- @ClassRule
- public static DBTestContext testContext = new DBTestContext();
-
- private static Node node;
-
- private static Construct velocityConstruct;
-
- private static Construct htmlConstruct;
-
- private static Template template;
-
- @BeforeClass
- public static void setupOnce() throws Exception {
- node = Trx.supply(() -> ContentNodeTestDataUtils.createNode());
- velocityConstruct = Trx.supply(() -> {
- Transaction t = TransactionManager.getCurrentTransaction();
- Construct construct = ContentNodeTestDataUtils.createVelocityConstruct(node);
- construct = t.getObject(construct, true);
- for (Part p : construct.getParts()) {
- if ("template".equals(p.getKeyname())) {
- p.setEditable(1);
- }
- }
- construct.save();
- return t.getObject(construct);
- });
- htmlConstruct = Trx.supply(() -> TransactionManager.getCurrentTransaction().getObject(Construct.class,
- ContentNodeTestDataUtils.createConstruct(node, HTMLPartType.class, "html", "html")));
- template = Trx.supply(() -> ContentNodeTestDataUtils.createTemplate(node.getFolder(), "[][][]", "Template",
- ContentNodeTestDataUtils.createTemplateTag(velocityConstruct.getId(), "vtl", true, false),
- ContentNodeTestDataUtils.createTemplateTag(htmlConstruct.getId(), "html1", true, false),
- ContentNodeTestDataUtils.createTemplateTag(htmlConstruct.getId(), "html2", true, false)));
- }
-
- /**
- * Test rendering another page using the render directive, where tags in the other page reference each other
- * @throws Exception
- */
- @Test
- public void testRenderOtherPage() throws Exception {
- Page page1 = Trx.supply(() -> {
- Transaction t = TransactionManager.getCurrentTransaction();
- Page p = ContentNodeTestDataUtils.createPage(node.getFolder(), template, "Page 1");
- p = t.getObject(p, true);
- ContentNodeTestDataUtils.getPartType(HTMLPartType.class, p.getContentTag("html1"), "html").getValueObject().setValueText("");
- ContentNodeTestDataUtils.getPartType(HTMLPartType.class, p.getContentTag("html2"), "html").getValueObject().setValueText("Content in Page 1");
- p.save();
- return t.getObject(p);
- });
-
- String content1 = "[][Content in Page 1][Content in Page 1]";
- try (Trx trx = new Trx(); RenderTypeTrx rt = new RenderTypeTrx(RenderType.EM_LIVEPREVIEW)) {
- assertThat(page1.render()).as("Rendered content page 1").isEqualTo(content1);
- }
-
-
- Page page2 = Trx.supply(() -> {
- Transaction t = TransactionManager.getCurrentTransaction();
- Page p = ContentNodeTestDataUtils.createPage(node.getFolder(), template, "Page 2");
- p = t.getObject(p, true);
- ContentNodeTestDataUtils.getPartType(LongHTMLPartType.class, p.getContentTag("vtl"), "template").getValueObject()
- .setValueText("#set($page1 = $cms.imps.loader.getPage(" + page1.getId() + "))##\n$page1\n#gtx_render($page1)");
- ContentNodeTestDataUtils.getPartType(HTMLPartType.class, p.getContentTag("html2"), "html").getValueObject().setValueText("Content in Page 2");
- p.save();
- return t.getObject(p);
- });
-
- String content2 = "[" + content1 + "\n" + content1 + "][][Content in Page 2]";
- try (Trx trx = new Trx(); RenderTypeTrx rt = new RenderTypeTrx(RenderType.EM_LIVEPREVIEW)) {
- assertThat(page2.render()).as("Rendered content").isEqualTo(content2);
- }
- }
-
- /**
- * Test rendering a tag in another page, using the render directive, where the other tag references a tag in the other page
- * @throws Exception
- */
- @Test
- public void testRenderTagOfOtherPage() throws Exception {
- Page page1 = Trx.supply(() -> {
- Transaction t = TransactionManager.getCurrentTransaction();
- Page p = ContentNodeTestDataUtils.createPage(node.getFolder(), template, "Page 1");
- p = t.getObject(p, true);
- ContentNodeTestDataUtils.getPartType(HTMLPartType.class, p.getContentTag("html1"), "html").getValueObject().setValueText("");
- ContentNodeTestDataUtils.getPartType(HTMLPartType.class, p.getContentTag("html2"), "html").getValueObject().setValueText("Content in Page 1");
- p.save();
- return t.getObject(p);
- });
-
- String content1 = "[][Content in Page 1][Content in Page 1]";
- try (Trx trx = new Trx(); RenderTypeTrx rt = new RenderTypeTrx(RenderType.EM_LIVEPREVIEW)) {
- assertThat(page1.render()).as("Rendered content page 1").isEqualTo(content1);
- }
-
- Page page2 = Trx.supply(() -> {
- Transaction t = TransactionManager.getCurrentTransaction();
- Page p = ContentNodeTestDataUtils.createPage(node.getFolder(), template, "Page 2");
- p = t.getObject(p, true);
- ContentNodeTestDataUtils.getPartType(LongHTMLPartType.class, p.getContentTag("vtl"), "template").getValueObject()
- .setValueText("#set($page1 = $cms.imps.loader.getPage(" + page1.getId() + "))##\n$page1.tags.html1\n#gtx_render($page1.tags.html1)");
- ContentNodeTestDataUtils.getPartType(HTMLPartType.class, p.getContentTag("html2"), "html").getValueObject().setValueText("Content in Page 2");
- p.save();
- return t.getObject(p);
- });
-
- try (Trx trx = new Trx(); RenderTypeTrx rt = new RenderTypeTrx(RenderType.EM_LIVEPREVIEW)) {
- assertThat(page2.render()).as("Rendered content").isEqualTo("[Content in Page 1\nContent in Page 1][][Content in Page 2]");
- }
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/SimpleVelocityRenderingSandboxTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/SimpleVelocityRenderingSandboxTest.java
deleted file mode 100644
index cb527299cc..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/SimpleVelocityRenderingSandboxTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.gentics.contentnode.tests.rendering;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.render.RenderResult;
-import com.gentics.contentnode.render.RenderType;
-
-/**
- * Test cases for rendering velocity parts
- */
-public class SimpleVelocityRenderingSandboxTest extends AbstractVelocityRenderingTest {
-
- @Before
- public void setUp() throws NodeException {
- Transaction t = TransactionManager.getCurrentTransaction();
- RenderType renderType = RenderType.getDefaultRenderType(testContext.getContext().getNodeConfig().getDefaultPreferences(), RenderType.EM_PREVIEW, "sid", -1);
- t.setRenderType(renderType);
- }
-
- @Test
- public void testRenderHelloWorld() throws Exception {
- String template = "$cms.imps.velocitytools.esc.url(\"hello &world\")";
- assertEquals("The rendered page should print hello world", "hello%3Cbr%3E%26world", renderTemplate(template));
- }
-
- @Test
- public void testRenderVeloImp() throws Exception {
- String template = "#set ($foo = \"hello world\")$foo";
- assertEquals("The rendered page should print hello world", "hello world", renderTemplate(template));
- }
-
- /**
- * Render the created page with the given content
- *
- * @param template
- * @return
- * @throws Exception
- */
- private String renderTemplate(String template) throws Exception {
- updateConstruct(template);
- TransactionManager.getCurrentTransaction().commit(false);
- RenderResult renderResult = new RenderResult();
- String output = page.render(renderResult);
- assertEquals("The return code was not correct. Output was {" + output + "}. Assert ReturnCode: ", "OK", renderResult.getReturnCode());
- return output;
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityDirectivesTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityDirectivesTest.java
deleted file mode 100644
index 8929508a3f..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityDirectivesTest.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package com.gentics.contentnode.tests.rendering;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-import java.io.ByteArrayInputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.factory.url.StaticUrlFactory;
-import com.gentics.contentnode.object.ContentTag;
-import com.gentics.contentnode.object.File;
-import com.gentics.contentnode.object.ImageFile;
-import com.gentics.contentnode.object.Node;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.object.Template;
-import com.gentics.contentnode.object.TemplateTag;
-import com.gentics.contentnode.object.parttype.ChangeableListPartType;
-import com.gentics.contentnode.object.parttype.CheckboxPartType;
-import com.gentics.contentnode.object.parttype.DHTMLPartType;
-import com.gentics.contentnode.object.parttype.DatasourcePartType;
-import com.gentics.contentnode.object.parttype.FileURLPartType;
-import com.gentics.contentnode.object.parttype.FolderURLPartType;
-import com.gentics.contentnode.object.parttype.HTMLPartType;
-import com.gentics.contentnode.object.parttype.HTMLTextPartType;
-import com.gentics.contentnode.object.parttype.ImageURLPartType;
-import com.gentics.contentnode.object.parttype.JavaEditorPartType;
-import com.gentics.contentnode.object.parttype.LongHTMLPartType;
-import com.gentics.contentnode.object.parttype.LongHTMLTextPartType;
-import com.gentics.contentnode.object.parttype.MultiSelectPartType;
-import com.gentics.contentnode.object.parttype.NodePartType;
-import com.gentics.contentnode.object.parttype.NormalTextPartType;
-import com.gentics.contentnode.object.parttype.OrderedListPartType;
-import com.gentics.contentnode.object.parttype.OverviewPartType;
-import com.gentics.contentnode.object.parttype.PageTagPartType;
-import com.gentics.contentnode.object.parttype.PageURLPartType;
-import com.gentics.contentnode.object.parttype.PartType;
-import com.gentics.contentnode.object.parttype.ShortTextPartType;
-import com.gentics.contentnode.object.parttype.SingleSelectPartType;
-import com.gentics.contentnode.object.parttype.TablePartType;
-import com.gentics.contentnode.object.parttype.TemplateTagPartType;
-import com.gentics.contentnode.object.parttype.UnorderedListPartType;
-import com.gentics.contentnode.render.RenderResult;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.contentnode.render.RenderUrl;
-import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils;
-import com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.PublishTarget;
-import com.gentics.contentnode.testutils.DBTestContext;
-import com.gentics.lib.etc.StringUtils;
-import com.gentics.testutils.GenericTestUtils;
-
-/**
- * Test cases for using the velocity directives #gtx_render and #gtx_edit to render other tags
- */
-@RunWith(value = Parameterized.class)
-public class VelocityDirectivesTest {
- @ClassRule
- public static DBTestContext testContext = new DBTestContext();
-
- /**
- * Tested class
- */
- private Class extends PartType> partTypeClass = null;
-
- /**
- * Tested rendermode
- */
- private int renderMode = 0;
-
- /**
- * Tested template
- */
- private String vtl = null;
-
- private static Node node;
- private static Template template;
- private static Page page;
-
- private static Template targetTemplate;
-
- private static TemplateTag templateTag;
-
- private static Page targetPage;
-
- private static File targetFile;
-
- private static ImageFile targetImage;
-
- @BeforeClass
- public static void setupOnce() throws Exception {
- testContext.getContext().login("node", "node");
-
- // Create node
- node = ContentNodeTestDataUtils.createNode("testnode", "Test Node", PublishTarget.NONE);
-
- // Create velocity construct that renders the given template
- int vtlConstructId = ContentNodeTestDataUtils.createVelocityConstruct(node, "vtl", "vtl");
-
- // Create template using the construct
- Transaction t = TransactionManager.getCurrentTransaction();
- template = t.createObject(Template.class);
- template.setFolderId(node.getFolder().getId());
- template.setMlId(1);
- template.setName("Template");
- template.setSource("");
- TemplateTag vtlTag = t.createObject(TemplateTag.class);
- vtlTag.setConstructId(vtlConstructId);
- vtlTag.setEnabled(true);
- vtlTag.setName("vtl");
- vtlTag.setPublic(false);
- template.getTemplateTags().put(vtlTag.getName(), vtlTag);
- template.save();
- t.commit(false);
-
- // Create a page
- page = t.createObject(Page.class);
- page.setFolderId(node.getFolder().getId());
- page.setTemplateId(template.getId());
- page.setName("Testpage");
- page.save();
- t.commit(false);
-
- // create a target template
- targetTemplate = t.createObject(Template.class);
- targetTemplate.setFolderId(node.getFolder().getId());
- targetTemplate.setMlId(1);
- targetTemplate.setName("Target Template");
- targetTemplate.setSource("");
- templateTag = t.createObject(TemplateTag.class);
- templateTag.setConstructId(vtlConstructId);
- templateTag.setEnabled(true);
- templateTag.setName("vtl");
- templateTag.setPublic(true);
- templateTag.getValues().getByKeyname("template").setValueText("This is the target template tag");
- targetTemplate.getTemplateTags().put(templateTag.getName(), templateTag);
- targetTemplate.save();
- t.commit(false);
-
- // create a target page
- targetPage = t.createObject(Page.class);
- targetPage.setFolderId(node.getFolder().getId());
- targetPage.setTemplateId(targetTemplate.getId());
- targetPage.setName("Target Page");
- targetPage.getContentTag("vtl").getValues().getByKeyname("template").setValueText("This is the target content tag");
- targetPage.save();
- targetPage.publish();
- t.commit(false);
-
- // create a target file
- targetFile = t.createObject(File.class);
- targetFile.setFileStream(new ByteArrayInputStream("File contents".getBytes()));
- targetFile.setFolderId(node.getFolder().getId());
- targetFile.setName("targetfile.txt");
- targetFile.save();
- t.commit(false);
-
- // create a target image
- targetImage = t.createObject(ImageFile.class);
- targetImage.setFileStream(GenericTestUtils.getPictureResource("blume.jpg"));
- targetImage.setFolderId(node.getFolder().getId());
- targetImage.setName("blume.jpg");
- targetImage.save();
- t.commit(false);
- }
-
- /**
- * Get the test parameters
- * @return collection of test parameter sets
- */
- @SuppressWarnings("unchecked")
- @Parameters(name = "{index}: PartType: {0}, rendermode: {1}, template: {2}")
- public static Collection data() {
- Collection data = new ArrayList();
-
- for (Class extends PartType> clazz : Arrays.asList(CheckboxPartType.class, SingleSelectPartType.class, MultiSelectPartType.class,
- ChangeableListPartType.class, OrderedListPartType.class, UnorderedListPartType.class, OverviewPartType.class, PageTagPartType.class,
- TemplateTagPartType.class, HTMLPartType.class, HTMLTextPartType.class, LongHTMLPartType.class, LongHTMLTextPartType.class,
- NormalTextPartType.class, ShortTextPartType.class, FileURLPartType.class, FolderURLPartType.class, ImageURLPartType.class,
- PageURLPartType.class, JavaEditorPartType.class, DHTMLPartType.class, TablePartType.class, DatasourcePartType.class, NodePartType.class)) {
- for (int renderMode : Arrays.asList(RenderType.EM_ALOHA, RenderType.EM_ALOHA_READONLY, RenderType.EM_LIVEPREVIEW,
- RenderType.EM_PREVIEW, RenderType.EM_PUBLISH)) {
- for (String vtl : Arrays.asList("gtx_render_name.vm", "gtx_edit_name.vm", "gtx_render_ref.vm", "gtx_edit_ref.vm")) {
- data.add(new Object[] {clazz, RenderType.renderEditMode(renderMode), vtl});
- }
- }
- }
-
- return data;
- }
-
- /**
- * Create a test instance
- * @param partTypeClass parttype class
- * @param renderMode render mode
- * @param vtl vtl code to render
- */
- public VelocityDirectivesTest(Class extends PartType> partTypeClass, String renderMode, String vtl) {
- this.partTypeClass = partTypeClass;
- this.renderMode = RenderType.parseEditMode(renderMode);
- this.vtl = vtl;
- }
-
- /**
- * Do the test. Render the velocity template, check that the content is not empty and compare with the "old style"
- * @throws Exception
- */
- @Test
- public void test() throws Exception {
- Transaction t = TransactionManager.getCurrentTransaction();
- template = t.getObject(Template.class, template.getId(), true);
- template.getTemplateTag("vtl").getValues().getByKeyname("template").setValueText(StringUtils.readStream(getClass().getResourceAsStream(vtl)));
- template.save();
- t.commit(false);
-
- int testedConstruct = ContentNodeTestDataUtils.createConstruct(node, partTypeClass, partTypeClass.getSimpleName().toLowerCase(), "part");
-
- page = t.getObject(Page.class, page.getId(), true);
- page.setTemplateId(template.getId());
- page.getContent().getTags().clear();
- ContentTag testedTag = page.getContent().addContentTag(testedConstruct);
- testedTag.setName("testtag");
- ContentNodeTestDataUtils.fillValue(testedTag.getValues().getByKeyname("part"), "Test text", true, Arrays.asList("one", "two", "three"), targetPage.getContentTag("vtl"), templateTag,
- targetFile, node, node.getFolder(), targetImage, targetPage);
- testedTag.setEnabled(true);
- page.save();
- t.commit(false);
-
- page = t.getObject(Page.class, page.getId());
- RenderType renderType = RenderType.getDefaultRenderType(testContext.getContext().getNodeConfig().getDefaultPreferences(), renderMode, "sid", -1);
- t.setRenderType(renderType);
- // set the url factory
- renderType.setRenderUrlFactory(new StaticUrlFactory(RenderUrl.LINKWAY_AUTO, RenderUrl.LINKWAY_AUTO, ""));
-
- RenderResult renderResult = new RenderResult();
- String content = page.render(renderResult);
-
- assertFalse("Content must not be empty", ObjectTransformer.isEmpty(content));
-
- template.getTemplateTag("vtl").getValues().getByKeyname("template")
- .setValueText(StringUtils.readStream(getClass().getResourceAsStream("compare_" + vtl)));
- template.save();
- t.commit(false);
-
- String oldContent = page.render(renderResult);
- assertEquals("Check rendered content", oldContent, content);
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityMacroLibraryTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityMacroLibraryTest.java
deleted file mode 100644
index 69188e1053..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityMacroLibraryTest.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package com.gentics.contentnode.tests.rendering;
-
-import static com.gentics.contentnode.factory.Trx.supply;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.create;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createNode;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createPage;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createTemplate;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createVelocityConstruct;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.update;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.time.Duration;
-import java.time.LocalTime;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.commons.io.FileUtils;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.factory.RenderTypeTrx;
-import com.gentics.contentnode.object.Construct;
-import com.gentics.contentnode.object.Node;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.object.Template;
-import com.gentics.contentnode.object.TemplateTag;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.contentnode.testutils.DBTestContext;
-import com.gentics.lib.render.velocity.SerializableVelocityTemplateWrapper;
-
-/**
- * Test configuring and using a velocity macro library with a file resource loader
- */
-public class VelocityMacroLibraryTest {
- /**
- * Name of the macro library file
- */
- public final static String VM_FILENAME = "gtx-vtl-macro-lib.vm";
-
- /**
- * Name of the vtl tag
- */
- public final static String TAG_NAME = "render";
-
- public final static int THREADS = 10;
-
- static {
- // Disable cache. This is necessary for the test, which runs garbage collections while the pages are rendered.
- // If the Velocity templates would be cached, they would never be garbage collected
- System.setProperty("com.gentics.portalnode.portalcache", "false");
- }
-
- /**
- * VTL configuration has to be provided before the DBTestContext (and with it the Velocity Engine) is initialized
- */
- @ClassRule
- public static DBTestContext testContext = new DBTestContext().config(map -> {
- try {
- File macroFile = new File(VelocityMacroLibraryTest.class.getResource(VM_FILENAME).toURI());
- Map velocityConfig = new HashMap<>();
- velocityConfig.put("resource.loader", "string,file");
- velocityConfig.put("file.resource.loader.path", macroFile.getParent());
- velocityConfig.put("file.resource.loader.cache", "true");
- velocityConfig.put("file.resource.loader.modificationCheckInterval", 1);
- velocityConfig.put("velocimacro.library", VM_FILENAME);
- map.set("velocity", velocityConfig);
- } catch (URISyntaxException e) {
- throw new NodeException(e);
- }
- });
-
- private static Node node;
-
- private static Page page;
-
- private static Page inlineMacroPage;
-
- @BeforeClass
- public static void setupOnce() throws NodeException, URISyntaxException, IOException {
- testContext.getContext().getTransaction().commit();
- node = supply(() -> createNode());
- page = createTestPage("#hello()##");
- inlineMacroPage = createTestPage(FileUtils.readFileToString(new File(VelocityMacroLibraryTest.class.getResource("inpage_macro.vm").toURI()), "UTF-8"));
- }
-
- /**
- * Create a velocity construct with the given velocity template code, a cms template using the construct and a test page from the template
- * @param vtlTemplate velocity template code
- * @return page
- * @throws NodeException
- */
- private static Page createTestPage(String vtlTemplate) throws NodeException {
- Construct vtlConstruct = supply(() -> update(createVelocityConstruct(node), c -> {
- c.getValues().getByKeyname("template").setValueText(vtlTemplate);
- }));
-
- Template template = supply(() -> update(createTemplate(node.getFolder(), "Template"), t -> {
- t.getTemplateTags().put(TAG_NAME, create(TemplateTag.class, tag -> {
- tag.setConstructId(vtlConstruct.getId());
- tag.setEnabled(true);
- tag.setName(TAG_NAME);
- tag.setPublic(false);
- }, false));
- t.setSource("");
- }));
-
- return supply(() -> createPage(node.getFolder(), template, "Page"));
- }
-
- /**
- * Return a runnable, which will render the page and check, whether the result
- * contains a '#' (which would be an error, because this would mean that macros
- * were not called)
- *
- * @param page page to be rendered
- * @param counter atomic counter for rendered pages
- * @param errorCounter atomic counter for errors (unresolved macros)
- * @return runnable
- */
- private static Runnable render(Page page, AtomicLong counter, AtomicLong errorCounter) {
- return () -> {
- try {
- String renderedPage = supply(() -> {
- try (RenderTypeTrx rTrx = new RenderTypeTrx(RenderType.EM_PREVIEW)) {
- return page.render();
- }
- });
-
- counter.incrementAndGet();
- if (renderedPage.contains("#")) {
- errorCounter.incrementAndGet();
- }
- } catch (NodeException e) {
- throw new RuntimeException(e);
- }
- };
- }
-
- /**
- * Return a runnable which will call System.gc()
- *
- * @param counter atomic counter for invocations
- * @return runnable
- */
- private static Runnable runGc(AtomicLong counter) {
- return () -> {
- try {
- System.gc();
- counter.incrementAndGet();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- };
- }
-
- /**
- * Test rendering the page
- * @throws Exception
- */
- @Test
- public void test() throws Exception {
- String renderedPage = supply(() -> {
- try (RenderTypeTrx rTrx = new RenderTypeTrx(RenderType.EM_PREVIEW)) {
- return page.render();
- }
- });
-
- assertThat(renderedPage).as("Rendered page").isEqualTo("Hello World!");
- }
-
- /**
- * Test garbage collection while rendering velocity. This test reproduced the
- * problem that instances of {@link SerializableVelocityTemplateWrapper}
- * sometimes were garbage collected while the wrapped template was still
- * rendered. This cause the template's namespace to be dumped so that inline
- * macros could not be resolved any more.
- *
- * @throws Exception
- */
- @Test
- public void testGcWhileRendering() throws Exception {
- ScheduledExecutorService service = Executors.newScheduledThreadPool(THREADS + 1);
-
- LocalTime start = LocalTime.now();
- AtomicLong counter = new AtomicLong();
- AtomicLong errorCounter = new AtomicLong();
- AtomicLong runGcCounter = new AtomicLong();
- Set> futures = new HashSet<>();
-
- // render pages in multiple threads
- for (int i = 0; i < THREADS; i++) {
- futures.add(service.scheduleWithFixedDelay(render(inlineMacroPage, counter, errorCounter), 0, 1, TimeUnit.MILLISECONDS));
- }
-
- // run garbage collector
- futures.add(service.scheduleWithFixedDelay(runGc(runGcCounter), 10, 10, TimeUnit.MILLISECONDS));
-
- Duration dur = Duration.between(start, LocalTime.now());
- while (errorCounter.get() == 0 && dur.toMinutes() < 1) {
- Thread.sleep(1000);
- dur = Duration.between(start, LocalTime.now());
- }
-
- futures.forEach(future -> future.cancel(false));
-
- service.shutdown();
- service.awaitTermination(1, TimeUnit.SECONDS);
-
- if (errorCounter.get() > 0) {
- fail(String.format("%d pages failed to render correctly", errorCounter.get()));
- }
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityNodeNotationTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityNodeNotationTest.java
deleted file mode 100644
index 057515f959..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityNodeNotationTest.java
+++ /dev/null
@@ -1,334 +0,0 @@
-package com.gentics.contentnode.tests.rendering;
-
-import static com.gentics.contentnode.factory.Trx.supply;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.create;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createNode;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createTemplate;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartType;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartTypeId;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.etc.Function;
-import com.gentics.contentnode.factory.RenderTypeTrx;
-import com.gentics.contentnode.object.Construct;
-import com.gentics.contentnode.object.ContentTag;
-import com.gentics.contentnode.object.Node;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.object.Part;
-import com.gentics.contentnode.object.Template;
-import com.gentics.contentnode.object.parttype.LongHTMLPartType;
-import com.gentics.contentnode.object.parttype.VelocityPartType;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.contentnode.testutils.DBTestContext;
-
-/**
- * Testcases for using <node>-Notation in VTL Templates
- */
-@RunWith(value = Parameterized.class)
-public class VelocityNodeNotationTest {
- @ClassRule
- public static DBTestContext testContext = new DBTestContext();
-
- /**
- * Pattern for the template
- */
- public static String TEMPLATE_PATTERN = "this is the template\n[%s]\nthis is the template";
-
- private static Node node;
-
- private static Template template;
-
- /**
- * Construct rendering velocity
- */
- private static Construct vtlConstruct;
-
- /**
- * Construct rendering velocity with inline editable template
- */
- private static Construct inlineEditableVtlConstruct;
-
- /**
- * Construct containing a single, inline editable part
- */
- private static Construct inlineEditableConstruct;
-
- @Parameters(name = "{index}: render {0}")
- public static Collection data() {
- Collection data = new ArrayList<>();
- for (TestedContent test : TestedContent.values()) {
- data.add(new Object[] { test });
- }
- return data;
- }
-
- @BeforeClass
- public static void setupOnce() throws NodeException {
- testContext.getContext().getTransaction().commit();
-
- node = supply(() -> createNode());
- template = supply(() -> createTemplate(node.getFolder(), "Template"));
- vtlConstruct = supply(() -> create(Construct.class, c -> {
- c.setKeyword("vtl");
- c.setName("VTL", 1);
-
- // Velocity part
- c.getParts().add(create(Part.class, p -> {
- p.setKeyname("velocity");
- p.setHidden(false);
- p.setEditable(0);
- p.setName("velocity", 1);
- p.setPartTypeId(getPartTypeId(VelocityPartType.class));
- }, false));
-
- // Template part
- c.getParts().add(create(Part.class, p -> {
- p.setKeyname("template");
- p.setHidden(true);
- p.setEditable(1);
- p.setName("Template", 1);
- p.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- }, false));
-
- // Inline editable part
- c.getParts().add(create(Part.class, p -> {
- p.setKeyname("inline");
- p.setHidden(true);
- p.setEditable(2);
- p.setName("Inline", 1);
- p.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- }, false));
-
- // Editable part
- c.getParts().add(create(Part.class, p -> {
- p.setKeyname("editable");
- p.setHidden(true);
- p.setEditable(1);
- p.setName("Editable", 1);
- p.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- }, false));
- }));
- inlineEditableVtlConstruct = supply(() -> create(Construct.class, c -> {
- c.setKeyword("vtl_inline");
- c.setName("VTL Inline", 1);
-
- // Velocity part
- c.getParts().add(create(Part.class, p -> {
- p.setKeyname("velocity");
- p.setHidden(false);
- p.setEditable(0);
- p.setName("velocity", 1);
- p.setPartTypeId(getPartTypeId(VelocityPartType.class));
- }, false));
-
- // Template part
- c.getParts().add(create(Part.class, p -> {
- p.setKeyname("template");
- p.setHidden(true);
- p.setEditable(2);
- p.setName("Template", 1);
- p.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- }, false));
- }));
-
- inlineEditableConstruct = supply(() -> create(Construct.class, c -> {
- c.setKeyword("inline");
- c.setName("Inline", 1);
-
- // Inline editable part
- c.getParts().add(create(Part.class, p -> {
- p.setKeyname("inline");
- p.setHidden(false);
- p.setEditable(2);
- p.setName("Inline", 1);
- p.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- }, false));
- }));
- }
-
- /**
- * Parameter defining the tested content
- */
- @Parameter(0)
- public TestedContent tested;
-
- /**
- * Test rendering an inline part using the VTL syntax
- * @throws NodeException
- */
- @Test
- public void testRenderVtlSyntax() throws NodeException {
- test(p -> {
- ContentTag tag = p.getContent().addContentTag(vtlConstruct.getId());
- tag.setEnabled(true);
- getPartType(LongHTMLPartType.class, tag, "template").getValueObject().setValueText(String.format(TEMPLATE_PATTERN, "$cms.tag.parts.inline"));
- getPartType(LongHTMLPartType.class, tag, "inline").getValueObject().setValueText(tested.content);
- return tag.getName();
- });
- }
-
- /**
- * Test rendering an inline part using the gtx_edit Directive
- * @throws NodeException
- */
- @Test
- public void testRenderDirective() throws NodeException {
- test(p -> {
- ContentTag tag = p.getContent().addContentTag(vtlConstruct.getId());
- tag.setEnabled(true);
- getPartType(LongHTMLPartType.class, tag, "template").getValueObject().setValueText(String.format(TEMPLATE_PATTERN, "#gtx_edit(\"inline\")"));
- getPartType(LongHTMLPartType.class, tag, "inline").getValueObject().setValueText(tested.content);
- return tag.getName();
- });
- }
-
- /**
- * Test rendering an inline part using the <node>-Notation
- * @throws NodeException
- */
- @Test
- public void testRenderNodeSyntax() throws NodeException {
- test(p -> {
- ContentTag tag = p.getContent().addContentTag(vtlConstruct.getId());
- tag.setEnabled(true);
- getPartType(LongHTMLPartType.class, tag, "template").getValueObject().setValueText(String.format(TEMPLATE_PATTERN, ""));
- getPartType(LongHTMLPartType.class, tag, "inline").getValueObject().setValueText(tested.content);
- return tag.getName();
- });
- }
-
- /**
- * Test rendering another part (using VTL syntax), that renders the inline editable part using <node>-Notation
- * @throws NodeException
- */
- @Test
- public void testRenderIndirectNodeSyntax() throws NodeException {
- test(p -> {
- ContentTag tag = p.getContent().addContentTag(vtlConstruct.getId());
- tag.setEnabled(true);
- getPartType(LongHTMLPartType.class, tag, "template").getValueObject().setValueText(String.format(TEMPLATE_PATTERN, "$cms.tag.parts.editable"));
- getPartType(LongHTMLPartType.class, tag, "editable").getValueObject().setValueText("");
- getPartType(LongHTMLPartType.class, tag, "inline").getValueObject().setValueText(tested.content);
- return tag.getName();
- });
- }
-
- /**
- * Test rendering another part (using <node>-Notation), that renders the inline editable part using <node>-Notation
- * @throws NodeException
- */
- @Test
- public void testRenderIndirectDoubleNodeSyntax() throws NodeException {
- test(p -> {
- ContentTag tag = p.getContent().addContentTag(vtlConstruct.getId());
- tag.setEnabled(true);
- getPartType(LongHTMLPartType.class, tag, "template").getValueObject().setValueText(String.format(TEMPLATE_PATTERN, ""));
- getPartType(LongHTMLPartType.class, tag, "editable").getValueObject().setValueText("");
- getPartType(LongHTMLPartType.class, tag, "inline").getValueObject().setValueText(tested.content);
- return tag.getName();
- });
- }
-
- /**
- * Test rendering another tag (containing an inline editable part) using the <node>-Notation
- * @throws NodeException
- */
- @Test
- public void testRenderOtherTagNodeSyntax() throws NodeException {
- test(p -> {
- ContentTag otherTag = p.getContent().addContentTag(inlineEditableConstruct.getId());
- otherTag.setEnabled(true);
- getPartType(LongHTMLPartType.class, otherTag, "inline").getValueObject().setValueText(tested.content);
-
- ContentTag tag = p.getContent().addContentTag(vtlConstruct.getId());
- tag.setEnabled(true);
- getPartType(LongHTMLPartType.class, tag, "template").getValueObject().setValueText(String.format(TEMPLATE_PATTERN, ""));
- return tag.getName();
- });
- }
-
- @Test
- public void testInlineEditableTemplate() throws NodeException {
- test(p -> {
- ContentTag otherTag = p.getContent().addContentTag(inlineEditableConstruct.getId());
- otherTag.setEnabled(true);
- getPartType(LongHTMLPartType.class, otherTag, "inline").getValueObject().setValueText(tested.content);
-
- ContentTag tag = p.getContent().addContentTag(inlineEditableVtlConstruct.getId());
- tag.setEnabled(true);
- getPartType(LongHTMLPartType.class, tag, "template").getValueObject().setValueText(String.format(TEMPLATE_PATTERN, "$cms.page.tags." + otherTag.getName()));
- return tag.getName();
- });
- }
-
- /**
- * Generic test method. Will create a page, pass the page to the
- * setupFunction, render the tag (which was returned by the setupFunction)
- * and compare the result with expected result
- *
- * @param setupFunction setup function. Gets the page and must return the name of the Velocity Tag
- * @throws NodeException
- */
- protected void test(Function setupFunction) throws NodeException {
- AtomicReference tagName = new AtomicReference<>();
- Page page = create(Page.class, p -> {
- p.setTemplateId(template.getId());
- p.setFolderId(node.getFolder().getId());
- p.setName("Page");
-
- tagName.set(setupFunction.apply(p));
- });
-
- String renderedContent = supply(() -> {
- try (RenderTypeTrx rTrx = new RenderTypeTrx(RenderType.EM_PREVIEW)) {
- return page.render(String.format("", tagName.get()), null, null, null, null, null);
- }
- });
-
- assertThat(renderedContent).as("Rendered tag").isEqualTo(tested.expected);
- }
-
- /**
- * Enum of tested contents
- */
- public static enum TestedContent {
- hash("before the evil part ##evil after the evil part"),
- dollar("before the evil part $cms.page after the evil part"),
- backslash("before the evil part \\evil after the evil part"),
- singlequote("before the evil part 'evil' after the evil part"),
- doublequote("before the evil part \"evil\" after the evil part"),
- exclamation("before the evil part !evil! after the evil part");
-
- /**
- * Content containing evil characters
- */
- public String content;
-
- /**
- * Expected rendered content
- */
- public String expected;
-
- /**
- * Create instance with content
- * @param content content
- */
- private TestedContent(String content) {
- this.content = content;
- this.expected = String.format(TEMPLATE_PATTERN, content);
- }
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityRenderingSandboxTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityRenderingSandboxTest.java
deleted file mode 100644
index db989a4abf..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelocityRenderingSandboxTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-package com.gentics.contentnode.tests.rendering;
-
-import static com.gentics.contentnode.tests.utils.Builder.create;
-import static com.gentics.contentnode.tests.utils.Builder.update;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartType;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartTypeId;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.regex.Pattern;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.factory.url.StaticUrlFactory;
-import com.gentics.contentnode.object.Construct;
-import com.gentics.contentnode.object.ContentTag;
-import com.gentics.contentnode.object.Part;
-import com.gentics.contentnode.object.parttype.PageURLPartType;
-import com.gentics.contentnode.render.RenderResult;
-import com.gentics.contentnode.render.RenderType;
-import com.gentics.contentnode.render.RenderUrl;
-
-/**
- * Test cases for rendering velocity parts
- */
-@RunWith(value = Parameterized.class)
-public class VelocityRenderingSandboxTest extends AbstractVelocityRenderingTest {
-
- /**
- * Tested templates
- */
- public final static String[] TEMPLATES = {
- "before[#gtx_render(\"text\")]middle[#gtx_render(\"text\")]after",
- "before[#gtx_render($cms.tag.parts.text)]middle[#gtx_render($cms.tag.parts.text)]after",
- "before[#gtx_edit(\"text\")]middle[#gtx_render(\"text\")]after",
- "before[#gtx_render(\"text\")]middle[#gtx_edit(\"text\")]after",
- "before[#gtx_edit($cms.tag.parts.text)]middle[#gtx_render($cms.tag.parts.text)]after",
- "before[#gtx_render($cms.tag.parts.text)]middle[#gtx_edit($cms.tag.parts.text)]after",
- "before[#gtx_edit($cms.page.tags.vtltag.parts.text)]middle[#gtx_render($cms.page.tags.vtltag.parts.text)]after",
- "before[#gtx_render($cms.page.tags.vtltag.parts.text)]middle[#gtx_edit($cms.page.tags.vtltag.parts.text)]after",
- "before[#gtx_edit($cms.page.tags.url_construct1)]middle[#gtx_render($cms.page.tags.url_construct1)]after",
- "before[#gtx_render($cms.page.tags.url_construct1)]middle[#gtx_edit($cms.page.tags.url_construct1)]after",
- };
-
- /**
- * Tested render modes
- */
- public final static String[] EDIT_MODE = {
- "publish",
- "preview",
- "aloha_readonly",
- "aloha"
- };
-
- /**
- * Get the test parameters
- * @return collection of test parameter sets
- */
- @Parameters(name = "{index}: rendertype: {0}, template: {1}")
- public static Collection data() {
- Collection data = new ArrayList();
-
- for (int t = 0; t < TEMPLATES.length; t++) {
- for (int e = 0; e < EDIT_MODE.length; e++) {
- data.add(new Object[] {EDIT_MODE[e], t});
- }
- }
-
- return data;
- }
-
- static Construct urlConstruct;
-
- /**
- * Edit mode
- */
- protected int editMode;
-
- /**
- * Flag to mark whether the template renders the part in edit mode
- */
- protected boolean templateRendersInEditMode;
-
- /**
- * Whether to expect the editable after rendered content, not before
- */
- protected boolean editAfterRender;
-
- /**
- * Whether to expect the whole tag rendering, instead of its distinct part
- */
- protected boolean renderWholeTag;
-
- /**
- * The expected tag content
- */
- protected String tagContent;
-
- /**
- * Create a test instance
- * @param editMode edit mode
- * @param templateIndex template index
- */
- public VelocityRenderingSandboxTest(String editMode, int templateIndex) throws Exception {
- this.editMode = RenderType.parseEditMode(editMode);
- this.templateRendersInEditMode = TEMPLATES[templateIndex].contains("gtx_edit");
- this.editAfterRender = TEMPLATES[templateIndex].indexOf("gtx_edit") > TEMPLATES[templateIndex].indexOf("gtx_render");
- this.renderWholeTag = TEMPLATES[templateIndex].contains(".") && (TEMPLATES[templateIndex].contains(".tags.") || TEMPLATES[templateIndex].endsWith(".tag")) && !TEMPLATES[templateIndex].contains(".parts.");
- this.tagContent = TEMPLATES[templateIndex].contains("tags.url_construct") ? "/nowhere/82.html" : "This is the test content";
- assertTrue("Given edit mode is unknown", editMode.equals(RenderType.renderEditMode(this.editMode)));
- updateConstruct(TEMPLATES[templateIndex]);
- }
-
- @BeforeClass
- public static void setupMore() throws NodeException {
- urlConstruct = create(Construct.class, c -> {
- c.setAutoEnable(true);
- c.setKeyword("url_construct");
- c.setName("url_construct", 1);
-
- c.getParts().add(create(Part.class, p -> {
- p.setPartTypeId(getPartTypeId(PageURLPartType.class));
- p.setEditable(2);
- p.setHidden(false);
- p.setKeyname("page");
- }).doNotSave().build());
- }).build();
-
- page = update(page, p -> {
- ContentTag urlsTag = p.getContent().addContentTag(urlConstruct.getId());
-
- // Since adding partial localization, addContentTag() will generate a UUID suffix for generated tag. For testing
- // purposes we need to set the tagname explicitly.
- urlsTag.setName("url_construct1");
- getPartType(PageURLPartType.class, urlsTag, "page").setTargetPage(page);
- getPartType(PageURLPartType.class, urlsTag, "page").setNode(node);
- }).unlock().build();
- page = update(page, p -> {
- }).unlock().publish().build();
- }
-
- @Test
- public void testRender() throws Exception {
- Transaction t = TransactionManager.getCurrentTransaction();
-
- // set the render type
- RenderType renderType = RenderType.getDefaultRenderType(testContext.getContext().getNodeConfig().getDefaultPreferences(), editMode, "sid", -1);
- t.setRenderType(renderType);
- // set the url factory
- renderType.setRenderUrlFactory(new StaticUrlFactory(RenderUrl.LINKWAY_AUTO, RenderUrl.LINKWAY_AUTO, ""));
-
- RenderResult renderResult = new RenderResult();
- String content = page.render(renderResult);
-
- // strip away the head, which probably was rendered for aloha editor (we don't want to test it, because it contains
- // JSON and the order of the properties might vary on different systems)
- Pattern pattern = Pattern.compile(".*", Pattern.DOTALL | Pattern.MULTILINE);
- content = pattern.matcher(content).replaceAll("");
-
- assertEquals("Check rendered content", getExpectedContent(), content);
- assertEquals("Check render result", "OK", renderResult.getReturnCode());
- }
-
- /**
- * Get the expected content
- * @return
- * @throws Exception
- */
- protected String getExpectedContent() throws Exception {
- // prepare data which is rendered into the editable tags
- String pageId = ObjectTransformer.getString(page.getId(), null);
- String tagId = ObjectTransformer.getString(page.getContentTag(VTL_TAGNAME).getId(), null);
- String urlTagId = ObjectTransformer.getString(page.getContentTag("url_construct1").getId(), null);
- String constructName = page.getContentTag(VTL_TAGNAME).getConstruct().getName().toString();
- String valueId = ObjectTransformer.getString(page.getContentTag(VTL_TAGNAME).getValues().getByKeyname("text").getId(), null);
- String expected = null;
- switch (editMode) {
- case RenderType.EM_ALOHA:
- String editablePart = null;
- if (templateRendersInEditMode) {
- if (renderWholeTag) {
- editablePart = "" + this.tagContent + "
";
- } else {
- editablePart = "" + this.tagContent + "
";
- }
- } else {
- editablePart = this.tagContent;
- }
- expected = "before[" + this.tagContent + "]middle[" + editablePart + "]after
";
- } else {
- expected = expected + "\">before[" + editablePart + "]middle[" + this.tagContent + "]after";
- }
- break;
- default:
- expected = "before[" + this.tagContent + "]middle[" + this.tagContent + "]after";
- break;
- }
- switch (editMode) {
- case RenderType.EM_ALOHA:
- case RenderType.EM_ALOHA_READONLY:
- expected = "\n\n" + expected + "\n";
- break;
- }
- return expected;
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelomacroRenderSandboxTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelomacroRenderSandboxTest.java
deleted file mode 100644
index b7b1deb6f0..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rendering/VelomacroRenderSandboxTest.java
+++ /dev/null
@@ -1,218 +0,0 @@
-package com.gentics.contentnode.tests.rendering;
-
-import static com.gentics.contentnode.tests.utils.ContentNodeRESTUtils.assertResponseOK;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createNode;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createVelocityConstruct;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartType;
-import static org.junit.Assert.assertEquals;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.factory.Transaction;
-import com.gentics.contentnode.factory.TransactionManager;
-import com.gentics.contentnode.factory.Trx;
-import com.gentics.contentnode.object.Folder;
-import com.gentics.contentnode.object.Node;
-import com.gentics.contentnode.object.Page;
-import com.gentics.contentnode.object.Template;
-import com.gentics.contentnode.object.TemplateTag;
-import com.gentics.contentnode.object.parttype.TextPartType;
-import com.gentics.contentnode.rest.model.request.LinksType;
-import com.gentics.contentnode.rest.model.response.PageRenderResponse;
-import com.gentics.contentnode.rest.resource.PageResource;
-import com.gentics.contentnode.rest.resource.impl.PageResourceImpl;
-import com.gentics.contentnode.testutils.DBTestContext;
-
-/**
- * Tests for rendering velocity tags containing macros
- */
-public class VelomacroRenderSandboxTest {
- @Rule
- public DBTestContext testContext = new DBTestContext();
-
- /**
- * Number of different templates
- */
- protected final static int NUM_TEMPLATES = 5;
-
- /**
- * Number of pages generated per template
- */
- protected final static int NUM_PAGES_PER_TEMPLATE = 10;
-
- /**
- * Number of threads that render pages
- */
- protected final static int NUM_THREADS = 10;
-
- /**
- * Node for the test data
- */
- protected Node node;
-
- /**
- * Collection of templates
- */
- protected Collection templates = new ArrayList();
-
- /**
- * Collection of test pages
- */
- protected Collection pages = new ArrayList();
-
- @Before
- public void setUp() throws Exception {
- testContext.getContext().login("node", "node");
- node = createNode("Test Node", "test", "/Content.Node", null, false, false, false);
- Folder root = node.getFolder();
-
- for (int i = 0; i < NUM_TEMPLATES; i++) {
- String name = "Template" + i;
- templates.add(createVelocityTemplate(node, name, generateVTL(name)));
- }
-
- for (int i = 0; i < NUM_PAGES_PER_TEMPLATE; i++) {
- for (Template template : templates) {
- pages.add(createPage(root, template, "Page " + i + " of " + template.getName()));
- }
- }
- }
-
- /**
- * Test rendering the pages using velocity macros in several threads
- * @throws Exception
- */
- @Test
- public void testRendering() throws Throwable {
- Transaction t = TransactionManager.getCurrentTransaction();
- List threads = new ArrayList(NUM_THREADS);
-
- for (int i = 0; i < NUM_THREADS; i++) {
- PageRenderThread thread = new PageRenderThread(t.getSessionId());
- threads.add(thread);
- thread.start();
- }
-
- for (PageRenderThread thread : threads) {
- thread.join();
- }
-
- for (PageRenderThread thread : threads) {
- thread.assertSuccess();
- }
- }
-
- /**
- * Create a template containing a single (non editable) tag that renders the given vtl using velocity
- * @param node node
- * @param name template name
- * @param vtl velocity code
- * @return template
- * @throws NodeException
- */
- protected Template createVelocityTemplate(Node node, String name, String vtl) throws NodeException {
- int vtlConstructId = createVelocityConstruct(node, "velocity", "vtl");
- Transaction t = TransactionManager.getCurrentTransaction();
- Template template = t.createObject(Template.class);
- template.setFolderId(node.getFolder().getId());
- template.setMlId(1);
- template.setName(name);
- template.setSource("");
-
- TemplateTag tag = t.createObject(TemplateTag.class);
- tag.setConstructId(vtlConstructId);
- tag.setEnabled(true);
- tag.setName("velocity");
- tag.setPublic(false);
- getPartType(TextPartType.class, tag, "template").getValueObject().setValueText(vtl);
- template.getTemplateTags().put("velocity", tag);
-
- template.save();
- t.commit(false);
-
- return t.getObject(Template.class, template.getId());
- }
-
- /**
- * Create a page in the folder using the given template
- * @param folder folder
- * @param template template
- * @param name name
- * @return page
- * @throws NodeException
- */
- protected Page createPage(Folder folder, Template template, String name) throws NodeException {
- Transaction t = TransactionManager.getCurrentTransaction();
- Page page = t.createObject(Page.class);
- page.setFolderId(folder.getId());
- page.setTemplateId(template.getId());
- page.setName(name);
- page.save();
- t.commit(false);
- return t.getObject(Page.class, page.getId());
- }
-
- /**
- * Generate the vtl for the given test template
- * @param name template name
- * @return vtl
- */
- protected String generateVTL(String name) {
- StringBuilder vtl = new StringBuilder();
- vtl.append("#testmacro(1 10)##\n");
- vtl.append("#macro(testmacro $level $max)##\n");
- vtl.append("#set($a = \"").append(name).append("\")##\n");
- vtl.append("$a##\n");
- vtl.append("#if($level < $max)##\n");
- vtl.append("#set($level = $level + 1)##\n");
- vtl.append("#testmacro($level $max)##\n");
- vtl.append("#end##\n");
- vtl.append("#end##\n");
- return vtl.toString();
- }
-
- public class PageRenderThread extends Thread {
- protected Throwable e;
-
- protected String sid;
-
- public PageRenderThread(String sid) {
- this.sid = sid;
- }
-
- @Override
- public void run() {
- try (Trx trx = new Trx(sid, -1)) {
- for (Page page : pages) {
- PageResource resource = new PageResourceImpl();
-
- PageRenderResponse renderResponse = resource.render(ObjectTransformer.getString(page.getId(), null), null, null, false, null,
- LinksType.frontend, false, false, false, 0);
- assertResponseOK(renderResponse);
- assertEquals("Check rendered content", StringUtils.repeat(page.getTemplate().getName(), 10), renderResponse.getContent());
- }
- } catch (Throwable e) {
- this.e = e;
- }
- }
-
- /**
- * Assert success of all render calls
- * @throws Exception
- */
- public void assertSuccess() throws Throwable {
- if (e != null) {
- throw e;
- }
- }
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rest/DiffSandboxTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rest/DiffSandboxTest.java
index febcb8967c..c4fa3f90d0 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rest/DiffSandboxTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/rest/DiffSandboxTest.java
@@ -82,13 +82,13 @@ public void testDiffHTMLWithInsertTemplate() {
request.setContent1("one two four five ");
request.setContent2("one two three four five ");
- request.setInsertTemplate("[$insert]");
+ request.setInsertTemplate("[{{insert}}]");
DiffResponse response = diffResource.diffHTML(request);
assertEquals("Check diff", "one two [three ]four five ", response.getDiff());
// test again using a template with wrong placeholder
- request.setInsertTemplate("[$remove]");
+ request.setInsertTemplate("[{{remove}}]");
response = diffResource.diffHTML(request);
assertEquals("Check diff", "one two []four five ", response.getDiff());
}
@@ -103,13 +103,13 @@ public void testDiffHTMLWithRemoveTemplate() {
request.setContent1("one two three four five ");
request.setContent2("one two four five ");
- request.setRemoveTemplate("[$remove]");
+ request.setRemoveTemplate("[{{remove}}]");
DiffResponse response = diffResource.diffHTML(request);
assertEquals("Check diff", "one two [three ]four five ", response.getDiff());
// test again using a template with wrong placeholder
- request.setRemoveTemplate("[$insert]");
+ request.setRemoveTemplate("[{{insert}}]");
response = diffResource.diffHTML(request);
assertEquals("Check diff", "one two []four five ", response.getDiff());
}
@@ -124,13 +124,13 @@ public void testDiffHTMLWithChangeTemplate() {
request.setContent1("one two three four five ");
request.setContent2("one two THREE four five ");
- request.setChangeTemplate("[$remove|$insert]");
+ request.setChangeTemplate("[{{remove}}|{{insert}}]");
DiffResponse response = diffResource.diffHTML(request);
assertEquals("Check diff", "one two [three|THREE] four five ", response.getDiff());
// test again using a different template
- request.setChangeTemplate("[$insert|$remove]");
+ request.setChangeTemplate("[{{insert}}|{{remove}}]");
response = diffResource.diffHTML(request);
assertEquals("Check diff", "one two [THREE|three] four five ", response.getDiff());
}
@@ -145,7 +145,7 @@ public void testDiffWordsBefore() {
request.setContent1("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ");
request.setContent2("1 2 3 4 5 6 7 8 9 10 11 12 13 NEW 14 15 ");
- request.setInsertTemplate("[($before) $insert]");
+ request.setInsertTemplate("[({{before}}) {{insert}}]");
// first test with the default value (10 words, spaces count as words)
DiffResponse response = diffResource.diffHTML(request);
@@ -168,7 +168,7 @@ public void testDiffWordsAfter() {
request.setContent1("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ");
request.setContent2("1 2 NEW 3 4 5 6 7 8 9 10 11 12 13 14 15 ");
- request.setInsertTemplate("[$insert ($after)]");
+ request.setInsertTemplate("[{{insert}} ({{after}})]");
// first test with the default value (10 words, spaces count as words)
DiffResponse response = diffResource.diffHTML(request);
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rest/PartTypeResourceImplTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rest/PartTypeResourceImplTest.java
deleted file mode 100644
index 166104c7fa..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/rest/PartTypeResourceImplTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.gentics.contentnode.tests.rest;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import com.gentics.api.lib.exception.NodeException;
-import com.gentics.contentnode.db.DBUtils;
-import com.gentics.contentnode.factory.Trx;
-import com.gentics.contentnode.rest.model.PartType;
-import com.gentics.contentnode.rest.resource.impl.PartTypeResourceImpl;
-import com.gentics.contentnode.rest.resource.parameter.FilterParameterBean;
-import com.gentics.contentnode.testutils.DBTestContext;
-import java.util.List;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-
-public class PartTypeResourceImplTest {
-
- @ClassRule
- public static DBTestContext testContext = new DBTestContext();
-
- @Test
- public void givenPartTypeRequest_shouldReturnItems() throws NodeException {
- List partTypes = new PartTypeResourceImpl().list(null);
-
- assertThat(partTypes).isNotEmpty();
- assertThat(partTypes.get(0)).hasFieldOrProperty("id");
- assertThat(partTypes.get(0)).hasFieldOrProperty("name");
- assertThat(partTypes.get(0)).hasFieldOrProperty("deprecated");
- assertThat(partTypes.get(0)).hasFieldOrProperty("javaClass");
- }
-
- @Test
- public void givenFilteredRequest_shouldContainOnlyDeprecatedItems() throws NodeException {
- Trx.operate(() -> DBUtils.update("UPDATE `type` SET `deprecated` = ? where id = ?", 1, 9));
-
- List partTypes = new PartTypeResourceImpl().list(
- new FilterParameterBean().setQuery("1"));
-
- assertThat(partTypes).isNotEmpty();
- assertThat(partTypes.get(0)).hasFieldOrPropertyWithValue("deprecated", true);
- }
-
-
-}
\ No newline at end of file
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/rest/PartTypeResourceListTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/rest/PartTypeResourceListTest.java
new file mode 100644
index 0000000000..7e55bef121
--- /dev/null
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/rest/PartTypeResourceListTest.java
@@ -0,0 +1,94 @@
+package com.gentics.contentnode.tests.rest;
+
+import static com.gentics.contentnode.factory.Trx.operate;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Function;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.gentics.api.lib.exception.NodeException;
+import com.gentics.contentnode.db.DBUtils;
+import com.gentics.contentnode.factory.PartTypeFactory;
+import com.gentics.contentnode.rest.model.PartType;
+import com.gentics.contentnode.rest.model.response.AbstractListResponse;
+import com.gentics.contentnode.rest.resource.PartTypeResource;
+import com.gentics.contentnode.rest.resource.impl.PartTypeResourceImpl;
+import com.gentics.contentnode.rest.resource.parameter.FilterParameterBean;
+import com.gentics.contentnode.rest.resource.parameter.PagingParameterBean;
+import com.gentics.contentnode.rest.resource.parameter.PartTypeListParameterBean;
+import com.gentics.contentnode.rest.resource.parameter.SortParameterBean;
+
+/**
+ * Sorting and filtering tests for {@link PartTypeResource#list(FilterParameterBean, SortParameterBean, PagingParameterBean, PartTypeListParameterBean)}
+ */
+public class PartTypeResourceListTest extends AbstractListSortAndFilterTest {
+ @Parameters(name = "{index}: sortBy {0}, ascending {2}, filter {3}")
+ public static Collection data() {
+ // "id", "name", "javaclass", "deprecated"
+ List>> sortAttributes = Arrays.asList(
+ Pair.of("id", item -> addLeadingZeros(item.getId())),
+ Pair.of("name", PartType::getName),
+ Pair.of("javaClass", PartType::getJavaClass),
+ Pair.of("deprecated", item -> Boolean.toString(item.isDeprecated()))
+ );
+
+ // "name", "description", "javaclass", "deprecated"
+ List>> filterAttributes = Arrays.asList(
+ Pair.of("name", PartType::getName),
+ Pair.of("description", PartType::getDescription),
+ Pair.of("javaClass", PartType::getJavaClass),
+ Pair.of("deprecated", item -> Boolean.toString(item.isDeprecated()))
+ );
+ return data(sortAttributes, filterAttributes);
+ }
+
+
+ @Override
+ protected PartType createItem() throws NodeException {
+ return null;
+ }
+
+ @Override
+ protected void fillItemsList(List super PartType> items) throws NodeException {
+ operate(() -> {
+ PartTypeFactory factory = PartTypeFactory.getInstance();
+
+ DBUtils.select("SELECT * FROM `type`", rs -> {
+ while (rs.next()) {
+ PartType partType = new PartType()
+ .setId(rs.getInt("id"))
+ .setName(rs.getString("name"))
+ .setDescription(rs.getString("description"))
+ .setJavaClass(rs.getString("javaclass"))
+ .setDeprecated(rs.getBoolean("deprecated"));
+
+ if (factory.isAvailable(partType.getId())) {
+ items.add(partType);
+ }
+ }
+ return null;
+ });
+ });
+ }
+
+ @Override
+ protected AbstractListResponse getResult(SortParameterBean sort, FilterParameterBean filter,
+ PagingParameterBean paging) throws NodeException {
+ PartTypeListParameterBean partTypeFilter = new PartTypeListParameterBean();
+
+ if (filterBy != null) {
+ switch (filterBy) {
+ case "deprecated":
+ partTypeFilter.deprecated = Boolean.valueOf(filter.query);
+ filter.query = null;
+ break;
+ }
+ }
+
+ return new PartTypeResourceImpl().list(filter, sort, paging, partTypeFilter);
+ }
+}
\ No newline at end of file
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/utils/ContentNodeTestDataUtils.java b/cms-core/src/test/java/com/gentics/contentnode/tests/utils/ContentNodeTestDataUtils.java
index a6a7c75e3f..197d5b29f8 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/utils/ContentNodeTestDataUtils.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/utils/ContentNodeTestDataUtils.java
@@ -7,7 +7,6 @@
import static org.junit.Assert.assertNotNull;
import java.io.ByteArrayInputStream;
-import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -24,8 +23,6 @@
import java.util.Properties;
import java.util.Set;
-import jakarta.ws.rs.core.MediaType;
-
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.glassfish.jersey.media.multipart.BodyPart;
@@ -34,7 +31,6 @@
import org.glassfish.jersey.media.multipart.MultiPart;
import org.junit.Assert;
-import com.gentics.api.contentnode.parttype.ExtensiblePartType;
import com.gentics.api.contentnode.publish.CnMapPublishHandler;
import com.gentics.api.lib.etc.ObjectTransformer;
import com.gentics.api.lib.exception.InsufficientPrivilegesException;
@@ -82,17 +78,13 @@
import com.gentics.contentnode.object.UserGroup;
import com.gentics.contentnode.object.Value;
import com.gentics.contentnode.object.ValueContainer;
-import com.gentics.contentnode.object.parttype.BreadcrumbPartType;
import com.gentics.contentnode.object.parttype.ChangeableListPartType;
import com.gentics.contentnode.object.parttype.CheckboxPartType;
import com.gentics.contentnode.object.parttype.DatasourcePartType;
-import com.gentics.contentnode.object.parttype.ExtensiblePartTypeWrapper;
import com.gentics.contentnode.object.parttype.FileURLPartType;
import com.gentics.contentnode.object.parttype.FolderURLPartType;
import com.gentics.contentnode.object.parttype.ImageURLPartType;
import com.gentics.contentnode.object.parttype.ListPartType;
-import com.gentics.contentnode.object.parttype.LongHTMLPartType;
-import com.gentics.contentnode.object.parttype.NavigationPartType;
import com.gentics.contentnode.object.parttype.NodePartType;
import com.gentics.contentnode.object.parttype.OverviewPartType;
import com.gentics.contentnode.object.parttype.PageTagPartType;
@@ -101,7 +93,6 @@
import com.gentics.contentnode.object.parttype.SelectPartType;
import com.gentics.contentnode.object.parttype.TemplateTagPartType;
import com.gentics.contentnode.object.parttype.TextPartType;
-import com.gentics.contentnode.object.parttype.VelocityPartType;
import com.gentics.contentnode.perm.PermissionStore;
import com.gentics.contentnode.rest.model.request.FileSaveRequest;
import com.gentics.contentnode.rest.model.request.FolderSaveRequest;
@@ -128,21 +119,13 @@
import com.gentics.testutils.GenericTestUtils;
import com.gentics.testutils.infrastructure.TestEnvironment;
+import jakarta.ws.rs.core.MediaType;
+
/**
* Static helper class for generation of test data
*/
public class ContentNodeTestDataUtils {
- /**
- * Name of the template part for a velocity construct
- */
- public static final String TEMPLATE_PARTNAME = "template";
-
- /**
- * Name of the startfolder part for a breadcrumb/navigation construct
- */
- public static final String STARTFOLDER_PARTNAME = "startfolder";
-
/**
* Id of the System Group
*/
@@ -208,9 +191,6 @@ public static int createConstruct(Node node, int partTypeId
* @throws NodeException
*/
public static int createConstruct(Node node, Class clazz, String constructKeyword, String partKeyword) throws NodeException {
- if (clazz.isAssignableFrom(ExtensiblePartTypeWrapper.class)) {
- return createVelocityConstruct(node, constructKeyword, partKeyword);
- }
Transaction t = TransactionManager.getCurrentTransaction();
// when creating a construct with a SelectPartType part, we create a Datasource first
@@ -236,181 +216,6 @@ public static int createConstruct(Node node, Class clazz
return createConstruct(node, getPartTypeId(clazz), constructKeyword, partKeyword, ds);
}
- /**
- * Create a construct with a visible part of given clazz.
- * This method can be used for {@link VelocityPartType}, {@link BreadcrumbPartType} or {@link NavigationPartType}
- * @param node node
- * @param clazz parttype class
- * @param constructKeyword keyword of the construct
- * @param partKeyword keyword of the part
- * @return id of the construct
- * @throws NodeException
- */
- public static int createExtensibleConstruct(Node node, Class clazz, String constructKeyword, String partKeyword)
- throws NodeException {
- if (clazz.isAssignableFrom(VelocityPartType.class)) {
- return createVelocityConstruct(node, constructKeyword, partKeyword);
- } else if (clazz.isAssignableFrom(BreadcrumbPartType.class)) {
- return createBreadcrumbConstruct(node, constructKeyword, partKeyword);
- } else if (clazz.isAssignableFrom(NavigationPartType.class)) {
- return createNavigationConstruct(node, constructKeyword, partKeyword);
- } else {
- throw new NodeException("Unable to create construct for parttype " + clazz);
- }
- }
-
- /**
- * Create a construct containing a velocity part
- * @param node node
- * @param constructKeyword construct keyword
- * @param partKeyword part keyword for the velocity part
- * @return construct id
- * @throws NodeException
- */
- public static int createVelocityConstruct(Node node, String constructKeyword, String partKeyword) throws NodeException {
- Transaction t = TransactionManager.getCurrentTransaction();
- Construct construct = t.createObject(Construct.class);
- construct.setAutoEnable(true);
- construct.setKeyword(constructKeyword);
- construct.setName(constructKeyword, 1);
- if (node != null) {
- construct.getNodes().add(node);
- }
-
- Part vtlPart = t.createObject(Part.class);
- vtlPart.setEditable(0);
- vtlPart.setHidden(false);
- vtlPart.setKeyname(partKeyword);
- vtlPart.setName(partKeyword, 1);
- vtlPart.setPartTypeId(getPartTypeId(VelocityPartType.class));
- construct.getParts().add(vtlPart);
-
- Part templatePart = t.createObject(Part.class);
- templatePart.setEditable(1);
- templatePart.setHidden(true);
- templatePart.setKeyname(TEMPLATE_PARTNAME);
- templatePart.setName(TEMPLATE_PARTNAME, 1);
- templatePart.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- t.createObject(Value.class).setPart(templatePart);
- construct.getParts().add(templatePart);
-
- construct.save();
- t.commit(false);
-
- return ObjectTransformer.getInt(construct.getId(), 0);
- }
-
- /**
- * Create a default breadcrumb construct
- * @param node node
- * @param constructKeyword construct keyword
- * @param partKeyword part keyword
- * @return construct id
- * @throws NodeException
- */
- public static int createBreadcrumbConstruct(Node node, String constructKeyword, String partKeyword) throws NodeException {
- Transaction t = TransactionManager.getCurrentTransaction();
- Construct construct = t.createObject(Construct.class);
- construct.setAutoEnable(true);
- construct.setKeyword(constructKeyword);
- construct.setName(constructKeyword, 1);
- construct.getNodes().add(node);
-
- // breadcrumb part
- Part vtlPart = t.createObject(Part.class);
- vtlPart.setEditable(0);
- vtlPart.setHidden(false);
- vtlPart.setKeyname(partKeyword);
- vtlPart.setName(partKeyword, 1);
- vtlPart.setPartTypeId(getPartTypeId(BreadcrumbPartType.class));
- construct.getParts().add(vtlPart);
-
- // template part
- Part templatePart = t.createObject(Part.class);
- templatePart.setEditable(1);
- templatePart.setHidden(true);
- templatePart.setKeyname(TEMPLATE_PARTNAME);
- templatePart.setName(TEMPLATE_PARTNAME, 1);
- templatePart.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- templatePart.setDefaultValue(t.createObject(Value.class));
- try {
- templatePart.getDefaultValue().setValueText(StringUtils.readStream(ContentNodeTestDataUtils.class.getResourceAsStream("breadcrumb.vm")));
- } catch (IOException e) {
- throw new NodeException("Could not create breadcrumb part", e);
- }
- construct.getParts().add(templatePart);
-
- // startfolder part
- Part startfolderPart = t.createObject(Part.class);
- startfolderPart.setEditable(1);
- startfolderPart.setHidden(true);
- startfolderPart.setKeyname(STARTFOLDER_PARTNAME);
- startfolderPart.setName(STARTFOLDER_PARTNAME, 1);
- startfolderPart.setPartTypeId(getPartTypeId(FolderURLPartType.class));
- startfolderPart.setDefaultValue(t.createObject(Value.class));
- construct.getParts().add(startfolderPart);
-
- construct.save();
- t.commit(false);
-
- return ObjectTransformer.getInt(construct.getId(), 0);
- }
-
- /**
- * Create a default navigation construct
- * @param node node
- * @param constructKeyword construct keyword
- * @param partKeyword part keyword
- * @return construct id
- * @throws NodeException
- */
- public static int createNavigationConstruct(Node node, String constructKeyword, String partKeyword) throws NodeException {
- Transaction t = TransactionManager.getCurrentTransaction();
- Construct construct = t.createObject(Construct.class);
- construct.setAutoEnable(true);
- construct.setKeyword(constructKeyword);
- construct.setName(constructKeyword, 1);
- construct.getNodes().add(node);
-
- // breadcrumb part
- Part vtlPart = t.createObject(Part.class);
- vtlPart.setEditable(0);
- vtlPart.setHidden(false);
- vtlPart.setKeyname(partKeyword);
- vtlPart.setName(partKeyword, 1);
- vtlPart.setPartTypeId(getPartTypeId(NavigationPartType.class));
- construct.getParts().add(vtlPart);
-
- // template part
- Part templatePart = t.createObject(Part.class);
- templatePart.setEditable(1);
- templatePart.setHidden(true);
- templatePart.setKeyname(TEMPLATE_PARTNAME);
- templatePart.setName(TEMPLATE_PARTNAME, 1);
- templatePart.setPartTypeId(getPartTypeId(LongHTMLPartType.class));
- templatePart.setDefaultValue(t.createObject(Value.class));
- try {
- templatePart.getDefaultValue().setValueText(StringUtils.readStream(ContentNodeTestDataUtils.class.getResourceAsStream("navigation.vm")));
- } catch (IOException e) {
- throw new NodeException("Could not create breadcrumb part", e);
- }
- construct.getParts().add(templatePart);
-
- // startfolder part
- Part startfolderPart = t.createObject(Part.class);
- startfolderPart.setEditable(1);
- startfolderPart.setHidden(true);
- startfolderPart.setKeyname(STARTFOLDER_PARTNAME);
- startfolderPart.setName(STARTFOLDER_PARTNAME, 1);
- startfolderPart.setPartTypeId(getPartTypeId(FolderURLPartType.class));
- startfolderPart.setDefaultValue(t.createObject(Value.class));
- construct.getParts().add(startfolderPart);
-
- construct.save();
- t.commit(false);
-
- return ObjectTransformer.getInt(construct.getId(), 0); }
-
/**
* Get the parttype id for the given parttype class
* @param clazz class
@@ -868,64 +673,6 @@ public static ObjectTagDefinition createObjectTagDefinition(String objTagName, i
return objProp;
}
- /**
- * Creates a velocity construct
- *
- * @return
- * @throws NodeException
- */
- public static Construct createVelocityConstruct(Node node) throws NodeException {
- Transaction t = TransactionManager.getCurrentTransaction();
-
- Construct construct = t.createObject(Construct.class);
- construct.setKeyword("constr");
- construct.setName("Construct (de)", 1);
- construct.setName("Construct (en)", 2);
- construct.getNodes().add(node);
-
- Part velPart = t.createObject(Part.class);
- velPart.setKeyname("velocity");
- velPart.setHidden(false);
- velPart.setEditable(0);
- velPart.setName("velocity", 1);
- velPart.setName("velocity", 2);
- velPart.setPartOrder(1);
- velPart.setPartTypeId(33);
-
- Part tplPart = t.createObject(Part.class);
- tplPart.setKeyname("template");
- tplPart.setHidden(true);
- tplPart.setEditable(0);
- tplPart.setName("tpl", 1);
- tplPart.setName("tpl", 2);
- tplPart.setPartOrder(2);
- tplPart.setPartTypeId(21);
-
- Part textPart = t.createObject(Part.class);
- textPart.setKeyname("text");
- textPart.setHidden(true);
- textPart.setEditable(2);
- textPart.setName("Text", 1);
- textPart.setName("Text", 2);
- textPart.setPartOrder(3);
- textPart.setPartTypeId(1);
-
- List parts = construct.getParts();
- parts.add(velPart);
- parts.add(tplPart);
- parts.add(textPart);
-
- Value vval = t.createObject(Value.class);
- vval.setContainer(construct);
- vval.setPart(tplPart);
- vval.setValueText("");
- tplPart.setDefaultValue(vval);
-
- construct.save();
-
- return construct;
- }
-
/**
* Create a new node.
* If the publish target is CONTENTREPOSITORY it will create a cr in memory.
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/utils/CountDirectiveRule.java b/cms-core/src/test/java/com/gentics/contentnode/tests/utils/CountDirectiveRule.java
deleted file mode 100644
index 7f75d99a33..0000000000
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/utils/CountDirectiveRule.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.gentics.contentnode.tests.utils;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
-
-/**
- * Test rule that assert that the {@link #CountDirective} was never invoked
- */
-public class CountDirectiveRule extends TestWatcher {
- /**
- * Rendered name
- */
- protected String renderedName;
-
- /**
- * Create rule for rendered name
- * @param renderedName rendered name
- */
- public CountDirectiveRule(String renderedName) {
- this.renderedName = renderedName;
- }
-
- @Override
- protected void starting(Description description) {
- CountDirective.reset();
- }
-
- @Override
- protected void finished(Description description) {
- assertEquals("Check render counts", 0, CountDirective.get(renderedName));
- }
-}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/utils/CountDirective.java b/cms-core/src/test/java/com/gentics/contentnode/tests/utils/CountHelperSource.java
similarity index 56%
rename from cms-core/src/test/java/com/gentics/contentnode/tests/utils/CountDirective.java
rename to cms-core/src/test/java/com/gentics/contentnode/tests/utils/CountHelperSource.java
index 365f1520e5..4a4dc80fd9 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/utils/CountDirective.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/utils/CountHelperSource.java
@@ -2,32 +2,13 @@
import static org.assertj.core.api.Assertions.assertThat;
-import java.io.IOException;
-import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
-import org.apache.velocity.context.InternalContextAdapter;
-import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.runtime.directive.Directive;
-import org.apache.velocity.runtime.parser.node.Node;
+import com.github.jknack.handlebars.helper.HelperFunction;
-import com.gentics.api.lib.etc.ObjectTransformer;
-
-/**
- * A simple velocity directive that just counts in a static field, how many
- * times it has been rendered.
- *
- * Additionally, the rendered content can be changed (default is empty)
- *
- * It can be used like
- * #gtx_test_count("bla")
- *
- */
-public class CountDirective extends Directive {
+public class CountHelperSource {
/**
* Render counts
*/
@@ -73,25 +54,15 @@ public static AutoCloseable asserter(String name, int expectedCount) {
return new Asserter(name, expectedCount);
}
- @Override
- public String getName() {
- return "gtx_test_count";
- }
-
- @Override
- public int getType() {
- return LINE;
- }
-
- @Override
- public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException,
- MethodInvocationException {
- String name = ObjectTransformer.getString(node.jjtGetChild(0).value(context), "");
+ /**
+ * Count the occurrance of the given name
+ * @param name name
+ * @return which should be rendered
+ */
+ @HelperFunction("gtx_test_count")
+ public static String count(String name) {
renderCounts.computeIfAbsent(name, key -> new AtomicInteger()).incrementAndGet();
- if (!ObjectTransformer.isEmpty(render)) {
- writer.write(render);
- }
- return true;
+ return render;
}
/**
@@ -110,12 +81,12 @@ protected static class Asserter implements AutoCloseable {
protected Asserter(String name, int expectedCount) {
this.name = name;
this.expectedCount = expectedCount;
- CountDirective.reset();
+ CountHelperSource.reset();
}
@Override
public void close() throws Exception {
- assertThat(CountDirective.get(name)).as("Count for " + name).isEqualTo(expectedCount);
+ assertThat(CountHelperSource.get(name)).as("Count for " + name).isEqualTo(expectedCount);
}
}
}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/tests/versioning/PageVersionsSandboxTest.java b/cms-core/src/test/java/com/gentics/contentnode/tests/versioning/PageVersionsSandboxTest.java
index 4fcbef1bd6..19ef364156 100644
--- a/cms-core/src/test/java/com/gentics/contentnode/tests/versioning/PageVersionsSandboxTest.java
+++ b/cms-core/src/test/java/com/gentics/contentnode/tests/versioning/PageVersionsSandboxTest.java
@@ -1,60 +1,118 @@
package com.gentics.contentnode.tests.versioning;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestUtils.clearNodeObjectCache;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestUtils.publishPage;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestUtils.setRenderType;
-import static com.gentics.contentnode.tests.utils.ContentNodeTestUtils.waitMS;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static com.gentics.contentnode.factory.Trx.consume;
+import static com.gentics.contentnode.factory.Trx.execute;
+import static com.gentics.contentnode.factory.Trx.operate;
+import static com.gentics.contentnode.factory.Trx.supply;
+import static com.gentics.contentnode.tests.assertj.GCNAssertions.assertThat;
+import static com.gentics.contentnode.tests.utils.Builder.create;
+import static com.gentics.contentnode.tests.utils.Builder.update;
+import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.clear;
+import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createConstruct;
+import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.createNode;
+import static com.gentics.contentnode.tests.utils.ContentNodeTestDataUtils.getPartType;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
-import java.sql.ResultSet;
+import java.util.concurrent.atomic.AtomicReference;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
import org.junit.Test;
-import com.gentics.api.lib.etc.ObjectTransformer;
-import com.gentics.contentnode.etc.ContentNodeHelper;
-import com.gentics.contentnode.factory.Transaction;
+import com.gentics.api.lib.exception.NodeException;
+import com.gentics.contentnode.db.DBUtils;
+import com.gentics.contentnode.etc.ContentNodeDate;
+import com.gentics.contentnode.factory.RenderTypeTrx;
+import com.gentics.contentnode.factory.TransactionManager;
+import com.gentics.contentnode.factory.Trx;
import com.gentics.contentnode.object.ContentTag;
import com.gentics.contentnode.object.Folder;
-import com.gentics.contentnode.object.Page;
+import com.gentics.contentnode.object.Node;
import com.gentics.contentnode.object.NodeObjectVersion;
+import com.gentics.contentnode.object.Overview;
+import com.gentics.contentnode.object.Page;
import com.gentics.contentnode.object.Template;
-import com.gentics.contentnode.object.Value;
+import com.gentics.contentnode.object.TemplateTag;
+import com.gentics.contentnode.object.parttype.LongHTMLPartType;
+import com.gentics.contentnode.object.parttype.OverviewPartType;
import com.gentics.contentnode.object.parttype.PageTagPartType;
-import com.gentics.contentnode.render.RenderResult;
-import com.gentics.contentnode.render.RenderType;
+import com.gentics.contentnode.object.parttype.handlebars.HandlebarsPartType;
+import com.gentics.contentnode.testutils.DBTestContext;
+import com.gentics.contentnode.testutils.LoaderHelperSource;
+import com.gentics.contentnode.testutils.TestHelpersHandlebarsService;
/**
* Page Versions Sandbox Test contains tests for versioned publishing
*/
-public class PageVersionsSandboxTest extends AbstractPageVersioningTest {
+public class PageVersionsSandboxTest {
+ protected final static String HTML_CONSTRUCT_NAME = "html";
- /**
- * Id of the template for using in the versions tests
- */
- public final static int VERSIONS_TEMPLATE_ID = 80;
+ protected final static String HTML_PART_NAME = "html";
- /**
- * Id of the folder for using in the versions tests
- */
- public final static int VERSIONS_FOLDER_ID = 42;
+ protected final static String OVERVIEW_CONSTRUCT_NAME = "overview";
- /**
- * Id of the overview page
- */
- public final static int OVERVIEW_PAGE_ID = 52;
+ protected final static String OVERVIEW_PART_NAME = "overview";
- /**
- * Id of the page tag construct
- */
- public final static int PAGE_TAG_CONSTRUCT_ID = 13;
+ protected final static String PAGETAG_CONSTRUCT_NAME = "pagetag";
- /**
- * Id of the velocity construct
- */
- public final static int VELOCITY_CONSTRUCT_ID = 2;
+ protected final static String PAGETAG_PART_NAME = "pagetag";
+
+ protected final static String HBS_CONSTRUCT_NAME = "hbs";
+
+ protected final static String HBS_PART_NAME = "hbs";
+
+ protected final static String TEMPLATE_TAG_NAME = "html";
+
+ @ClassRule
+ public static DBTestContext testContext = new DBTestContext();
+ private static Node node;
+
+ private static int htmlConstructId;
+ private static int overviewConstructId;
+ private static int pagetagConstructId;
+ private static int hbsConstructId;
+
+ private static Template template;
+
+
+ @BeforeClass
+ public static void setupOnce() throws NodeException {
+ testContext.getContext().getTransaction().commit();
+ TestHelpersHandlebarsService.addHelper(LoaderHelperSource.class);
+
+ node = supply(() -> createNode());
+
+ htmlConstructId = supply(() -> createConstruct(node, LongHTMLPartType.class, HTML_CONSTRUCT_NAME, HTML_PART_NAME));
+ overviewConstructId = supply(() -> createConstruct(node, OverviewPartType.class, OVERVIEW_CONSTRUCT_NAME, OVERVIEW_PART_NAME));
+ pagetagConstructId = supply(() -> createConstruct(node, PageTagPartType.class, PAGETAG_CONSTRUCT_NAME, PAGETAG_PART_NAME));
+ hbsConstructId = supply(() -> createConstruct(node, HandlebarsPartType.class, HBS_CONSTRUCT_NAME, HBS_PART_NAME));
+
+ template = create(Template.class, tmpl -> {
+ tmpl.setFolderId(node.getFolder().getId());
+ tmpl.setName("Template");
+ tmpl.setMlId(1);
+
+ tmpl.getTags().put(TEMPLATE_TAG_NAME, create(TemplateTag.class, tt -> {
+ tt.setConstructId(htmlConstructId);
+ tt.setEnabled(true);
+ tt.setPublic(true);
+ tt.setName(TEMPLATE_TAG_NAME);
+ }).doNotSave().build());
+
+ tmpl.setSource("".formatted(TEMPLATE_TAG_NAME));
+ }).build();
+ }
+
+ @Before
+ public void setup() throws NodeException {
+ operate(() -> clear(node));
+
+ template = update(template, upd -> {
+ upd.setSource("".formatted(TEMPLATE_TAG_NAME));
+ }).build();
+ }
/**
* Test creation of a page version for a new page
@@ -63,33 +121,29 @@ public class PageVersionsSandboxTest extends AbstractPageVersioningTest {
*/
@Test
public void testCreatePageVersion() throws Exception {
- Transaction t = testContext.startTransactionWithPermissions(true);
String name = "Create Page Version";
String filename = "create_page_version.html";
String content = "Name: , Filename: , Version: ";
// create a page and check whether it has a page version with number 0.1
- Page page = createPage(VERSIONS_TEMPLATE_ID, VERSIONS_FOLDER_ID, name, filename, content);
- Integer pageId = page.getId();
-
- clearNodeObjectCache();
-
- // wait a sec
- waitMS(1000);
-
- // start a new transaction
- t = testContext.startTransactionWithPermissions(false);
-
- // get the page
- page = t.getObject(Page.class, pageId);
- assertNotNull("Check whether the create page was found", page);
-
- // get the versions and check them
- NodeObjectVersion[] pageVersions = page.getVersions();
-
- assertEquals("Check the # of page versions", 1, pageVersions.length);
- assertEquals("Check number of created version", "0.1", pageVersions[0].getNumber());
- assertEquals("Check whether version is published", false, pageVersions[0].isPublished());
+ Page page = create(Page.class, p -> {
+ p.setName(name);
+ p.setFilename(filename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
+
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(content);
+ }).at(1000).build();
+
+ // reload the page
+ page = execute(Page::reload, page);
+ assertThat(page).as("Created page").isNotNull();
+
+ // versions
+ NodeObjectVersion[] pageVersions = execute(Page::getVersions, page);
+ assertThat(pageVersions).as("Page versions")
+ .usingRecursiveFieldByFieldElementComparatorOnFields("versionNumber", "published", "current", "date")
+ .containsExactly(new NodeObjectVersion(0, "0.1", null, new ContentNodeDate(1000), true, false));
}
/**
@@ -99,52 +153,47 @@ public void testCreatePageVersion() throws Exception {
*/
@Test
public void testPublishPageVersion() throws Exception {
- Transaction t = testContext.startTransactionWithPermissions(true);
String name = "Publish Page Version";
String filename = "publish_page_version.html";
String content = "Name: , Filename: , Version: ";
// create a page and publish it
- Page page = createPage(VERSIONS_TEMPLATE_ID, VERSIONS_FOLDER_ID, name, filename, content);
- Integer pageId = page.getId();
-
- clearNodeObjectCache();
+ Page page = create(Page.class, p -> {
+ p.setName(name);
+ p.setFilename(filename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
- // wait a sec
- waitMS(1000);
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(content);
+ }).at(1000).build();
// publish the page
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), page);
+ page = update(page, p -> {}).at(2000).publish().build();
- // start a new transaction
- t = testContext.startTransactionWithPermissions(false);
-
- // get the page
- setRenderType(RenderType.EM_PREVIEW);
- RenderResult renderResult = new RenderResult();
-
- page = t.getObject(Page.class, pageId);
- assertTrue("Check whether the current version of the page was fetched now", page.getObjectInfo().getVersionTimestamp() < 0);
- assertNotNull("Check whether the created page was found", page);
-
- // get the versions and check them
- NodeObjectVersion[] pageVersions = page.getVersions();
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
- assertEquals("Check the # of page versions", 1, pageVersions.length);
- assertEquals("Check number of created version", "1.0", pageVersions[0].getNumber());
- assertEquals("Check whether version is published", true, pageVersions[0].isPublished());
+ // reload
+ page = execute(Page::reload, page);
+ assertThat(page.getObjectInfo().getVersionTimestamp()).as("Version timestamp").isLessThan(0);
- ContentNodeHelper.setLanguageId(1);
+ // versions
+ NodeObjectVersion[] pageVersions = execute(Page::getVersions, page);
+ assertThat(pageVersions).as("Page versions")
+ .usingRecursiveFieldByFieldElementComparatorOnFields("versionNumber", "published", "current", "date")
+ .containsExactly(new NodeObjectVersion(0, "1.0", null, new ContentNodeDate(2000), true, true), new NodeObjectVersion(0, "0.1", null, new ContentNodeDate(1000), false, false));
- // render live preview of page (current version)
- String livePreview = page.render(renderResult);
+ String expected = "Name: %s, Filename: %s, Version: %s".formatted(name, filename, "1.0");
- assertEquals("Check the live preview of the page", "Name: " + name + ", Filename: " + filename + ", Version: 1.0", livePreview);
+ try (Trx trx = new Trx(); RenderTypeTrx rTrx = RenderTypeTrx.publish()) {
+ assertThat(page.render()).as("Rendered page").isEqualTo(expected);
+ trx.success();
+ }
// get the published version
- String publishedContent = getPublishedContent(ObjectTransformer.getInt(pageId, 0));
-
- assertEquals("Check the published content of the page", "Name: " + name + ", Filename: " + filename + ", Version: 1.0", publishedContent);
+ assertThat(getPublishedContent(page.getId())).as("Published page content").isEqualTo(expected);
}
/**
@@ -155,69 +204,63 @@ public void testPublishPageVersion() throws Exception {
*/
@Test
public void testModifyPublishedPage() throws Exception {
- // create a page and publish it.
- Transaction t = testContext.startTransactionWithPermissions(true);
-
- ContentNodeHelper.setLanguageId(1);
-
String name = "Publish Page Version";
String filename = "publish_page_version.html";
String content = "Name: , Filename: , Version: ";
// create a page and publish it
- Page page = createPage(VERSIONS_TEMPLATE_ID, VERSIONS_FOLDER_ID, name, filename, content);
- Integer pageId = page.getId();
-
- clearNodeObjectCache();
+ Page page = create(Page.class, p -> {
+ p.setName(name);
+ p.setFilename(filename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
- // wait a sec
- waitMS(1000);
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(content);
+ }).at(1000).build();
// publish the page
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), page);
+ page = update(page, p -> {}).at(2000).publish().build();
- // start a new transaction
- t = testContext.startTransactionWithPermissions(false);
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
// modify the page
- page = t.getObject(Page.class, pageId, true);
- page.setName("Modified " + page.getName());
- page.setFilename("modified_" + page.getFilename());
- Value value = (Value) page.getContentTag(CONTENTTAG_NAME).getValues().get(PART_NAME);
+ page = update(page, update -> {
+ update.setName("Modified " + update.getName());
+ update.setFilename("modified_" + update.getFilename());
- value.setValueText("Modified Content: " + value.getValueText());
- page.save();
- t.commit();
+ LongHTMLPartType partType = getPartType(LongHTMLPartType.class, update.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME);
+ partType.setText("Modified Content: " + partType.getText());
+ }).at(3000).doNotPublish().build();
- // check whether a new version was created
- t = testContext.startTransactionWithPermissions(false);
- page = t.getObject(Page.class, pageId);
- NodeObjectVersion[] pageVersions = page.getVersions();
+ NodeObjectVersion[] pageVersions = execute(Page::getVersions, page);
- assertEquals("Check number of page versions", 2, pageVersions.length);
- assertEquals("Check version number of last version", "1.1", pageVersions[0].getNumber());
- assertEquals("Check whether last version is published", false, pageVersions[0].isPublished());
+ assertThat(pageVersions).as("Page versions")
+ .usingRecursiveFieldByFieldElementComparatorOnFields("versionNumber", "published", "current", "date")
+ .containsExactly(
+ new NodeObjectVersion(0, "1.1", null, new ContentNodeDate(3000), true, false),
+ new NodeObjectVersion(0, "1.0", null, new ContentNodeDate(2000), false, true),
+ new NodeObjectVersion(0, "0.1", null, new ContentNodeDate(1000), false, false));
// render a live preview of the page and check whether it renders the
// modified content
- setRenderType(RenderType.EM_PREVIEW);
- assertNotNull("Check whether the created page was found", page);
- assertTrue("Check whether the current version of the page was fetched now", page.getObjectInfo().getVersionTimestamp() < 0);
- RenderResult renderResult = new RenderResult();
- String livePreview = page.render(renderResult);
-
- assertEquals("Check preview content of the modified page",
- "Modified Content: Name: Modified " + name + ", Filename: modified_" + filename + ", Version: 1.1", livePreview);
+ try (Trx trx = new Trx(); RenderTypeTrx rTrx = RenderTypeTrx.publish()) {
+ assertThat(page.render()).as("Rendered page")
+ .isEqualTo("Modified Content: Name: Modified %s, Filename: modified_%s, Version: %s".formatted(name,
+ filename, "1.1"));
+ trx.success();
+ }
// render the page for publishing and check whether it is the
// unmodified version of the page
- page = page.getPublishedObject();
- assertNotNull("Check whether the created page was found", page);
- assertTrue("Check whether a versioned page was fetched now", page.getObjectInfo().getVersionTimestamp() > 0);
- renderResult = new RenderResult();
- String publishedPage = page.render(renderResult);
-
- assertEquals("Check published content of the modified page", "Name: " + name + ", Filename: " + filename + ", Version: 1.0", publishedPage);
+ try (Trx trx = new Trx(); RenderTypeTrx rTrx = RenderTypeTrx.publish()) {
+ assertThat(page.getPublishedObject().render()).as("Rendered published page")
+ .isEqualTo("Name: %s, Filename: %s, Version: %s".formatted(name,
+ filename, "1.0"));
+ trx.success();
+ }
}
/**
@@ -227,91 +270,96 @@ public void testModifyPublishedPage() throws Exception {
*/
@Test
public void testReferencingModifiedPage() throws Exception {
- Transaction t = testContext.startTransactionWithPermissions(true);
-
- ContentNodeHelper.setLanguageId(1);
String name = "Referenced Page";
String filename = "referenced_page.html";
String content = "Referenced Content";
- // get the overview page
- Page overviewPage = (Page) t.getObject(Page.class, OVERVIEW_PAGE_ID);
+ // create overview page
+ Page overviewPage = create(Page.class, p -> {
+ p.setName("Overview");
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
+
+ ContentTag overviewTag = p.getContent().addContentTag(overviewConstructId);
+ Overview overview = getPartType(OverviewPartType.class, overviewTag, OVERVIEW_PART_NAME).getOverview();
+ overview.setObjectClass(Page.class);
+ overview.setSelectionType(Overview.SELECTIONTYPE_PARENT);
+ overview.setOrderKind(Overview.ORDER_NAME);
+ overview.setOrderWay(Overview.ORDERWAY_DESC);
+ getPartType(OverviewPartType.class, overviewTag, OVERVIEW_PART_NAME).getValueObject().setValueText("Name: , Filename: , Version: , Content: ");
+
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME)
+ .setText("".formatted(overviewTag.getName()));
+ }).at(1000).build();
// Create a referenced page
- Page page = createPage(VERSIONS_TEMPLATE_ID, ObjectTransformer.getInt(overviewPage.getFolder().getId(), 0), name, filename, content);
- Integer pageId = page.getId();
+ Page page = create(Page.class, p -> {
+ p.setName(name);
+ p.setFilename(filename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
- // wait a sec
- waitMS(1500);
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(content);
+ }).at(1000).build();
// publish the pages
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), overviewPage, page);
- overviewPage = t.getObject(Page.class, overviewPage.getId());
- NodeObjectVersion publishedOverviewVersion = overviewPage.getPublishedVersion();
-
- String expectedContent = "Name: " + name + ", Filename: " + filename + ", Version: 1.0, Content: " + content + " ";
+ overviewPage = update(overviewPage, p -> {}).at(2000).publish().build();
+ page = update(page, p -> {}).at(2000).publish().build();
- expectedContent += "Name: " + overviewPage.getName() + ", Filename: " + overviewPage.getFilename() + ", Version: "
- + publishedOverviewVersion.getNumber() + ", Content: ";
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
- String overviewContent = getPublishedContent(OVERVIEW_PAGE_ID);
+ String expectedContent = "Name: " + name + ", Filename: " + filename + ", Version: 1.0, Content: " + content + " ";
+ expectedContent += "Name: " + overviewPage.getName() + ", Filename: " + overviewPage.getFilename() + ", Version: 1.0, Content: ";
- assertEquals("Check the content of the overview page", expectedContent, overviewContent);
+ String overviewContent = getPublishedContent(overviewPage.getId());
- // wait a sec
- waitMS(1500);
+ assertThat(overviewContent).as("Published overview page").isEqualTo(expectedContent);
// modify the page
- t = testContext.startTransactionWithPermissions(false);
- page = t.getObject(Page.class, pageId, true);
-
- page.setName(page.getName() + " (Modified)");
- page.setFilename("modified_" + page.getFilename());
- Value value = (Value) page.getContentTag(CONTENTTAG_NAME).getValues().get(PART_NAME);
-
- value.setValueText("Modified Content: " + value.getValueText());
- page.save();
- t.commit(false);
+ page = update(page, upd -> {
+ upd.setName(upd.getName() + " (Modified)");
+ upd.setFilename("modified_" + upd.getFilename());
+ LongHTMLPartType partType = getPartType(LongHTMLPartType.class, upd.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME);
+ partType.setText("Modified Content: " + partType.getText());
+ }).at(3000).doNotPublish().build();
// change and republish the overview page
- overviewPage = t.getObject(Page.class, OVERVIEW_PAGE_ID, true);
- overviewPage.setName(overviewPage.getName() + " republished");
- overviewPage.save();
- t.commit(false);
- clearNodeObjectCache();
+ overviewPage = update(overviewPage, upd -> {
+ upd.setName(upd.getName() + " republished");
+ }).at(3000).publish().build();
- // wait a sec
- waitMS(1500);
-
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), overviewPage);
- overviewPage = t.getObject(Page.class, overviewPage.getId());
- publishedOverviewVersion = overviewPage.getPublishedVersion();
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
// get the rendered content of the overview page
- overviewContent = getPublishedContent(OVERVIEW_PAGE_ID);
+ overviewContent = getPublishedContent(overviewPage.getId());
+
// change the expected content (overview has a new page, but referenced page is unmodified)
expectedContent = "Name: " + name + ", Filename: " + filename + ", Version: 1.0, Content: " + content + " ";
- expectedContent += "Name: " + overviewPage.getName() + ", Filename: " + overviewPage.getFilename() + ", Version: "
- + publishedOverviewVersion.getNumber() + ", Content: ";
- assertEquals("Check the content of the overview page after modifying referenced page", expectedContent, overviewContent);
-
- // wait a sec
- waitMS(1500);
+ expectedContent += "Name: " + overviewPage.getName() + ", Filename: " + overviewPage.getFilename() + ", Version: 2.0, Content: ";
+ assertThat(overviewContent).as("Published overview page").isEqualTo(expectedContent);
// publish the modified page
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), page);
- page = t.getObject(Page.class, page.getId());
+ page = update(page, upd -> {}).at(4000).publish().build();
+
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
// change the expected content.
expectedContent = "Name: " + page.getName() + ", Filename: " + page.getFilename() + ", Version: 2.0, Content: Modified Content: Referenced Content ";
- expectedContent += "Name: " + overviewPage.getName() + ", Filename: " + overviewPage.getFilename() + ", Version: "
- + publishedOverviewVersion.getNumber() + ", Content: ";
+ expectedContent += "Name: " + overviewPage.getName() + ", Filename: " + overviewPage.getFilename() + ", Version: 2.0, Content: ";
// get the overview content
- overviewContent = getPublishedContent(OVERVIEW_PAGE_ID);
-
- assertEquals("Check the content of the overview page after modifying referenced page", expectedContent, overviewContent);
+ overviewContent = getPublishedContent(overviewPage.getId());
+ assertThat(overviewContent).as("Published overview page").isEqualTo(expectedContent);
}
/**
@@ -322,64 +370,57 @@ public void testReferencingModifiedPage() throws Exception {
*/
@Test
public void testMovePublishedPage() throws Exception {
- Transaction t = testContext.startTransactionWithPermissions(true);
-
- ContentNodeHelper.setLanguageId(1);
-
String name = "Publish Page Version";
String filename = "publish_page_version.html";
String content = "Name: , folder name: , Version: ";
- // create two folders
- Folder folder1 = t.createObject(Folder.class);
-
- folder1.setMotherId(VERSIONS_FOLDER_ID);
- folder1.setPublishDir("/");
- folder1.setName("Folder 1");
- folder1.save();
- Folder folder2 = t.createObject(Folder.class);
- folder2.setMotherId(VERSIONS_FOLDER_ID);
- folder2.setPublishDir("/");
- folder2.setName("Folder 2");
- folder2.save();
- t.commit(false);
+ // create two folders
+ Folder folder1 = create(Folder.class, create -> {
+ create.setMotherId(node.getFolder().getId());
+ create.setPublishDir("/");
+ create.setName("Folder 1");
+ }).build();
+
+ Folder folder2 = create(Folder.class, create -> {
+ create.setMotherId(node.getFolder().getId());
+ create.setPublishDir("/");
+ create.setName("Folder 2");
+ }).build();
// create a page and publish it
- Page page = createPage(VERSIONS_TEMPLATE_ID, ObjectTransformer.getInt(folder1.getId(), -1), name, filename, content);
-
- clearNodeObjectCache();
+ Page page = create(Page.class, p -> {
+ p.setName(name);
+ p.setFilename(filename);
+ p.setFolderId(folder1.getId());
+ p.setTemplateId(template.getId());
- // wait a sec
- waitMS(1500);
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(content);
+ }).at(1000).build();
- // publish the page
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), page);
-
- // wait a sec
- waitMS(1500);
+ page = update(page, p -> {}).at(2000).publish().build();
- // we need a new transaction here, because otherwise, we would not create another version of the page
- t = testContext.startTransactionWithPermissions(false);
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
// move page to another folder and remove the original folder
- page = t.getObject(Page.class, page.getId(), true);
- page.setFolderId(folder2.getId());
- page.setName("Modified " + page.getName());
- page.getContentTag(CONTENTTAG_NAME).getValues().getByKeyname(PART_NAME).setValueText("bla");
- page.save();
- folder1.delete();
- t.commit(false);
+ update(page, upd -> {
+ upd.setFolderId(folder2.getId());
+ upd.setName("Modified " + upd.getName());
+ getPartType(LongHTMLPartType.class, upd.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText("bla");
+ }).doNotPublish().build();
+
+ consume(Folder::delete, folder1);
// get the page content of the published version
- page = (Page) page.getPublishedObject();
- assertNotNull("Check whether the created page was found", page);
- assertTrue("Check whether a versioned page was fetched now", page.getObjectInfo().getVersionTimestamp() > 0);
- setRenderType(RenderType.EM_PREVIEW);
- RenderResult renderResult = new RenderResult();
- String pageContent = page.render(renderResult);
-
- assertEquals("Check the rendered page after moving", "Name: " + name + ", folder name: Folder 2, Version: 1.0", pageContent);
+ String expected = "Name: " + name + ", folder name: Folder 2, Version: 1.0";
+
+ try (Trx trx = new Trx(); RenderTypeTrx rTrx = RenderTypeTrx.publish()) {
+ assertThat(page.getPublishedObject().render()).as("Rendered page").isEqualTo(expected);
+ trx.success();
+ }
}
/**
@@ -389,53 +430,47 @@ public void testMovePublishedPage() throws Exception {
*/
@Test
public void testRemoveTag() throws Exception {
- Transaction t = testContext.startTransactionWithPermissions(true);
-
- ContentNodeHelper.setLanguageId(1);
-
String name = "Publish Page Version";
String filename = "publish_page_version.html";
- String content = "Outer Tag, here comes the inner:[]";
+ String content = "Outer Tag, here comes the inner:[]";
String innerContent = "This is the inner Tag";
- // create a page
- Page page = createPage(VERSIONS_TEMPLATE_ID, VERSIONS_FOLDER_ID, name, filename, content);
- // add an inner tag
- ContentTag outerTag = page.getContentTag(CONTENTTAG_NAME);
- ContentTag innerTag = page.getContent().addContentTag(ObjectTransformer.getInt(outerTag.getConstruct().getId(), -1));
+ AtomicReference innerTagName = new AtomicReference<>();
- innerTag.setName("innertag");
- innerTag.getValues().getByKeyname(PART_NAME).setValueText(innerContent);
- page.save();
- t.commit(false);
+ Page page = create(Page.class, p -> {
+ p.setName(name);
+ p.setFilename(filename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
- // publish the page
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), page);
+ ContentTag outerTag = p.getContentTag(TEMPLATE_TAG_NAME);
+ ContentTag innerTag = p.getContent().addContentTag(htmlConstructId);
- // wait a sec
- waitMS(1500);
+ getPartType(LongHTMLPartType.class, innerTag, HTML_PART_NAME).setText(innerContent);
+ getPartType(LongHTMLPartType.class, outerTag, HTML_PART_NAME).setText(content.formatted(innerTag.getName()));
+ innerTagName.set(innerTag.getName());
- // new transaction
- t = testContext.startTransactionWithPermissions(false);
+ }).at(1000).build();
- // now remove the inner tag
- page = t.getObject(Page.class, page.getId(), true);
- page.getContentTags().remove(innerTag.getName());
- page.save();
- t.commit(false);
+ // publish the page
+ page = update(page, p -> {}).at(2000).publish().build();
+
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
- // new transaction
- t = testContext.startTransactionWithPermissions(false);
+ page = update(page, upd -> {
+ upd.getContentTags().remove(innerTagName.get());
+ }).at(3000).doNotPublish().build();
// get the page content of the published version
- page = (Page) page.getPublishedObject();
- assertNotNull("Check whether the created page was found", page);
- assertTrue("Check whether a versioned page was fetched now", page.getObjectInfo().getVersionTimestamp() > 0);
- setRenderType(RenderType.EM_PREVIEW);
- RenderResult renderResult = new RenderResult();
- String pageContent = page.render(renderResult);
-
- assertEquals("Check the rendered page after removing tag", "Outer Tag, here comes the inner:[This is the inner Tag]", pageContent);
+ String expected = "Outer Tag, here comes the inner:[This is the inner Tag]";
+
+ try (Trx trx = new Trx(); RenderTypeTrx rTrx = RenderTypeTrx.publish()) {
+ assertThat(page.getPublishedObject().render()).as("Rendered page").isEqualTo(expected);
+ trx.success();
+ }
}
/**
@@ -445,49 +480,43 @@ public void testRemoveTag() throws Exception {
*/
@Test
public void testAddTag() throws Exception {
- Transaction t = testContext.startTransactionWithPermissions(true);
-
- ContentNodeHelper.setLanguageId(1);
-
String name = "Publish Page Version";
String filename = "publish_page_version.html";
String content = "Outer Tag, here comes the inner:[]";
String innerContent = "This is the inner Tag";
- // create a page
- Page page = createPage(VERSIONS_TEMPLATE_ID, VERSIONS_FOLDER_ID, name, filename, content);
-
- // publish the page
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), page);
+ Page page = create(Page.class, p -> {
+ p.setName(name);
+ p.setFilename(filename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
- // wait a sec
- waitMS(1500);
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(content);
- // new transaction
- t = testContext.startTransactionWithPermissions(false);
+ }).at(1000).build();
- // now add the inner tag
- page = t.getObject(Page.class, page.getId(), true);
- ContentTag outerTag = page.getContentTag(CONTENTTAG_NAME);
- ContentTag innerTag = page.getContent().addContentTag(ObjectTransformer.getInt(outerTag.getConstruct().getId(), -1));
+ // publish the page
+ page = update(page, p -> {}).at(2000).publish().build();
- innerTag.setName("innertag");
- innerTag.getValues().getByKeyname(PART_NAME).setValueText(innerContent);
- page.save();
- t.commit(false);
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
- // new transaction
- t = testContext.startTransactionWithPermissions(false);
+ // now add the inner tag
+ page = update(page, upd -> {
+ ContentTag innerTag = upd.getContent().addContentTag(htmlConstructId);
+ innerTag.setName("innertag");
+ getPartType(LongHTMLPartType.class, innerTag, HTML_PART_NAME).setText(innerContent);
+ }).at(2000).doNotPublish().build();
// get the page content of the published version
- page = (Page) page.getPublishedObject();
- assertNotNull("Check whether the created page was found", page);
- assertTrue("Check whether a versioned page was fetched now", page.getObjectInfo().getVersionTimestamp() > 0);
- setRenderType(RenderType.EM_PREVIEW);
- RenderResult renderResult = new RenderResult();
- String pageContent = page.render(renderResult);
-
- assertEquals("Check the rendered page after removing tag", "Outer Tag, here comes the inner:[]", pageContent);
+ String expected = "Outer Tag, here comes the inner:[]";
+
+ try (Trx trx = new Trx(); RenderTypeTrx rTrx = RenderTypeTrx.publish()) {
+ assertThat(page.getPublishedObject().render()).as("Rendered page").isEqualTo(expected);
+ trx.success();
+ }
}
/**
@@ -498,56 +527,52 @@ public void testAddTag() throws Exception {
*/
@Test
public void testChangeTemplate() throws Exception {
- Transaction t = testContext.startTransactionWithPermissions(true);
-
- ContentNodeHelper.setLanguageId(1);
-
String name = "Publish Page Version";
String filename = "publish_page_version.html";
String content = "";
- // create a copy of the template
- Template template = t.getObject(Template.class, VERSIONS_TEMPLATE_ID);
- Template newTemplate = (Template) template.copy();
-
- newTemplate.setName("This is the new template");
- newTemplate.save();
- t.commit(false);
+ Template newTemplate = execute(tmpl -> {
+ Template copy = (Template)tmpl.copy();
+ copy.setName("This is the new template");
+ copy.save();
+ return copy;
+ }, template);
+ int newTemplateId = newTemplate.getId();
// create a page
- Page page = createPage(ObjectTransformer.getInt(newTemplate.getId(), -1), VERSIONS_FOLDER_ID, name, filename, content);
+ Page page = create(Page.class, p -> {
+ p.setName(name);
+ p.setFilename(filename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(newTemplateId);
- // publish the page
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), page);
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(content);
- // wait a sec
- waitMS(1500);
+ }).at(1000).build();
- // new transaction
- t = testContext.startTransactionWithPermissions(false);
+ // publish the page
+ page = update(page, p -> {}).at(2000).publish().build();
+
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
// now change the template
- page = t.getObject(Page.class, page.getId(), true);
- page.setTemplateId(VERSIONS_TEMPLATE_ID);
- page.save();
- t.commit(false);
+ page = update(page, upd -> {
+ upd.setTemplateId(template.getId());
+ }).doNotPublish().build();
// remove the (unused) template
- newTemplate.delete();
- t.commit(false);
-
- // new transaction
- t = testContext.startTransactionWithPermissions(false);
+ consume(Template::delete, newTemplate);
// get the page content of the published version
- page = (Page) page.getPublishedObject();
- assertNotNull("Check whether the created page was found", page);
- assertTrue("Check whether a versioned page was fetched now", page.getObjectInfo().getVersionTimestamp() > 0);
- setRenderType(RenderType.EM_PREVIEW);
- RenderResult renderResult = new RenderResult();
- String pageContent = page.render(renderResult);
-
- assertEquals("Check the rendered page after removing tag", template.getName(), pageContent);
+ String expected = template.getName();
+
+ try (Trx trx = new Trx(); RenderTypeTrx rTrx = RenderTypeTrx.publish()) {
+ assertThat(page.getPublishedObject().render()).as("Rendered page").isEqualTo(expected);
+ trx.success();
+ }
}
/**
@@ -558,10 +583,6 @@ public void testChangeTemplate() throws Exception {
*/
@Test
public void testModifiedPageTag() throws Exception {
- Transaction t = testContext.startTransactionWithPermissions(true);
-
- ContentNodeHelper.setLanguageId(1);
-
String targetName = "Target Page";
String targetFilename = "target_page.html";
String targetContent = "Target Content";
@@ -570,120 +591,131 @@ public void testModifiedPageTag() throws Exception {
String sourceContent = "Here comes the page tag:[]";
// create the target page
- Page targetPage = createPage(VERSIONS_TEMPLATE_ID, VERSIONS_FOLDER_ID, targetName, targetFilename, targetContent);
+ Page targetPage = create(Page.class, p -> {
+ p.setName(targetName);
+ p.setFilename(targetFilename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(targetContent);
+ }).at(1000).build();
+ Page finalTargetPage = targetPage;
// create the source page
- Page sourcePage = createPage(VERSIONS_TEMPLATE_ID, VERSIONS_FOLDER_ID, sourceName, sourceFilename, sourceContent);
- // add the page tag
- ContentTag pageTagTag = sourcePage.getContent().addContentTag(PAGE_TAG_CONSTRUCT_ID);
-
- pageTagTag.setName("pagetag");
- pageTagTag.setEnabled(true);
- Value value = pageTagTag.getValues().iterator().next();
- PageTagPartType partType = (PageTagPartType) value.getPartType();
-
- partType.setPageTag(targetPage, targetPage.getContentTag(CONTENTTAG_NAME));
- sourcePage.save();
- t.commit(false);
+ Page sourcePage = create(Page.class, p -> {
+ p.setName(sourceName);
+ p.setFilename(sourceFilename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(sourceContent);
+
+ // add the page tag
+ ContentTag pagetagTag = p.getContent().addContentTag(pagetagConstructId);
+ pagetagTag.setName("pagetag");
+ getPartType(PageTagPartType.class, pagetagTag, PAGETAG_PART_NAME).setPageTag(finalTargetPage, finalTargetPage.getContentTag(TEMPLATE_TAG_NAME));
+ }).at(1000).build();
// publish the pages
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), sourcePage, targetPage);
+ sourcePage = update(sourcePage, p -> {}).at(2000).publish().build();
+ targetPage = update(targetPage, p -> {}).at(2000).publish().build();
- // check the correct source page content
- assertEquals("Check published source page content", "Here comes the page tag:[Target Content]",
- getPublishedContent(ObjectTransformer.getInt(sourcePage.getId(), -1)));
-
- // wait a sec
- waitMS(1500);
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
- // new transaction
- t = testContext.startTransactionWithPermissions(false);
+ // check the correct source page content
+ assertThat(getPublishedContent(sourcePage.getId())).as("Published source page")
+ .isEqualTo("Here comes the page tag:[Target Content]");
// now modify the content of the target tag
- targetPage = t.getObject(Page.class, targetPage.getId(), true);
- targetPage.getContentTag(CONTENTTAG_NAME).getValues().getByKeyname(PART_NAME).setValueText("Modified Target Page");
- targetPage.save();
- t.commit(false);
+ update(targetPage, upd -> {
+ getPartType(LongHTMLPartType.class, upd.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText("Modified Target Page");
+ }).at(3000).doNotPublish().build();
// also modify the source page (to make sure it is really re-rendered in publish process)
- sourcePage = t.getObject(Page.class, sourcePage.getId(), true);
- sourcePage.getContentTag(CONTENTTAG_NAME).getValues().getByKeyname(PART_NAME).setValueText("Here still comes the page tag:[]");
- sourcePage.save();
- t.commit(false);
+ update(sourcePage, upd -> {
+ getPartType(LongHTMLPartType.class, upd.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText("Here still comes the page tag:[]");
+ }).at(3000).publish().build();
- // publish the source page again
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), sourcePage);
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
// check the correct source page content after republishing
- assertEquals("Check republished source page content", "Here still comes the page tag:[Target Content]",
- getPublishedContent(ObjectTransformer.getInt(sourcePage.getId(), -1)));
+ assertThat(getPublishedContent(sourcePage.getId())).as("Published source page")
+ .isEqualTo("Here still comes the page tag:[Target Content]");
}
/**
- * Test republish a page rendering another page (that was modified but not republished) in velocity
+ * Test republish a page rendering another page (that was modified but not republished) in handlebars
*
* @throws Exception
*/
@Test
- public void testModifiedVelocityPage() throws Exception {
- Transaction t = testContext.startTransactionWithPermissions(true);
-
- ContentNodeHelper.setLanguageId(1);
-
+ public void testModifiedHandlebarsPage() throws Exception {
String targetName = "Target Page";
String targetFilename = "target_page.html";
String targetContent = "Target Content";
String sourceName = "Source Page";
String sourceFilename = "source_page.html";
- String sourceContent = "Here comes the vtl tag:[]";
+ String sourceContent = "Here comes the hbs tag:[]";
// create the target page
- Page targetPage = createPage(VERSIONS_TEMPLATE_ID, VERSIONS_FOLDER_ID, targetName, targetFilename, targetContent);
+ Page targetPage = create(Page.class, p -> {
+ p.setName(targetName);
+ p.setFilename(targetFilename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(targetContent);
+ }).at(1000).build();
+ Page finalTargetPage = targetPage;
// create the source page
- Page sourcePage = createPage(VERSIONS_TEMPLATE_ID, VERSIONS_FOLDER_ID, sourceName, sourceFilename, sourceContent);
- // add the vtl tag
- ContentTag pageTagTag = sourcePage.getContent().addContentTag(VELOCITY_CONSTRUCT_ID);
-
- pageTagTag.setName("vtl");
- pageTagTag.setEnabled(true);
- Value value = pageTagTag.getValues().getByKeyname("template");
-
- value.setValueText("#set($page = $cms.imps.loader.getPage(" + targetPage.getId() + "))$page");
- sourcePage.save();
- t.commit(false);
+ Page sourcePage = create(Page.class, p -> {
+ p.setName(sourceName);
+ p.setFilename(sourceFilename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(sourceContent);
+
+ // add the hbs tag
+ ContentTag hbsTag = p.getContent().addContentTag(hbsConstructId);
+ hbsTag.setName("hbs");
+ getPartType(HandlebarsPartType.class, hbsTag, HBS_PART_NAME).setText("{{#with (gtx_test_page %d)}}{{gtx_render this}}{{/with}}".formatted(finalTargetPage.getId()));
+ }).at(1000).build();
// publish the pages
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), sourcePage, targetPage);
+ sourcePage = update(sourcePage, p -> {}).at(2000).publish().build();
+ targetPage = update(targetPage, p -> {}).at(2000).publish().build();
- // check the correct source page content
- assertEquals("Check published source page content", "Here comes the vtl tag:[Target Content]",
- getPublishedContent(ObjectTransformer.getInt(sourcePage.getId(), -1)));
-
- // wait a sec
- waitMS(1500);
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
- // new transaction
- t = testContext.startTransactionWithPermissions(false);
+ // check the correct source page content
+ assertThat(getPublishedContent(sourcePage.getId())).as("Published source page")
+ .isEqualTo("Here comes the hbs tag:[Target Content]");
// now modify the content of the target tag
- targetPage = t.getObject(Page.class, targetPage.getId(), true);
- targetPage.getContentTag(CONTENTTAG_NAME).getValues().getByKeyname(PART_NAME).setValueText("Modified Target Page");
- targetPage.save();
- t.commit(false);
+ targetPage = update(targetPage, upd -> {
+ getPartType(LongHTMLPartType.class, upd.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText("Modified Target Page");
+ }).at(3000).doNotPublish().build();
// also modify the source page (to make sure it is really re-rendered in publish process)
- sourcePage = t.getObject(Page.class, sourcePage.getId(), true);
- sourcePage.getContentTag(CONTENTTAG_NAME).getValues().getByKeyname(PART_NAME).setValueText("Here still comes the vtl tag:[]");
- sourcePage.save();
- t.commit(false);
+ sourcePage = update(sourcePage, upd -> {
+ getPartType(LongHTMLPartType.class, upd.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText("Here still comes the hbs tag:[]");
+ }).at(3000).publish().build();
- // publish the source page again
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), sourcePage);
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
// check the correct source page content after republishing
- assertEquals("Check republished source page content", "Here still comes the vtl tag:[Target Content]",
- getPublishedContent(ObjectTransformer.getInt(sourcePage.getId(), -1)));
+ assertThat(getPublishedContent(sourcePage.getId())).as("Published source page")
+ .isEqualTo("Here still comes the hbs tag:[Target Content]");
}
/**
@@ -695,10 +727,6 @@ public void testModifiedVelocityPage() throws Exception {
*/
@Test
public void testModifiedPageVariant() throws Exception {
- Transaction t = testContext.startTransactionWithPermissions(true);
-
- ContentNodeHelper.setLanguageId(1);
-
String firstName = "First Page Variant";
String firstFilename = "first.html";
String secondName = "Second Page Variant";
@@ -706,65 +734,62 @@ public void testModifiedPageVariant() throws Exception {
String sharedContent = "This is the shared content";
// create the first page
- Page firstPage = createPage(VERSIONS_TEMPLATE_ID, VERSIONS_FOLDER_ID, firstName, firstFilename, sharedContent);
+ Page firstPage = create(Page.class, p -> {
+ p.setName(firstName);
+ p.setFilename(firstFilename);
+ p.setFolderId(node.getFolder().getId());
+ p.setTemplateId(template.getId());
+ getPartType(LongHTMLPartType.class, p.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText(sharedContent);
+ }).at(1000).build();
// create a page variant
- Page secondPage = firstPage.createVariant();
-
- secondPage.setName(secondName);
- secondPage.setFilename(secondFilename);
- secondPage.save();
- t.commit(false);
-
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), firstPage, secondPage);
+ Page secondPage = execute(p -> {
+ TransactionManager.getCurrentTransaction().setTimestamp(1000 * 1000);
+ Page variant = p.createVariant();
+ variant.setName(secondName);
+ variant.setFilename(secondFilename);
+ variant.save();
+ return variant;
+ }, firstPage);
- // wait a sec
- Thread.sleep(1500);
+ // publish the pages
+ firstPage = update(firstPage, p -> {}).at(2000).publish().build();
+ secondPage = update(secondPage, p -> {}).at(2000).publish().build();
- // new transaction
- t = testContext.startTransactionWithPermissions(false);
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
// now modify the first page, but do not publish it
- firstPage = t.getObject(Page.class, firstPage.getId(), true);
- firstPage.getContentTag(CONTENTTAG_NAME).getValues().getByKeyname(PART_NAME).setValueText("Modified shared content");
- firstPage.save();
- t.commit(false);
-
- // modify the template to dirt the pages
- Template template = t.getObject(Template.class, VERSIONS_TEMPLATE_ID, true);
-
- template.setSource(template.getSource() + " - modified");
- template.save();
- t.commit(false);
-
- // wait a sec
- Thread.sleep(1500);
-
- // republish, after dirts are done
- testContext.waitForDirtqueueWorker();
- testContext.publish(false);
-
- // wait a sec
- Thread.sleep(1500);
-
- // new transaction
- t = testContext.startTransactionWithPermissions(false);
-
- String firstPageContent = getPublishedContent(ObjectTransformer.getInt(firstPage.getId(), -1));
-
- assertEquals("Check published content of first page", "This is the shared content - modified", firstPageContent);
- String secondPageContent = getPublishedContent(ObjectTransformer.getInt(secondPage.getId(), -1));
+ firstPage = update(firstPage, upd -> {
+ getPartType(LongHTMLPartType.class, upd.getContentTag(TEMPLATE_TAG_NAME), HTML_PART_NAME).setText("Modified shared content");
+ }).at(3000).doNotPublish().build();
+
+ // change template to have the pages republished
+ template = update(template, upd -> {
+ upd.setSource(upd.getSource() + " - modified");
+ }).build();
+
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
- assertEquals("Check published content of second page", "This is the shared content - modified", secondPageContent);
+ assertThat(getPublishedContent(firstPage.getId())).as("Published content of first page").isEqualTo("This is the shared content - modified");
+ assertThat(getPublishedContent(secondPage.getId())).as("Published content of second page").isEqualTo("This is the shared content - modified");
// now publish the first page
- publishPage(testContext.getContext(), testContext.getDBSQLUtils(), firstPage);
+ firstPage = update(firstPage, upd -> {
+ }).at(4000).publish().build();
+
+ try (Trx trx = new Trx()) {
+ testContext.publish(false);
+ trx.success();
+ }
- // and check the published contents again
- firstPageContent = getPublishedContent(ObjectTransformer.getInt(firstPage.getId(), -1));
- assertEquals("Check published content of first page", "Modified shared content - modified", firstPageContent);
- secondPageContent = getPublishedContent(ObjectTransformer.getInt(secondPage.getId(), -1));
- assertEquals("Check published content of second page", "Modified shared content - modified", secondPageContent);
+ assertThat(getPublishedContent(firstPage.getId())).as("Published content of first page").isEqualTo("Modified shared content - modified");
+ assertThat(getPublishedContent(secondPage.getId())).as("Published content of second page").isEqualTo("Modified shared content - modified");
}
/**
@@ -775,14 +800,16 @@ public void testModifiedPageVariant() throws Exception {
* @return content of the published page
* @throws Exception
*/
- public String getPublishedContent(int pageId) throws Exception {
- ResultSet publish = testContext.getDBSQLUtils().executeQuery("SELECT source FROM publish WHERE page_id = " + pageId + " AND active = 1");
-
- if (publish.next()) {
- return publish.getString("source");
- } else {
- fail("Did not find published overview page");
- return null;
+ public String getPublishedContent(int pageId) throws NodeException {
+ String publishedContent = supply(() -> {
+ return DBUtils.select("SELECT source FROM publish WHERE page_id = ? AND active = 1", pst -> {
+ pst.setInt(1, pageId);
+ }, DBUtils.firstString("source"));
+ });
+
+ if (publishedContent == null) {
+ fail("Did not find published page content");
}
+ return publishedContent;
}
}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/testutils/LoaderHelperSource.java b/cms-core/src/test/java/com/gentics/contentnode/testutils/LoaderHelperSource.java
new file mode 100644
index 0000000000..9a35603fa8
--- /dev/null
+++ b/cms-core/src/test/java/com/gentics/contentnode/testutils/LoaderHelperSource.java
@@ -0,0 +1,68 @@
+package com.gentics.contentnode.testutils;
+
+import com.gentics.api.lib.exception.NodeException;
+import com.gentics.contentnode.factory.Transaction;
+import com.gentics.contentnode.factory.TransactionManager;
+import com.gentics.contentnode.object.File;
+import com.gentics.contentnode.object.Folder;
+import com.gentics.contentnode.object.NodeObject;
+import com.gentics.contentnode.object.Page;
+import com.gentics.contentnode.resolving.ResolvableMapWrappable;
+import com.gentics.contentnode.resolving.ResolvableMapWrapper;
+import com.github.jknack.handlebars.helper.HelperFunction;
+
+/**
+ * Helper Source for some loader helpers
+ */
+public class LoaderHelperSource {
+ /**
+ * Load a folder with given id
+ * @param id folder id
+ * @return folder
+ * @throws NodeException
+ */
+ @HelperFunction("gtx_test_folder")
+ public static Object getFolder(int id) throws NodeException {
+ Transaction t = TransactionManager.getCurrentTransaction();
+ return wrap(t.getObject(Folder.class, id));
+ }
+
+ /**
+ * Load a page with given id
+ * @param id page id
+ * @return page
+ * @throws NodeException
+ */
+ @HelperFunction("gtx_test_page")
+ public static Object getPage(int id) throws NodeException {
+ Transaction t = TransactionManager.getCurrentTransaction();
+ return wrap(t.getObject(Page.class, id));
+ }
+
+ /**
+ * Load a file with given id
+ * @param id file id
+ * @return file
+ * @throws NodeException
+ */
+ @HelperFunction("gtx_test_file")
+ public static Object getFile(int id) throws NodeException {
+ Transaction t = TransactionManager.getCurrentTransaction();
+ return wrap(t.getObject(File.class, id));
+ }
+
+ /**
+ * Wrap the returned object
+ * @param object object to be wrapped
+ * @return wrapped object
+ */
+ protected static Object wrap(NodeObject object) {
+ if (object == null) {
+ return null;
+ } else if (object instanceof ResolvableMapWrappable wrappable) {
+ return new ResolvableMapWrapper(wrappable);
+ } else {
+ return object;
+ }
+ }
+}
diff --git a/cms-core/src/test/java/com/gentics/contentnode/testutils/TestHelpersHandlebarsService.java b/cms-core/src/test/java/com/gentics/contentnode/testutils/TestHelpersHandlebarsService.java
new file mode 100644
index 0000000000..50dfcd7c16
--- /dev/null
+++ b/cms-core/src/test/java/com/gentics/contentnode/testutils/TestHelpersHandlebarsService.java
@@ -0,0 +1,35 @@
+package com.gentics.contentnode.testutils;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.gentics.contentnode.render.HandlebarsService;
+import com.github.jknack.handlebars.Handlebars;
+
+/**
+ * Implementation of {@link HandlebarsService} which will register the helpers via the helper source classes given by {@link #addHelper(Class)}
+ */
+public class TestHelpersHandlebarsService implements HandlebarsService {
+ protected static Set> helperSources = new HashSet<>();
+
+ /**
+ * Add the given class as helper source
+ * @param helperSource helper source class
+ */
+ public static void addHelper(Class> helperSource) {
+ helperSources.add(helperSource);
+ }
+
+ /**
+ * Remove the class from the helper sources
+ * @param helperSource helper source class
+ */
+ public static void removeHelper(Class> helperSource) {
+ helperSources.remove(helperSource);
+ }
+
+ @Override
+ public void registerHelpers(Handlebars handlebars) {
+ helperSources.forEach(handlebars::registerHelpers);
+ }
+}
diff --git a/cms-core/src/test/resources/META-INF/services/com.gentics.contentnode.render.HandlebarsService b/cms-core/src/test/resources/META-INF/services/com.gentics.contentnode.render.HandlebarsService
new file mode 100644
index 0000000000..9166ec6214
--- /dev/null
+++ b/cms-core/src/test/resources/META-INF/services/com.gentics.contentnode.render.HandlebarsService
@@ -0,0 +1 @@
+com.gentics.contentnode.testutils.TestHelpersHandlebarsService
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/dirting/languageset.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/dirting/languageset.vm
deleted file mode 100644
index bde188ca07..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/dirting/languageset.vm
+++ /dev/null
@@ -1,3 +0,0 @@
-#foreach($page in $cms.page.languageset.pages)
-#if($page.online)$page.id ($page.name)#end
-#end
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/overview/page_props.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/overview/page_props.vm
deleted file mode 100644
index 62e0a29357..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/overview/page_props.vm
+++ /dev/null
@@ -1,48 +0,0 @@
-#foreach($page in $cms.tag.parts.ds.items)##
-id: $page.id
-url: $page.url
-template.id: $page.template.id
-name: $page.name
-filename: $page.filename
-description: $page.description
-priority: $page.priority
-publishtimestamp: $page.publishtimestamp
-publishdate: $page.publishdate
-creationtimestamp: $page.creationtimestamp
-creationdate: $page.creationdate
-edittimestamp: $page.edittimestamp
-editdate: $page.editdate
-folder: $page.folder.name
-folder.isfolder: $page.folder.isfolder
-creator: $page.creator
-editor: $page.editor
-publisher: $page.publisher
-language: $page.language.code
-languageset.id $page.languageset.id
-online: $page.online
-ispage: $page.ispage
-isfolder: $page.isfolder
-isfile: $page.isfile
-isimage: $page.isimage
-istag: $page.istag
-version.number: $page.version.number
-version.date: $page.version.date
-version.editor: $page.version.editor
-version.major: $page.version.major
-ismaster: $page.ismaster
-inherited: $page.inherited
-template.id: $page.template.id
-template.name: $page.template.name
-template.ml.name: $page.template.ml.name
-template.ml.extension: $page.template.ml.extension
-template.ml.contenttype: $page.template.ml.contenttype
-ttype: $page.ttype
-versions:
-#foreach($v in $page.versions)##
- $v.number
-#end##
-pagevariants:
-#foreach($v in $page.pagevariants)##
- $v.id
-#end##
-#end##
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/overview/tags.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/overview/tags.vm
deleted file mode 100644
index 23262c4131..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/overview/tags.vm
+++ /dev/null
@@ -1,15 +0,0 @@
-#foreach($page in $cms.tag.parts.ds.items)##
-#foreach($tag in $page.tags)##
-id:$tag.id
- tag.id:$tag.tag.id
- name:$tag.name
- visible:$tag.visible
- empty:$tag.empty
- istag:$tag.istag
- rendered:[$tag]
- parts:
-#foreach($part in $tag.parts)##
- rendered:[$part]
-#end##
-#end##
-#end##
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/language_variants.hbs b/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/language_variants.hbs
new file mode 100644
index 0000000000..eb2eecf5d0
--- /dev/null
+++ b/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/language_variants.hbs
@@ -0,0 +1,6 @@
+{{#each (gtx_sort cms.page.languageset.pages "language.code")}}
+id: {{id}}
+ name: {{name}}
+ language: {{language.code}}
+ online: {{online}}
+{{/each}}
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/language_variants.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/language_variants.vm
deleted file mode 100644
index c5412f148c..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/language_variants.vm
+++ /dev/null
@@ -1,6 +0,0 @@
-#foreach($item in $cms.imps.sorter.sort($cms.page.languageset.pages, "language.code:asc"))##
-id: $item.id
- name: $item.name
- language: $item.language.code
- online: $item.online
-#end##
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/page_props.hbs b/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/page_props.hbs
new file mode 100644
index 0000000000..8396f9d2fc
--- /dev/null
+++ b/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/page_props.hbs
@@ -0,0 +1,41 @@
+id: {{cms.page.id}}
+url: {{cms.page.url}}
+template.id: {{cms.page.template.id}}
+name: {{cms.page.name}}
+filename: {{cms.page.filename}}
+description: {{cms.page.description}}
+priority: {{cms.page.priority}}
+publishtimestamp: {{cms.page.publishtimestamp}}
+publishdate: {{cms.page.publishdate}}
+creationtimestamp: {{cms.page.creationtimestamp}}
+creationdate: {{cms.page.creationdate}}
+edittimestamp: {{cms.page.edittimestamp}}
+editdate: {{cms.page.editdate}}
+folder: {{cms.page.folder.name}}
+folder.isfolder: {{cms.page.folder.isfolder}}
+creator: {{cms.page.creator}}
+editor: {{cms.page.editor}}
+publisher: {{cms.page.publisher}}
+language: {{cms.page.language.code}}
+languageset.id {{cms.page.languageset.id}}
+online: {{cms.page.online}}
+ispage: {{cms.page.ispage}}
+isfolder: {{cms.page.isfolder}}
+isfile: {{cms.page.isfile}}
+isimage: {{cms.page.isimage}}
+istag: {{cms.page.istag}}
+version.number: {{cms.page.version.number}}
+version.date: {{cms.page.version.date}}
+version.editor: {{cms.page.version.editor}}
+version.major: {{cms.page.version.major}}
+ismaster: {{cms.page.ismaster}}
+inherited: {{cms.page.inherited}}
+ttype: {{cms.page.ttype}}
+versions:
+{{#each cms.page.versions}}
+ {{number}}
+{{/each}}
+pagevariants:
+{{#each cms.page.pagevariants}}
+ {{id}}
+{{/each}}
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/page_props.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/page_props.vm
deleted file mode 100644
index 9d84a4240b..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/page_props.vm
+++ /dev/null
@@ -1,41 +0,0 @@
-id: $cms.page.id
-url: $cms.page.url
-template.id: $cms.page.template.id
-name: $cms.page.name
-filename: $cms.page.filename
-description: $cms.page.description
-priority: $cms.page.priority
-publishtimestamp: $cms.page.publishtimestamp
-publishdate: $cms.page.publishdate
-creationtimestamp: $cms.page.creationtimestamp
-creationdate: $cms.page.creationdate
-edittimestamp: $cms.page.edittimestamp
-editdate: $cms.page.editdate
-folder: $cms.page.folder.name
-folder.isfolder: $cms.page.folder.isfolder
-creator: $cms.page.creator
-editor: $cms.page.editor
-publisher: $cms.page.publisher
-language: $cms.page.language.code
-languageset.id $cms.page.languageset.id
-online: $cms.page.online
-ispage: $cms.page.ispage
-isfolder: $cms.page.isfolder
-isfile: $cms.page.isfile
-isimage: $cms.page.isimage
-istag: $cms.page.istag
-version.number: $cms.page.version.number
-version.date: $cms.page.version.date
-version.editor: $cms.page.version.editor
-version.major: $cms.page.version.major
-ismaster: $cms.page.ismaster
-inherited: $cms.page.inherited
-ttype: $cms.page.ttype
-versions:
-#foreach($v in $cms.page.versions)
- $v.number
-#end
-pagevariants:
-#foreach($v in $cms.page.pagevariants)
- $v.id
-#end
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/tags.hbs b/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/tags.hbs
new file mode 100644
index 0000000000..1362bfac6d
--- /dev/null
+++ b/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/tags.hbs
@@ -0,0 +1,12 @@
+{{#each cms.page.tags}}
+id:{{id}}
+ tag.id:{{tag.id}}
+ name:{{name}}
+ visible:{{visible}}
+ empty:{{empty}}
+ istag:{{istag}}
+ parts:
+{{#each parts}}
+ {{gtx_render this}}
+{{/each}}
+{{/each}}
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/tags.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/tags.vm
deleted file mode 100644
index 8a13fd70c6..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/publish/wrapper/tags.vm
+++ /dev/null
@@ -1,12 +0,0 @@
-#foreach($tag in $cms.page.tags)##
-id:$tag.id
- tag.id:$tag.tag.id
- name:$tag.name
- visible:$tag.visible
- empty:$tag.empty
- istag:$tag.istag
- parts:
-#foreach($part in $tag.parts)##
- $part
-#end##
-#end##
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/Cat_silhouette.svg b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/Cat_silhouette.svg
deleted file mode 100644
index 683c84249e..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/Cat_silhouette.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_edit_name.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_edit_name.vm
deleted file mode 100644
index 1e3729e4e6..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_edit_name.vm
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_edit_ref.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_edit_ref.vm
deleted file mode 100644
index 1e3729e4e6..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_edit_ref.vm
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_render_name.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_render_name.vm
deleted file mode 100644
index ca9de35c1a..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_render_name.vm
+++ /dev/null
@@ -1 +0,0 @@
-$cms.page.tags.testtag
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_render_ref.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_render_ref.vm
deleted file mode 100644
index ca9de35c1a..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/compare_gtx_render_ref.vm
+++ /dev/null
@@ -1 +0,0 @@
-$cms.page.tags.testtag
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha.txt
deleted file mode 100644
index 78acfe1fc3..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha_readonly.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha_readonly.txt
deleted file mode 100644
index 68e998bcad..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha_readonly.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha_readonly_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha_readonly_svg.txt
deleted file mode 100644
index 68e998bcad..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha_readonly_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha_svg.txt
deleted file mode 100644
index 78acfe1fc3..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_aloha_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_preview.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_preview.txt
deleted file mode 100644
index 2f76e817c3..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_preview.txt
+++ /dev/null
@@ -1 +0,0 @@
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_preview_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_preview_svg.txt
deleted file mode 100644
index 2f76e817c3..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_preview_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish.txt
deleted file mode 100644
index 1745f6c584..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/auto/prop/nowhere/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish_seg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish_seg.txt
deleted file mode 100644
index 1f49329857..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish_seg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/auto/prop/nowhere/mother/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish_seg_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish_seg_svg.txt
deleted file mode 100644
index 1f49329857..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish_seg_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/auto/prop/nowhere/mother/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish_svg.txt
deleted file mode 100644
index 1745f6c584..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_0_publish_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/auto/prop/nowhere/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha.txt
deleted file mode 100644
index a9471755fa..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha_readonly.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha_readonly.txt
deleted file mode 100644
index f8d2d9d305..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha_readonly.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha_readonly_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha_readonly_svg.txt
deleted file mode 100644
index f8d2d9d305..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha_readonly_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha_svg.txt
deleted file mode 100644
index a9471755fa..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_aloha_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_preview.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_preview.txt
deleted file mode 100644
index e368442555..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_preview.txt
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_preview_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_preview_svg.txt
deleted file mode 100644
index e368442555..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_preview_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish.txt
deleted file mode 100644
index 3ad46c498e..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish.txt
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish_seg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish_seg.txt
deleted file mode 100644
index 0f3e79b618..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish_seg.txt
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish_seg_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish_seg_svg.txt
deleted file mode 100644
index 0f3e79b618..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish_seg_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish_svg.txt
deleted file mode 100644
index 3ad46c498e..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_1_publish_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha.txt
deleted file mode 100644
index 78acfe1fc3..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha_readonly.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha_readonly.txt
deleted file mode 100644
index 68e998bcad..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha_readonly.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha_readonly_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha_readonly_svg.txt
deleted file mode 100644
index 68e998bcad..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha_readonly_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha_svg.txt
deleted file mode 100644
index 78acfe1fc3..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_aloha_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_preview.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_preview.txt
deleted file mode 100644
index 2f76e817c3..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_preview.txt
+++ /dev/null
@@ -1 +0,0 @@
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_preview_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_preview_svg.txt
deleted file mode 100644
index 2f76e817c3..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_preview_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-/GenticsImageStore/100/auto/prop/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish.txt
deleted file mode 100644
index 48c0e55d4c..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish.txt
+++ /dev/null
@@ -1 +0,0 @@
-widget('genticsimagestore.widgets.GenticsImageStoreWidget', array('id' => #IMAGEID#, 'publishPath' => "/nowhere/bla/#IMAGENAME#", 'resizeOptions' => array('width' => 100, 'height' => "auto", 'mode' => "prop"))); ?>
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish_seg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish_seg.txt
deleted file mode 100644
index e889aad68c..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish_seg.txt
+++ /dev/null
@@ -1 +0,0 @@
-widget('genticsimagestore.widgets.GenticsImageStoreWidget', array('id' => #IMAGEID#, 'publishPath' => "/nowhere/mother/bla/#IMAGENAME#", 'resizeOptions' => array('width' => 100, 'height' => "auto", 'mode' => "prop"))); ?>
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish_seg_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish_seg_svg.txt
deleted file mode 100644
index e889aad68c..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish_seg_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-widget('genticsimagestore.widgets.GenticsImageStoreWidget', array('id' => #IMAGEID#, 'publishPath' => "/nowhere/mother/bla/#IMAGENAME#", 'resizeOptions' => array('width' => 100, 'height' => "auto", 'mode' => "prop"))); ?>
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish_svg.txt
deleted file mode 100644
index 48c0e55d4c..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_2_publish_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-widget('genticsimagestore.widgets.GenticsImageStoreWidget', array('id' => #IMAGEID#, 'publishPath' => "/nowhere/bla/#IMAGENAME#", 'resizeOptions' => array('width' => 100, 'height' => "auto", 'mode' => "prop"))); ?>
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha.txt
deleted file mode 100644
index a9471755fa..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha_readonly.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha_readonly.txt
deleted file mode 100644
index f8d2d9d305..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha_readonly.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha_readonly_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha_readonly_svg.txt
deleted file mode 100644
index f8d2d9d305..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha_readonly_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha_svg.txt
deleted file mode 100644
index a9471755fa..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_aloha_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_preview.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_preview.txt
deleted file mode 100644
index e368442555..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_preview.txt
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_preview_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_preview_svg.txt
deleted file mode 100644
index e368442555..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_preview_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish.txt
deleted file mode 100644
index e00e2e764b..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish.txt
+++ /dev/null
@@ -1 +0,0 @@
- #IMAGEID#, 'publishPath' => "/nowhere/bla/#IMAGENAME#", 'resizeOptions' => array('width' => "auto", 'height' => 50, 'mode' => "smart"), 'cropOptions' => array('x' => 10, 'y' => 15, 'width' => 30, 'height' => 35))); ?>'>
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish_seg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish_seg.txt
deleted file mode 100644
index 60c1ceaea1..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish_seg.txt
+++ /dev/null
@@ -1 +0,0 @@
- #IMAGEID#, 'publishPath' => "/nowhere/mother/bla/#IMAGENAME#", 'resizeOptions' => array('width' => "auto", 'height' => 50, 'mode' => "smart"), 'cropOptions' => array('x' => 10, 'y' => 15, 'width' => 30, 'height' => 35))); ?>'>
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish_seg_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish_seg_svg.txt
deleted file mode 100644
index 60c1ceaea1..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish_seg_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
- #IMAGEID#, 'publishPath' => "/nowhere/mother/bla/#IMAGENAME#", 'resizeOptions' => array('width' => "auto", 'height' => 50, 'mode' => "smart"), 'cropOptions' => array('x' => 10, 'y' => 15, 'width' => 30, 'height' => 35))); ?>'>
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish_svg.txt
deleted file mode 100644
index e00e2e764b..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_3_publish_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
- #IMAGEID#, 'publishPath' => "/nowhere/bla/#IMAGENAME#", 'resizeOptions' => array('width' => "auto", 'height' => 50, 'mode' => "smart"), 'cropOptions' => array('x' => 10, 'y' => 15, 'width' => 30, 'height' => 35))); ?>'>
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha.txt
deleted file mode 100644
index c30b7a1ba7..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/80/80/force/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha_readonly.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha_readonly.txt
deleted file mode 100644
index 8119d26a0c..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha_readonly.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/80/80/force/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha_readonly_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha_readonly_svg.txt
deleted file mode 100644
index 8119d26a0c..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha_readonly_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/80/80/force/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha_svg.txt
deleted file mode 100644
index c30b7a1ba7..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_aloha_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/80/80/force/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_preview.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_preview.txt
deleted file mode 100644
index 3918ef4de1..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_preview.txt
+++ /dev/null
@@ -1 +0,0 @@
-/GenticsImageStore/80/80/force/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_preview_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_preview_svg.txt
deleted file mode 100644
index 3918ef4de1..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_preview_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-/GenticsImageStore/80/80/force/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish.txt
deleted file mode 100644
index 8f826f63ad..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/80/80/force/nowhere/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish_seg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish_seg.txt
deleted file mode 100644
index 12c45a1317..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish_seg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/80/80/force/nowhere/mother/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish_seg_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish_seg_svg.txt
deleted file mode 100644
index 12c45a1317..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish_seg_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/80/80/force/nowhere/mother/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish_svg.txt
deleted file mode 100644
index 8f826f63ad..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_4_publish_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/80/80/force/nowhere/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha.txt
deleted file mode 100644
index 36c7ba7df5..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/100/cropandresize/smart/0/108/1160/1160/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha_readonly.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha_readonly.txt
deleted file mode 100644
index 7220bc77a1..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha_readonly.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/100/cropandresize/smart/0/108/1160/1160/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha_readonly_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha_readonly_svg.txt
deleted file mode 100644
index 140143920c..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha_readonly_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/100/smart/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha_svg.txt
deleted file mode 100644
index 004d7627c4..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_aloha_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/100/smart/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_preview.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_preview.txt
deleted file mode 100644
index d22f72c675..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_preview.txt
+++ /dev/null
@@ -1 +0,0 @@
-/GenticsImageStore/100/100/cropandresize/smart/0/108/1160/1160/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_preview_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_preview_svg.txt
deleted file mode 100644
index e71fd44e55..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_preview_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-/GenticsImageStore/100/100/smart/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish.txt
deleted file mode 100644
index 347a8b62e2..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/100/cropandresize/smart/0/108/1160/1160/nowhere/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish_seg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish_seg.txt
deleted file mode 100644
index c6c1fdbadc..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish_seg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/100/cropandresize/smart/0/108/1160/1160/nowhere/mother/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish_seg_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish_seg_svg.txt
deleted file mode 100644
index 163930a88c..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish_seg_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/100/smart/nowhere/mother/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish_svg.txt
deleted file mode 100644
index 85433e619e..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_5_publish_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/100/smart/nowhere/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha.txt
deleted file mode 100644
index ebd665e8b4..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/1000/cropandresize/smart/512/0/137/1376/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha_readonly.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha_readonly.txt
deleted file mode 100644
index 4f2dcbe56e..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha_readonly.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/1000/cropandresize/smart/512/0/137/1376/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha_readonly_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha_readonly_svg.txt
deleted file mode 100644
index e28c786038..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha_readonly_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/1000/smart/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha_svg.txt
deleted file mode 100644
index 19b966b0a1..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_aloha_svg.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-/GenticsImageStore/100/1000/smart/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_preview.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_preview.txt
deleted file mode 100644
index 7fd570b9cc..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_preview.txt
+++ /dev/null
@@ -1 +0,0 @@
-/GenticsImageStore/100/1000/cropandresize/smart/512/0/137/1376/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_preview_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_preview_svg.txt
deleted file mode 100644
index 0b8f59d53f..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_preview_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-/GenticsImageStore/100/1000/smart/rest/file/content/load/#IMAGEID#?sid=1&nodeId=#NODEID#&fingerprint=#IMAGEMD5#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish.txt
deleted file mode 100644
index abd7f66370..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/1000/cropandresize/smart/512/0/137/1376/nowhere/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish_seg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish_seg.txt
deleted file mode 100644
index 1abb43fae0..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish_seg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/1000/cropandresize/smart/512/0/137/1376/nowhere/mother/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish_seg_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish_seg_svg.txt
deleted file mode 100644
index 335d24cbff..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish_seg_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/1000/smart/nowhere/mother/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish_svg.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish_svg.txt
deleted file mode 100644
index 0223b7e659..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gis_6_publish_svg.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://dummyHost/GenticsImageStore/100/1000/smart/nowhere/bla/#IMAGENAME#
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx-vtl-macro-lib.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx-vtl-macro-lib.vm
deleted file mode 100644
index 13e7f31a5f..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx-vtl-macro-lib.vm
+++ /dev/null
@@ -1,3 +0,0 @@
-#macro( hello )
-Hello World!##
-#end
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_edit_name.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_edit_name.vm
deleted file mode 100644
index 79feaf0f5e..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_edit_name.vm
+++ /dev/null
@@ -1 +0,0 @@
-#gtx_edit("testtag")
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_edit_ref.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_edit_ref.vm
deleted file mode 100644
index d1f851a9e9..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_edit_ref.vm
+++ /dev/null
@@ -1 +0,0 @@
-#gtx_edit($cms.page.tags.testtag)
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_render_name.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_render_name.vm
deleted file mode 100644
index 6617fa23f1..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_render_name.vm
+++ /dev/null
@@ -1 +0,0 @@
-#gtx_render("testtag")
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_render_ref.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_render_ref.vm
deleted file mode 100644
index 1d950cb9ec..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/gtx_render_ref.vm
+++ /dev/null
@@ -1 +0,0 @@
-#gtx_render($cms.page.tags.testtag)
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/inpage_macro.vm b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/inpage_macro.vm
deleted file mode 100644
index 0980839d79..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/inpage_macro.vm
+++ /dev/null
@@ -1,8 +0,0 @@
-#macro(inpage $page)##
-$page.id,##
-#end##
-
-#foreach($page in $cms.folder.pages)##
-#inpage($page)##
-#hello($page)##
-#end##
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/render_part_in_editmode.vtl b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/render_part_in_editmode.vtl
deleted file mode 100644
index 971ca0992e..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/render_part_in_editmode.vtl
+++ /dev/null
@@ -1,4 +0,0 @@
-Tag ID: $cms.tag.id
-Tag name: $cms.tag.name
-editmode: $cms.rendermode.edit
-#gtx_edit($cms.tag.parts.editable)##
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/render_tag_from_masterpage.vtl b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/render_tag_from_masterpage.vtl
deleted file mode 100644
index d6a5de1713..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/render_tag_from_masterpage.vtl
+++ /dev/null
@@ -1,8 +0,0 @@
-Tag ID: $cms.tag.id
-Tag name: $cms.tag.name
-editmode: $cms.rendermode.edit
-#gtx_channel($cms.page.node.master.id)##
- #set($masterPage = $!{cms.imps.loader.getPage($cms.page.id)})##
- #set($tag = $masterPage.tags.get("inner_tag"))##
-#end##
-[#gtx_render($tag)]##
\ No newline at end of file
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/rendered_localizedpage.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/rendered_localizedpage.txt
deleted file mode 100644
index b1703cea1f..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/rendered_localizedpage.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-Tag ID: ##OUTER_TAG_ID##
-Tag name: outer_tag
-editmode: true
-[Tag ID: ##INNER_TAG_ID##
-Tag name: inner_tag
-editmode: false
-]
diff --git a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/rendered_masterpage.txt b/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/rendered_masterpage.txt
deleted file mode 100644
index 26d98c86d1..0000000000
--- a/cms-core/src/test/resources/com/gentics/contentnode/tests/rendering/nested/rendered_masterpage.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-Tag ID: ##OUTER_TAG_ID##
-Tag name: outer_tag
-editmode: true
-[Tag ID: ##INNER_TAG_ID##
-Tag name: inner_tag
-editmode: true
-
]
diff --git a/cms-oss-changelog/src/changelog/entries/2026/08/8857.GPU-2192.manualchange b/cms-oss-changelog/src/changelog/entries/2026/08/8857.GPU-2192.manualchange
new file mode 100644
index 0000000000..9444bfa77d
--- /dev/null
+++ b/cms-oss-changelog/src/changelog/entries/2026/08/8857.GPU-2192.manualchange
@@ -0,0 +1,5 @@
+The Velocity rendering engine has been removed from the CMS. Constructs using one of the part types
+* Velocity
+* Breadcrumb
+* Navigation
+must be migrated to using Handlebars before updating the CMS.
diff --git a/cms-oss-changelog/src/changelog/entries/2026/08/8858.GPU-2192.optional-manualchange b/cms-oss-changelog/src/changelog/entries/2026/08/8858.GPU-2192.optional-manualchange
new file mode 100644
index 0000000000..67b597483c
--- /dev/null
+++ b/cms-oss-changelog/src/changelog/entries/2026/08/8858.GPU-2192.optional-manualchange
@@ -0,0 +1,2 @@
+The REST API Endpoints @/diff/html@ and @/diff/source@ will now use Handlebars instead of
+Velocity to render the diff. If requests are made using custom templates, they must be converted to Handlebars templates.
diff --git a/cms-oss-doc/src/main/source/admin_migration_cmp8.textile b/cms-oss-doc/src/main/source/admin_migration_cmp8.textile
index 621ab5e5ec..2e4cf039c9 100644
--- a/cms-oss-doc/src/main/source/admin_migration_cmp8.textile
+++ b/cms-oss-doc/src/main/source/admin_migration_cmp8.textile
@@ -108,14 +108,11 @@ h6. Exceptions
There are two exception to the naming rule above:
# Settings in `$PUBLISH_LOAD_BALANCING` must be put under `config.loadbalancing`.
-# Settings in `$VELOCITY_PROPERTIES` must be put under `velocity`.
PHP-style:
$PUBLISH_LOAD_BALANCING["threadlimit"] = 2;
-
-$VELOCITY_PROPERTIES["resource.loader"] = "string,file";
New format:
@@ -124,9 +121,6 @@ New format:
config
loadbalancing:
threadlimit: 2
-
-velocity:
- resource.loader: "string,file"
h4. Configuration changes
@@ -514,7 +508,7 @@ h3. Removed Features
h4. XNL
-Rendering XNL has been removed. All existing XNL Implementations must be replaced with Velocity Implementations.
+Rendering XNL has been removed. All existing XNL Implementations must be replaced with Handlebars Implementations.
h4. Import/Export
diff --git a/cms-oss-doc/src/main/source/aloha_gcn_overview.textile b/cms-oss-doc/src/main/source/aloha_gcn_overview.textile
index 38bfd019c1..9565092bf1 100644
--- a/cms-oss-doc/src/main/source/aloha_gcn_overview.textile
+++ b/cms-oss-doc/src/main/source/aloha_gcn_overview.textile
@@ -37,7 +37,7 @@ h4. Single Root Tags
Use single root tags for your constructs. This will allow Gentics CMS to re-use your root tags as container elements. Make sure that *there are no whitespaces* before or after your root tag. It is *possible, yet discouraged to add your own ID attributes to the root tags*: along with making sure that those IDs are unique on the page, one must remember that the root tag is changed in the terms of attributes (including an ID) to make it recognizable by the tagging mechanism, and having a custom ID can trigger unwanted side effects while adding/editing/removing the tag in an editor. If it is possible, please eliminate adding own IDs in the root tags, by, for example, wrapping the tag with an ID with another empty tag (making it a root).
-WARNING: No whitespace also means: no line breaks! Avoid line breaks in velocity implementations by putting velocity comments at the end of the line (##).
+WARNING: No whitespace also means: no line breaks! Avoid line breaks in Handlebars implementations.
@@ -202,7 +202,6 @@ The Part Type names are simplified by first removing the characters '(', ')' and
The following table will show, how Part Type names are simplified:
|_.Name |_.Class |
-| Breadcrumb | breadcrumb |
| Checkbox | checkbox |
| Datasource | datasource |
| DHTML Editor | dhtml_editor |
@@ -216,7 +215,6 @@ The following table will show, how Part Type names are simplified:
| List | list |
| List (ordered) | list_ordered |
| List (unordered) | list_unordered |
-| Navigation | navigation |
| Overview | overview |
| Select (image-height) | select_image_height |
| Select (image-width) | select_image_width |
@@ -235,6 +233,5 @@ The following table will show, how Part Type names are simplified:
| URL (folder) | url_folder |
| URL (image) | url_image |
| URL (page) | url_page |
-| Velocity | velocity |
For the sake of completeness, this table contains +all+ existing Part Types, although most of them can not be used as editables.
diff --git a/cms-oss-doc/src/main/source/aloha_persist_plugin_settings.textile b/cms-oss-doc/src/main/source/aloha_persist_plugin_settings.textile
index 68b0ce9a3f..4ab4aa1997 100644
--- a/cms-oss-doc/src/main/source/aloha_persist_plugin_settings.textile
+++ b/cms-oss-doc/src/main/source/aloha_persist_plugin_settings.textile
@@ -23,18 +23,17 @@ h3. Create an object property to store Aloha Editor settings
Before creating a new object property to store our settings we will need to create a new Tagtype called "alohasettings", composed of three parts:
|_. Parttype |_. Keyword |_. Visibility |_. Description |
-| +Velocity+ | - | visible | used to render velocity |
+| +Handlebars+ | handlebars | visible | used to render Handlebars |
| +HTML/long+ | alohasettings | hidden | will store our settings |
-| +HTML/long+ | template | hidden | will render the settings |
-Fill the +template+ part with the following code
+Fill the +handlebars+ part with the following code
-
-#if ($cms.rendermode.edit)##
+
+{{#if cms.rendermode.edit}}
-#end##
+{{/if}}
In the next step create a new object property for pages, that will use our newly created Tagtype "alohasettings". We will call the object property "alohasettings" too.
@@ -91,6 +90,6 @@ Aloha.ready(function() {
});
-NOTE: When using this implementation you want to put it inside a velocity tag checking for +$cms.rendermode.edit+.
+NOTE: When using this implementation you want to put it inside a Handlebars tag checking for +cms.rendermode.edit+.
Now, changing the state of the numerated-headers plugin will be persisted to the pages +object.alohasettings+ object property whenever the user saves the page.
diff --git a/cms-oss-doc/src/main/source/feature_copy_tags.textile b/cms-oss-doc/src/main/source/feature_copy_tags.textile
index 6239952312..d2795558c5 100644
--- a/cms-oss-doc/src/main/source/feature_copy_tags.textile
+++ b/cms-oss-doc/src/main/source/feature_copy_tags.textile
@@ -71,7 +71,7 @@ h4. Pasting annotated Tags
When content is pasted into editables of pages and the _copy_tags_ feature is enabled (using +CTRL-V+), a special content handler will detect tag annotations and will then create copies of the original tags, which are placed in the edited page.
If the tag "contains" other tags (references other tags using the __ notation), the referenced (nested) tags will also be copied into the edited page and the references will be updated to the names of the new tags.
-WARNING: Tag references other than using the __ notation will +not+ be detected and updated. This especially includes tag references using velocity.
+WARNING: Tag references other than using the __ notation will +not+ be detected and updated. This especially includes tag references using Handlebars.
WARNING: Copy & Paste of tags will only work as expected if both the source and target page are hosted on the same CMS system, Copy & Paste across CMS systems is not supported.
diff --git a/cms-oss-doc/src/main/source/feature_file_publish_dependencies.textile b/cms-oss-doc/src/main/source/feature_file_publish_dependencies.textile
index 200dab37a9..96d5e88f51 100644
--- a/cms-oss-doc/src/main/source/feature_file_publish_dependencies.textile
+++ b/cms-oss-doc/src/main/source/feature_file_publish_dependencies.textile
@@ -40,7 +40,7 @@ h4. Examples of objects using files
* A page contains a link to the file
* A page displays properties of the file by rendering an overview that contains the file
-* A page displays properties of the file by rendering velocity code
+* A page displays properties of the file by rendering Handlebars templates
NOTE: Dependencies are only calculated when rendering objects during the publish process. If e.g. a page uses a file only in edit or preview mode, but not in publish mode, the dependency does not count.
When the dependency is created in an object property, it only counts, if the object property is either rendered in the page content or published into the contentrepository.
diff --git a/cms-oss-doc/src/main/source/feature_genticsimagestore.textile b/cms-oss-doc/src/main/source/feature_genticsimagestore.textile
index 6ee96814d8..965623affe 100644
--- a/cms-oss-doc/src/main/source/feature_genticsimagestore.textile
+++ b/cms-oss-doc/src/main/source/feature_genticsimagestore.textile
@@ -66,123 +66,6 @@ h4. Handlebars Helper
See "gtx_gis Helper":handlebars.html#gtx_gis for details of how to include a resized image into a handlebars tag.
-h4. Render Directive
-
-To include a resized image into a velocity tag, this should be done with the directive +#gtx_gis+.
-
-
-
-
-
-or, when cropping shall be done:
-
-
-
-
-
-The +$image+ may be an image from the same or from another node.
-
-h5. Parameters
-
-|_. Name |_. Description |_. Usage example |
-| +$image+ | Either the image (as object) or the image ID | +$cms.tag.parts.img.target+ |
-| +$resize+ | Resize options | +{"width": 50, "mode": "smart"}+ |
-| +$crop+ | Crop options | +{"x": 10, "y": 10, "width": 30, "height": 30}+ |
-
-h5. Resize options
-
-|_. Name |_. Description |_. Default value |
-| +width+ | Image width | "auto" |
-| +height+ | Image height | "auto" |
-| +mode+ | Resizing mode ("prop", "force", "smart", "fpsmart") | "prop" |
-| +type+ | Type of the rendering ("url", "phpwidget") | "url" |
-
-NOTE: +width+ and +height+ must not both be set to "auto".
-
-NOTE: The +mode+ "fpsmart" is like "smart", but it requires both +width+ and +height+ to be set and it takes the focal point of the image into account when cropping.
-"fpsmart" is only available in the render directive, not in the GenticsImageStore itself. The directive will convert "fpsmart"
-into a "cropandresize" operation. See "Using Focal Point with GenticsImageStore":gis_fpsmart.html for details.
-
-h5. Cropping options
-
-|_. Name |_. Description |_. Default value |
-| +x+ | Start X coordinate of the image area (from the top left corner) | 0 |
-| +y+ | Start Y coordinate of the image area (from the top left corner) | 0 |
-| +width+ | Cropping width | |
-| +height+ | Cropping height | |
-
-h5. Usage examples
-
-The following example assumes, that the tag has a part +img+ of type +URL (Image)+:
-
-
-#set($image = $cms.tag.parts.img.target)##
-
-
-
-It is also possible, to define the resizing parameters in a separate variable (which can be reused in the template):
-
-
-#set($image = $cms.tag.parts.img.target)##
-#set($resize = {"width": 50, "mode": "smart"})##
-
-
-
-Additionally, when cropping shall be done, the cropping parameters have to be passed as (optional) third parameter:
-
-
-#set($image = $cms.tag.parts.img.target)##
-#set($resize = {"width": 50, "mode": "smart"})##
-#set($crop = {"x": 10, "y": 10, "width": 30, "height": 30})##
-
-
-
-NOTE: When publishing pages for Gentics Portal.Node PHP, you should set the type to "phpwidget" in the resize options. It will render a PHP widget that resizes the image.
-
-h4. Static Cross Node Projects
-
-NOTE: When using the directive +#gtx_gis()+, the URLs will already be rendered correctly, even in the image
-is contained in a foreign node. The following description applies only, if *not* using the directive +#gtx_gis()+.
-
-The GenticsImageStore is also able to resize images in foreign nodes. A page in node A may contain the following image url:
-
-http://www.node-b-hostname.tld/GenticsImageStore/300/auto/prop/Content.Node/images/flower.jpg
-
-
-Such an url will be identified by the GenticsImageStore during the publish process.
-The GenticsImageStore identifies the referenced node by examining the hostname within the found url.
-The image within node B will be resized when the GenticsImageStore determines that the referenced
-node (in this case node b) is publishing into the file system. Resizing will otherwise be omitted.
-
-The image tag must be adapted to include the node B hostname.
-
-Example velocity implementation:
-
-#set( $nodePath = "$cms.tag.parts.src.target.folder.node.path")
-#set( $pubdir = "$cms.tag.parts.src.target.folder.pub_dir")
-#set( $imagePath = "$cms.tag.parts.src.target.name")
-
-## Remove the trailing slash from the pub_dir
-#set( $pubdir = $pubdir.trim())
-#if($pubdir.endsWith("/"))
-#set( $len = $cms.imps.velocitytools.math.sub($pubdir.length(),1) )
-#set( $pubdir = $pubdir.substring(0, $len))
-#end
-
-## Remove the trailing slash from the nodePath
-#set( $nodePath = $nodePath.trim())
-#if($nodePath.endsWith("/"))
-#set( $len = $cms.imps.velocitytools.math.sub($nodePath.length(),1) )
-#set( $nodePath = $nodePath.substring(0, $len))
-#end
-
-#if($cms.rendermode.publish)
-
-#else
-
-#end
-
-
h4. Publishing
Resized images will be written to the file system when the GenticsImageStore was used within the project. The usage will be determined by examining the final page content. All GenticsImageStore URLs will be processed.
diff --git a/cms-oss-doc/src/main/source/feature_mesh_contentrepository.textile b/cms-oss-doc/src/main/source/feature_mesh_contentrepository.textile
index 1629b00d3d..9a6b049ddd 100644
--- a/cms-oss-doc/src/main/source/feature_mesh_contentrepository.textile
+++ b/cms-oss-doc/src/main/source/feature_mesh_contentrepository.textile
@@ -96,7 +96,7 @@ The user (identified either by username/password or be API Token) must have suff
h4. Roles Property
-By setting the field _Roles Property_ it is possible to assign the +readPublished+ permission on published objects to specific roles in Gentics Mesh. This property can be either an object property with a select part, or an expression that evaluates fields in a Velocity context.
+By setting the field _Roles Property_ it is possible to assign the +readPublished+ permission on published objects to specific roles in Gentics Mesh. This property can be an object property with a select part.
h5. Roles Objectproperty
@@ -109,21 +109,6 @@ Permissions in Mesh can neither be set language specific nor branch specific. Th
NOTE: If one of the roles object properties is *not* synchronized, the action +Check+ in the ContentRepository will fail (and the log will show an error). The publish process will not fail
in such cases, but will possibly lead to unexpected permission settings in Mesh.
-h5. Velocity Expression
-
-Variables used in a Velocity template can be resolved using the "Expression Parser":https://www.gentics.com/Content.Node/guides/tagmap_expression_parser.html. Such expressions can be used to define the desired roles. For example:
-
-# Create a tagtype with a Velocity part called +vtl+ and the following template:
-
-#set($roles = [])
-$roles.add("role_a")
-$roles.add("role_b")
-
-# Create Folder/File/Page object properties with the name +meshroles+ using the created tagtype.
-# Set the ContentRepositories _Roles Property_ to +object.meshroles.parts.vtl.roles+.
-
-For more complex solution additional tagparts will be needed, and the corespondig logic must be implemented in the Velocity template.
-
h4. Default Role
The set default role will have the +readPublished+ permission assigned on all objects, for which the _Roles Property_ was not filled.
@@ -223,7 +208,7 @@ h6. Transformation of tagtypes
When a Mesh ContentRepository contains at least one tagmap entry of type "Micronode", all constructs that meet all of the following requirements will be transformed into microschemas:
# The construct must be assigned to at least one Node that publishes into the Mesh ContentRepository
-# The construct must contain at least one editable Part with a non-empty keyword - other than @Tag (global)@, @File (localpath)@, @Table ext@, @Velocity@, @Breadcrumb@, @Navigation@
+# The construct must contain at least one editable Part with a non-empty keyword - other than @Tag (global)@, @File (localpath)@, @Table ext@
# The construct matches at least one of the micronode filters
h6. Part Types with special mapping
diff --git a/cms-oss-doc/src/main/source/feature_validation.textile b/cms-oss-doc/src/main/source/feature_validation.textile
index ac63686b25..894e52eb70 100644
--- a/cms-oss-doc/src/main/source/feature_validation.textile
+++ b/cms-oss-doc/src/main/source/feature_validation.textile
@@ -32,7 +32,7 @@ Once the validation feature is turned on, edit operations performed on tags will
HTML attributes in existing content (templates, tags, tagtypes) must not contain node-tags, with the exception of URL tags (wich have a default part-policy of "any URI")
all parts of tag-types, and only parts of tag-types, have keywords beginning with "part". Tag-types themselves should not have keywords beginning with "part"
-page-templates and the "template" and "macros" parts, that are used in conjunction with Overview and Velocity parts, are not editable, and Overview parts are not changeable, and any input entered by editors that is processed by XNL tags and Overview and Velocity tags is performed in a safe manner.
+page-templates, that are used in conjunction with Overview parts, are not editable, and Overview parts are not changeable, and any input entered by editors that is processed by XNL tags and Overview tags is performed in a safe manner.
No errors will be displayed if these requirements aren't fulfilled, but these requirements must be fulfilled in order for the validation to be secure.
h4. Node tags in HTML attributes
@@ -65,21 +65,19 @@ Additionally, it is specified that node-tag keywords may not contain a dot (".")
An alternative to prefixing the keyword of a tag-part with "part" is to leave the keyword empty, which will make it impossible to resolve the part with a node-tag.
-h4. Page-Templates, XNL, Velocity and Overviews
+h4. Page-Templates, XNL and Overviews
-The third condition concerns page-templates, XNL, and Velocity and Overview parts.
+The third condition concerns page-templates, XNL, and Overview parts.
Page-templates must be able to contain arbitrary HTML, since it must be possible to define script dependencies and the HTML structure for the page.
XNL functinos and conditions may perform arbitrary operations.
-Velocity and Overview parts, both, use the "template" and "macros" parts, which may contain arbitray Velocity.
+Authoring page-templates or calling XNL functions or writing XNL conditions are inherently trusted operations. It is not feasible to validate these operations to prevent XSS attacks.
-Authoring page-templates or Velocity code, or calling XNL functions or writing XNL conditions are inherently trusted operations. It is not feasible to validate these operations to prevent XSS attacks.
+For this reason, editors must not have the possibility to edit page-templates or use XNL functions or XNL conditions, and Overview parts must not be editable (checkbox in the part-properties dialog) and Overview templates must not be changeable (there is a checkbox below the template when filling-in the tag-type defaults).
-For this reason, editors must not have the possibility to edit page-templates or use XNL functions or XNL conditions, and Overview and Velocity parts must not be editable (checkbox in the part-properties dialog) and Overview templates must not be changeable (there is a checkbox below the template when filling-in the tag-type defaults).
-
-If XNL structures are encountered in the markup, they will by default cause a validation error. However, the impelementer is still responsible for ensuring that user-supplied parameters to XNL functions or XNL conditions can't be exploited to formulate an XSS attack. The same applies to page-templates and Overview/Velocity parts except that these must be explicitly disabled for editors. The same also applies for parts of tag-types, for which the implementer chose a more permissive policy than the default policy. Such tag-types must not be editable by a user, and the implementer must ensure that user-supplied content is processed in a safe manner.
+If XNL structures are encountered in the markup, they will by default cause a validation error. However, the impelementer is still responsible for ensuring that user-supplied parameters to XNL functions or XNL conditions can't be exploited to formulate an XSS attack. The same applies to page-templates and Overview parts except that these must be explicitly disabled for editors. The same also applies for parts of tag-types, for which the implementer chose a more permissive policy than the default policy. Such tag-types must not be editable by a user, and the implementer must ensure that user-supplied content is processed in a safe manner.
For example, consider the following scenario: the implementer writes the following HTML fragment into the source of a page-template, or into a part with a permissive policy:
@@ -89,11 +87,11 @@ var userVariable = '';
-If the tag "user-supplied-content" has the default XSS-safe policy, an editor will be able to write arbitrary text into the tag. In this scenario, however, arbitrary text means that the user is able to write arbitrary javascript, since it is straightforward to escape the single quotes from within the user supplied content. It is not possible to combine Javascript and node-tags in a safe manner. This is because node-tags are not treated as Javascript objects - once the page is rendered, the node tags will be inserted into the Javascript element as an arbitrary chunk of text. It is possible, however, to use Velocity to access contents of node tags in a safe manner. Velocity can access the contents of node-tags in the form of Java Strings. These Java Strings do not escape the Velocity contex. If the Java String is to be rendered in the page, however, the same Problem as above applies. With Velocity, however, it is possible to perform custom validation or escaping on the string before rendering it into the page, since Velocity is executed during the rendering process of the page.
+If the tag "user-supplied-content" has the default XSS-safe policy, an editor will be able to write arbitrary text into the tag. In this scenario, however, arbitrary text means that the user is able to write arbitrary javascript, since it is straightforward to escape the single quotes from within the user supplied content. It is not possible to combine Javascript and node-tags in a safe manner. This is because node-tags are not treated as Javascript objects - once the page is rendered, the node tags will be inserted into the Javascript element as an arbitrary chunk of text.
h3. Working with secure tag-types
-Implementers will have the requirement to be able to insert arbitrary HTML, including arbitrary scripts, into parts that are not accessible by editors. Once the implementer has made certain, that a part is not editable, he may choose a more permissive validation policy for this part. For example, the "any Content" policy will allow any input to be entered, which is necessitated by e.g. the "template" part of Velocity tag-types.
+Implementers will have the requirement to be able to insert arbitrary HTML, including arbitrary scripts, into parts that are not accessible by editors. Once the implementer has made certain, that a part is not editable, he may choose a more permissive validation policy for this part. For example, the "any Content" policy will allow any input to be entered.
h3. Configuring a custom AntiSamy policy
diff --git a/cms-oss-doc/src/main/source/features_discontinued.textile b/cms-oss-doc/src/main/source/features_discontinued.textile
index ef03d216f8..276af50bd8 100644
--- a/cms-oss-doc/src/main/source/features_discontinued.textile
+++ b/cms-oss-doc/src/main/source/features_discontinued.textile
@@ -319,7 +319,6 @@ user_importexport_permissions
usergroup_popup
UTF8
var_field
-velocity_helplink
versiondiff
wikiedit
win_halt
diff --git a/cms-oss-doc/src/main/source/gcn_part_types.textile b/cms-oss-doc/src/main/source/gcn_part_types.textile
index 00c816066a..3e8085735d 100644
--- a/cms-oss-doc/src/main/source/gcn_part_types.textile
+++ b/cms-oss-doc/src/main/source/gcn_part_types.textile
@@ -18,41 +18,12 @@ h3. Overview
| 30 | Select (multiple) | This part type provides static datasources from which a user can pick multiple values. |
| 31 | Checkbox | Part type for input of boolean value. |
| 32 | Datasource | With this part type, the user can define individual datasources in the tag. |
-| 33 | Velocity | The velocity part type can be used to evaluate all previously generated text using the velocity markup parser. |
| 40 | Node | The node part is a drop-down menu with the nodes available to the user. |
| 42 | Form | The CMS Form part lets the user select a form from the CMS. See "Gentics CMS Forms":feature_forms.html for details. **NOTE:** Parts of this type can only be used in the new Editor User Interface. |
| 43 | Handlebars | The Handlebars part type renders its content with the Handlebars rendering engine. See "Rendering with Handlebars":handlebars.html for details. |
NOTE: Inline editable parts - which are transformed to editables in Aloha Editor - should only use the part type @HTML@.
-h3. Velocity Part Type
-
-An example for this tag part type can be found within the demo server in the folder "Demo-CMS-Projekt/Home/Node Tags".
-
-* Parameter "template"
-* Type: HTML lang
-* Content: The Velocity Template Code that should be rendered by the visible Velocity Part Type.
-
-* Parameter "macros":
-* Type: HTML lang
-* Content: VTL Macros which can be used within the implementation.
-
-Example Velocity Tagtyp:
-
-* Part 1: Typ Velocity, Keyword vtl, Visible
-* Part 2: Typ HTML lang, Keyword template, Not visible
-* Part 3: Typ HTML lang, Keyword macros, Not visible
-
-Errors within the velocity implementation will be diplayed within the Gentics CMS im "error stream".
-
-NOTE: Use always the __.toString()__ method when comparing two tags within a __#if()__ command.
-
-Example:
-
-
-#if( $cms.page.object.myprop.toString() == "test" )
-
-
h3. Custom Part Type Implementations
Custom part types can be created using the AbstractExtensiblePartType class.
diff --git a/cms-oss-doc/src/main/source/handlebars.textile b/cms-oss-doc/src/main/source/handlebars.textile
index afbf4d4016..ffb6b5c936 100644
--- a/cms-oss-doc/src/main/source/handlebars.textile
+++ b/cms-oss-doc/src/main/source/handlebars.textile
@@ -33,9 +33,9 @@ The context of a rendered Handlebars part will always contain the base object +c
INFO: To find out all possible attributes that can be resolved from the base object "cms", you can use something like +{{#each cms}}{{ @key }}:{{ this }} {{/each}}+.
This obviously does not only work for "cms", but for every object in the context.
-WARNING: Unlike the Velocity Part Type, the Handlebars Part Type does not support "shortcuts" when resolving. So for example to resolve a specific part in the current tag,
+WARNING: The Handlebars Part Type does not support "shortcuts" when resolving. So for example to resolve a specific part in the current tag,
it is not allowed to omit the "parts" keyword in handlebars: +{{ cms.tag.parts.html }}+ will resolve to the part "html" in the current tag, whereas +{{ cms.tag.html }}+ will *not* work.
-Hence, if you need to, say, render a copyright of a referenced image, set withing an image's object property, the Velocity's definition +{{cms.tag.parts.img.object.copyright}}+ turns into longer variants for the Handlebars:
+Hence, if you need to, say, render a copyright of a referenced image, set withing an image's object property, it is possible to use
either +{{{gtx_render cms.tag.parts.img.target.object.copyright }}}+ with +target+ image dereferencing, or
+{{cms.tag.parts.img.target.object.copyright.parts.text.text}}+, where in addition +parts+ property listing, and +text+ part type now have to be explicitly mentioned, if one wants to avoid using +gtx_render+ (which is discouraged).
@@ -98,7 +98,7 @@ The helper can also be used in combination with other helpers (conditional helpe
NOTE: Since gtx_render will always output a String, the comparison must also be done with the String ("1") and not with the Integer (1).
-WARNING: Unlike Velocity, the Handlebars Part Type will *only* render objects if the gtx_render helper is used. Simply referencing like +{{{ cms.page.tags.othertag }}}+ will not render the other tag, but will output some information about the referenced object.
+WARNING: The Handlebars Part Type will *only* render objects if the gtx_render helper is used. Simply referencing like +{{{ cms.page.tags.othertag }}}+ will not render the other tag, but will output some information about the referenced object.
h5. gtx_edit
@@ -353,7 +353,7 @@ NOTE: Partials will not be synchonized into the CMS, so changes in a partial fil
h3. Differences to Velocity
-This section will cover some differences between the Velocity PartType and the Handlebars PartType (apart from the obvious difference in templating language syntax), which hopefully will help with migration of implementations.
+This section will cover some differences between the old Velocity PartType and the Handlebars PartType (apart from the obvious difference in templating language syntax), which hopefully will help with migration of implementations.
|_. |_. Velocity |_. Handlebars |
| Construct setup | The Velocity PartType needs another PartType with keyword +template+ which contains the template to render. | The Handlebars PartType will use its own content as template. |
@@ -362,4 +362,4 @@ This section will cover some differences between the Velocity PartType and the H
| Reusable templates | The Velocity PartType supports both locally defined and globally configured macros | The Handlebars PartType supports "partials":#partials, which must be defined in devtool packages. |
| Programmatic logic | Velocity supports programmatic logic like defining variables, calling various methods of objects and even instantiation of new objects. | Handlebars is logic-less but supports programmatic logic via "helpers":#helpers (built-in or "custom":#custom-helpers) which guarantees a clean separation between business logic and presentation. |
| HTML Escaping | Velocity does not escape HTML by default, so for instance the EscapeTool must be used for that purpose. | Handlebars does HTML Escaping when two curly braces are used and omits HTML Escaping upon three curly braces. |
-| Resolving of context variables | In Velocity, it is possible to add variables to the context and resolve them via the velocity part (as described "here":feature_mesh_contentrepository.html#velocity-expression). | In Handlebars it is not possible to access the context via resolving. |
+| Resolving of context variables | In Velocity, it is possible to add variables to the context and resolve them via the velocity part. | In Handlebars it is not possible to access the context via resolving. |
diff --git a/cms-oss-doc/src/main/source/impl_using_velocity.textile b/cms-oss-doc/src/main/source/impl_using_velocity.textile
deleted file mode 100644
index 727b397c61..0000000000
--- a/cms-oss-doc/src/main/source/impl_using_velocity.textile
+++ /dev/null
@@ -1,126 +0,0 @@
-h2. Using Velocity in Tagtypes
-
-If you want to use Velocity in your tagtypes you have to use at least 2 parts of the tagtype in the right manner.
-
-endprologue.
-
-NOTE: Using Velocity as template language is deprecated. Since GCMS version 6.2 "Handlebars":handlebars.html is the recommended template language.
-
-h3. Basic Usage
-
-# Add a Velocity part. Do not hide it and don't make it editable.
-# Add any HTML part, set "template" as the key and hide it. The part may be editable (when editors should be able to modify the template), but should not be inline editable.
-
-NOTE: Make sure that the Velocity part is not editable. Editable Velocity parts are not supported. It could lead to side effects and there is no possibility
-that users can edit the Velocity part anyway.
-
-h3. <node>-Notation in Templates
-
-WARNING: It is strongly discouraged to use the <node>-Notation in Velocity templates. It is better to use Velocity syntax or the "Render Directives":#render-directives to render other parts, tags or other data from the CMS.
-
-If the VTL-Template includes data via the <node>-Notation, these includes will be resolved in a separate step before Velocity rendering is done.
-
-bq.. For example, when using the VTL-template
-
-@Page renders into the content.@
-
-for a page (with name "Test Page"), and @textpart@ is resolved into another part of the tag, with content
-
-@## Hello world ##@
-
-the <node> inclusions would be resolved first, leading to
-
-@Page Test Page renders ## Hello world ## into the content.@
-
-which Velocity would render to
-
-@Page Test Page renders@
-
-because @##@ starts a VTL-comment.
-
-p. This is bad for the following reasons:
-
-# The rendering behaviour is unpredictable, because included content could contain the characters # and $ which have a special meaning in Velocity.
-# The templates depend on the content and can therefore not be cached efficiently, which can decrease rendering performance significantly.
-
-h3. Render Directives
-
-In the velocity template, two directives will be available for rendering other parts or tags.
-
-|_. Name |_. Description |_. Usage example |
-| +#gtx_render+ | Renders the specified part or tag not editable (even if in edit mode) | #gtx_render("text"), #gtx_render($cms.tag.parts.text), #gtx_render($cms.page.tags.content) |
-| +#gtx_edit+ | Renders the specified part or tag editable (if in edit mode) or not editable (if not in edit mode) | #gtx_edit("text"), #gtx_edit($cms.tag.parts.text), #gtx_edit($cms.page.tags.content) |
-
-h3. GIS Directive
-
-The directive +#gtx_gis+ can be used to include resized images in velocity tags. See "GenticsImageStore":feature_genticsimagestore.html for details about this directive.
-
-h3. Channel Directive
-
-The directive +#gtx_channel+ can be used to render its body in the context of another channel, which is
-for example useful to create links to another channel.
-
-
-#gtx_channel($cms.tag.parts.channel)
-$cms.tag.parts.text
-#end
-
-
-Its is also possible to use global UUIDs instead of local ids. E.g.:
-
-
-#gtx_channel("63C2.85f146ae-8d03-11ed-b8bc-0242ac1a0002")
-$cms.tag.parts.text
-#end
-
-
-
-h3. Form Directive
-
-The directive +#gtx_form+ is used to render the template code necessary for rendering a CMS Form into a page in either Gentics Portal | java or Gentics Portal | php.
-See "Gentics CMS Forms":feature_forms.html#form-directive for details.
-
-h3. Defining Macros
-
-There are three possible ways to define macros:
-
-h4. Inline Macros in Templates
-
-Define the macro directly in the template, which will use it.
-The drawback of this approach is, that macros can not be reused
-in other tags in a proper manner.
-
-Note: Starting with Gentics CMS 5.2.5, inline macros will
-only be callable in the template and not interfere with macros from other tags.
-
-h4. Global Macro Library
-
-For correctly reusing macros, they must be defined in a global macro library.
-
-
-velocity:
- resource.loader: "string,file"
- file.resource.loader.path: "/cms/data/"
- file.resource.loader.cache: "true"
- file.resource.loader.modificationCheckInterval: "60"
- velocimacro.library: "velocimacro-lib.vm"
-
-
-You define a single file @/cms/data/velocimacro-lib.vm@ (which should be readable for user node)
-to contain the global macros. Those macros will automatically be available to all Velocity Tags.
-With the above settings, changes to the @velocimacro-lib.vm@ will be available after up to 60 seconds.
-
-NOTE: After changing the file resource loader path, the configuration must be reloaded in order for the setting to take effect.
-
-See the "Velocity Developer Guide":http://velocity.apache.org/engine/1.6/developer-guide.html#velocity_configuration_keys_and_values
-for details about the velocity configuration settings.
-
-h4. Macro Library in a pagetag
-
-The third possibility to reuse macros is to create e.g. a special page, that contains the macros in a tag (do use Tagtype HTML (long) here).
-Then add a third tagpart with keyword "macros" and parttype "Tag (page)" to the Velocity Tag, and let it link to the tag of the macro library page.
-In this way, the macros can be maintained in a global place, but will be used as inline macros in the tags.
-
-h4. Velocity Implementations with Aloha Editor
-
-To avoid common mistakes you should "follow this guide":aloha_gcn_overview.html#constructs for implementing your root tag.
diff --git a/cms-oss-doc/src/main/source/meta_attributes.textile b/cms-oss-doc/src/main/source/meta_attributes.textile
index 991d1d4c1e..6d170fdaf9 100644
--- a/cms-oss-doc/src/main/source/meta_attributes.textile
+++ b/cms-oss-doc/src/main/source/meta_attributes.textile
@@ -156,109 +156,6 @@ h4. Rendermode
| frontend | +true+ when rendering in frontend mode. The return value is valid in edit mode only. |
| backend | +true+ when rendering in backend mode. The return value is valid in edit mode only. |
-h4. Imps
-
-|_. Property name |_. Description |
-| velocitytools | Velocity ToolsImp |
-| velocitytools.date | "DateTool":http://velocity.apache.org/tools/1.4/javadoc/org/apache/velocity/tools/generic/DateTool.html |
-| velocitytools.math | "MathTool":http://velocity.apache.org/tools/1.4/generic/MathTool.html |
-| velocitytools.number | "NumberTool":http://velocity.apache.org/tools/1.4/javadoc/org/apache/velocity/tools/generic/NumberTool.html |
-| velocitytools.esc | "EscapeTool":http://velocity.apache.org/tools/1.4/generic/EscapeTool.html |
-| velocitytools.alternator | "AlternatorTool":http://velocity.apache.org/tools/1.4/javadoc/org/apache/velocity/tools/generic/AlternatorTool.html |
-| velocitytools.list | "ListTool":http://velocity.apache.org/tools/1.4/javadoc/org/apache/velocity/tools/generic/ListTool.html |
-| velocitytools.iterator | "IteratorTool":http://velocity.apache.org/tools/1.4/javadoc/org/apache/velocity/tools/generic/IteratorTool.html |
-| string | "String Formatter Imp":#string-formatter-imp |
-| date | "Date Formatter Imp":#date-formatter-imp |
-| sorter | "Sort Imp":#sort-imp |
-| loader | "Loader Imp":#loader-imp |
-| url | "URL Include Imp":#url-include-imp |
-
-h5. String Formatter Imp
-
-The String Formatter Imp provides methods for escaping and other string manipulation:
-
-|_. Syntax |_. Description |
-| $cms.imps.string.escapeHTML(string) | Escape special characters (like '<', '>', '&') with entities. |
-| $cms.imps.string.escapeJS(string) | Escapes special javascript characters (like '\', ''', '"') with \ to make them save for output in javascript strings. |
-| $cms.imps.string.stripML(string) | Remove the embedded HTML tags from user input string to prevent potential problems (in fact it removes anything beginning with < and ending with > ). |
-| $cms.imps.string.trim(string, length) | Trim the given string to be no longer than length characters. |
-| $cms.imps.string.regexp(string, pattern, replacement) | Replace all occurances of the pattern with replacement. |
-| $cms.imps.string.testRegex(string, regex) | Test whether the string matches the regex. |
-| $cms.imps.string.trimWords(string, length) | Trim all words in @string@ to be no longer than @length@. Longer words are trimmed using ... as ellipsis. |
-| $cms.imps.string.trimWords(string, length, ellipsis) | Trim all words in @string@ to be no longer than @length@. Longer words are trimmed using @ellipsis@. |
-| $cms.imps.string.trimWords(string, length, ellipsis, template) | Trim all words in @string@ to be no longer than @length@. Longer words are replaced by @template@, where @$trimmedword@ will be replaced by the trimmed word and @$word@ with the original one. |
-| $cms.imps.string.encodeURL(string[, string]) | URL - encode the specified @string@ and return it. The encoding used to get the bytes for unsafe characters defaults to "utf-8" but may be given as second parameter (e.g. "iso-8859-1"). |
-| $cms.imps.string.implode(Array/Collection, seperator) | Convert the given array or collection into a string separating the items with the given string separator. |
-| $cms.imps.string.implode(Array/Collection, separator, prefix, postfix) | See above. In addition the items will be pre- and postfixed. |
-| $cms.imps.string.toUpper(string) | Convert the given string to all uppercase. |
-| $cms.imps.string.md5(string) | Compute the md5 hash of the given String. |
-
-h5. Date Formatter Imp
-
-The DateFormatterImp allows you to format date strings and date objects.
-
-
- // Format the date using the given pattern and the english locale
- $cms.imps.date.format($date, "dd MMM yyyy HH:mm:ss", "en")
-
- // Format the date using the given pattern. The local is deduced by inspecting the page language.
- $cms.imps.date.format($date, "dd MMM yyyy HH:mm:ss")
-
- // Create a date by using a timestamp
- $cms.imps.date.fromTimestamp($timestamp)
-
- // Parse a date string and create a date object
- $cms.imps.date.parse("22 MAR 1984 12:30:00", "dd MMM yyyy HH:mm:ss", "EN")
-
- // Calculate difference in years between dateA and dateB
- $cms.imps.date.dateDiff($dateA, $dateB, "y")
-
- // Example of using the imp with edittimestamps
- $cms.imps.date.format($cms.imps.date.fromTimestamp($cms.page.edittimestamp), "MMMM dd, yyyy", "en")
-
-
-h5. Sort Imp
-
-Sort the given collection (might also be an array or a map) by the given list of properties.
-
-
- $cms.imps.sorter.sort(Collection collection, String[] properties[, boolean caseSensitive][, String languageCode])
-
-
-Sort the given collection (might also be an array or a map) by the given list of properties.
-The sortorder can be independently set for each property in the list.
-When sorting by only one property, one can also pass a single String instead of an array of Strings as value for the parameter properties.
-
-| __collection__ | Collection to be sorted. |
-| __properties__ | Array of sorted properties. The general syntax for a sorted property is @[path.to.property][:asc][:desc]@. If neither @:asc@ nor @:desc@ are given, the sorting is done ascending. |
-| __caseSensitive__ | Optional boolean flag to sort case sensitive (default is @false@). |
-| __languageCode__ | Optional language code. Must be a lower-case, two-letter code as defined by "ISO-639-1":http://www.loc.gov/standards/iso639-2/php/code_list.php. |
-
-h5. Loader Imp
-
-The Loader Imp can be used to retrieve content objects by id.
-
-|_. Syntax |_. Description |
-| $cms.imps.loader.getObject(type, id) | Load the object of @type@ with @id@. @type@ can be one of "page", "folder", "image", "file", "node" |
-| $cms.imps.loader.getPage(id) | Load the page with @id@. |
-| $cms.imps.loader.getFolder(id) | Load the folder with @id@. |
-| $cms.imps.loader.getImage(id) | Load the image with @id@. |
-| $cms.imps.loader.getFile(id) | Load the file with @id@. |
-| $cms.imps.loader.getNode(id) | Load the node with @id@. |
-
-h5. URL Include Imp
-
-The +URLIncludeImp+ allows you to include contents from other URLs.
-
-
- $cms.imps.url.include(url, cache, timeout, default)
-
-
-| __url__ | URL to be requested |
-| __cache__ | cache lifetime in secs, defaults to 300 secs (5 mins) |
-| __timeout__ | timeout for accessing the URL and getting the contents in ms, defaults to 2000 ms (2 secs) |
-| __default__ | default content to be returned, if the URL cannot be accessed (default: null, will result in an error if URL cannot be accessed) |
-
h3. Childobjects
h4. Language
@@ -309,9 +206,9 @@ h3. Parttypes
h4. Overview Parttype
-h5. Velocity Properties
+h5. Handlebars Properties
-Properties available when rendering an overview using velocity:
+Properties available when rendering an overview using Handlebars:
|_. Property name |_. Description |
| items | Collection, viewable objects of the overview |
@@ -322,15 +219,15 @@ Properties available when rendering an overview using velocity:
| maxItems | Maximum number of listed items |
| recursive | True to select items recursively (when selectType is either FOLDER or AUTO) |
-
-#foreach($item in $cms.page.tags.overviewtag.overviewpart.items)
-$item.key $item.value
-#end
+
+{{#each cms.page.tags.iverviewtag.parts.overviewpart.items}}
+{{key}} {{value}}
+{{/each}}
h5. <node> Template Properties
-These placeholders are available in overview templates (when the overview part is rendered directly, without the use of velocity):
+These placeholders are available in overview templates (when the overview part is rendered directly, without the use of Handlebars):
|_. Property name |_. Description |
| <node ds.nr> | iteration counter |
@@ -339,7 +236,7 @@ These placeholders are available in overview templates (when the overview part i
h4. Datasource/Select (Single)/Select (Multiple) Parttype
-h5. Velocity Properties
+h5. Handlebars Properties
|_. Property name |_. Description |
| items | Collection of all entries in the database |
@@ -352,14 +249,14 @@ h5. Velocity Properties
| dsid | internal id of the element |
-#foreach( $item in $cms.tag.parts.multiselect.items )
-$item.key - $item.value
-#end
+{{#each cms.tag.parts.multiselect.items}}
+{{key}} - {{value}}
+{{/each}}
h5. <node> Template Properties
-These placeholders are available in datasource templates (when the part is rendered directly, without the use of velocity).
+These placeholders are available in datasource templates (when the part is rendered directly, without the use of Handlebars).
|_. Property name |_. Description |
| <ds value> | the selected value |
diff --git a/cms-oss-doc/src/main/source/using_meta_attributes.textile b/cms-oss-doc/src/main/source/using_meta_attributes.textile
index 4f0bf5c22e..b83e7eea22 100644
--- a/cms-oss-doc/src/main/source/using_meta_attributes.textile
+++ b/cms-oss-doc/src/main/source/using_meta_attributes.textile
@@ -13,32 +13,18 @@ h4. Node-Style
The Node-style syntax is available in pages, templates and tags. When the rendered attribute
is a tag, it will be rendered with the appropriate icons.
-WARNING: Rendering tags in edit mode via the Node-Style syntax can cause problems, if the template contains "@<@" or "@>@" characters (for example @@). Consider using the @#gtx_edit@ "render directive":impl_using_velocity.html#render-directives.
+WARNING: Rendering tags in edit mode via the Node-Style syntax can cause problems, if the template contains "@<@" or "@>@" characters (for example @@). Consider using the @#gtx_edit@.
-h4. Velocity-Style (VTL-Style)
+h4. Handlebars-Style
-WARNING: Rendering tags with the plain Velocity-Style syntax will *not* generate tag icons. Use the @#gtx_edit@ "render directive":impl_using_velocity.html#render-directives to render tags in edit mode.
-
-VTL stands for "Velocity Template Language" and stands for the syntax of "Velocity" (a template language) -
-see "Velocity part type":gcn_part_types.html#velocity-part-type and
-"Using Velocity in Tagtypes":impl_using_velocity.html for details.
+WARNING: Rendering tags with the plain Handlebars syntax will *not* generate tag icons. Use the @#gtx_edit@ helper to render tags in edit mode.
- $cms.page.name
-
-
-WARNING: If a Tagtype contains a part names "class" Velocity syntax cannot be used to resolve its value because it would just return the Tagtypes Java class. Use @getProperty@ as a workaround.
-
-
-## won't work as expected will just return a Java class
-$cms.tag.parts.class
-
-## this will work as expected
-$cms.tag.parts.getProperty("class")
+ {{cms.page.name}}
h4. Tagmap-Style
@@ -64,16 +50,15 @@ h3. Baseobjects
These are the base objects that can be used in the CMS, along with examples on how they can be accessed and in which contexts they are made available.
-|_. Object |_. Velocity example |_. Node-Style Example |_. Availability |
-| "page":#page | $cms.page.name | <node page.name> | page |
-| "template":#template | $cms.template.id | <node template.id> | page, template |
-| "file":#file | $cms.file.name | <node file.name> | file |
-| "folder":#folder | $cms.folder.name | <node folder.name> | folder, file, page |
-| "node":#node | $cms.node.host | <node node.host> | file, folder, page, tag, template |
-| "object":#object | $cms.object.startpage | <node object.startpage> | file, folder, page |
-| "rendermode":#rendermode | $cms.rendermode | N/A | file, folder, page, tag, template |
-| "imps":#imps | $cms.imps.string | N/A | file, folder, page, tag, template |
-| "tag":#tag | $cms.tag.parts.url | <node url> | tag |
+|_. Object |_. Handlebars example |_. Node-Style Example |_. Availability |
+| "page":#page | {{cms.page.name}} | <node page.name> | page |
+| "template":#template | {{cms.template.id}} | <node template.id> | page, template |
+| "file":#file | {{cms.file.name}} | <node file.name> | file |
+| "folder":#folder | {{cms.folder.name}} | <node folder.name> | folder, file, page |
+| "node":#node | {{cms.node.host}} | <node node.host> | file, folder, page, tag, template |
+| "object":#object | {{gtx_render cms.object.startpage}} | <node object.startpage> | file, folder, page |
+| "rendermode":#rendermode | {{cms.rendermode}} | N/A | file, folder, page, tag, template |
+| "tag":#tag | {{gtx_render cms.tag.parts.url}} | <node url> | tag |
h4. Page
@@ -86,22 +71,6 @@ The actual pageobject is only available in pagecontext (pages, pageurl's, page o
$cms.page.publishdate // VTL-Style
-A very common use case is to check whether a page exists using a Velocity if-statement.
-
-
-## bad - the whole page will be rendered
-#if("$cms.page.languageset.pages.en" != "")
-English
-#end
-
-WARNING: When checking if pages exists in Velocity if-statements it's best to always check for page ids rather than checking for the page itself, as any direct invocation of a page object will render the page. This is rather costly if you just want to check if a page exists.
-
-## good - best performance
-#if($cms.page.languageset.pages.en.id)
-English
-#end
-
-
h4. Template
NOTE: Access the list of "template meta attributes":meta_attributes.html#template from the "list of meta attributes":meta_attributes.html page.
@@ -176,26 +145,14 @@ VTL Style: $cms.page.tags.TAGNAME.name
h4. Rendermode
-NOTE: Rendermode is *only available when using velocity syntax*. Access the list of "rendermode meta attributes":meta_attributes.html#rendermode from the "list of meta attributes":meta_attributes.html page.
+NOTE: Rendermode is *only available when using Handlebars syntax*. Access the list of "rendermode meta attributes":meta_attributes.html#rendermode from the "list of meta attributes":meta_attributes.html page.
-This basic object applies access to information of the actual node during rendering with velocity.
+This basic object applies access to information of the actual node during rendering with Handlebars.
-VTL Style: $cms.rendermode.publish
-
-
-h4. Imps
-
-NOTE: Access the list of "imps meta attributes":meta_attributes.html#imps from the "list of meta attributes":meta_attributes.html page.
-
-This basic object allows access to information of velocity imps.
-
-
-$cms.imps.string
+VTL Style: {{cms.rendermode.publish}}
-Velocity GenericTools contains a collection of reusable and well documented tools and utility classes of general interest to Velocity users. These classes and tools have no dependency on the VelocityView or VelocityStruts sub-projects. The tools may be used as you would any other POJO ("plain old java object").
-
h3. Childobjects
Child objects are only available from the context of a base object.
diff --git a/cms-oss-server/src/main/java/com/gentics/contentnode/init/Initializer.java b/cms-oss-server/src/main/java/com/gentics/contentnode/init/Initializer.java
index 7c0f7773b7..cde552e972 100644
--- a/cms-oss-server/src/main/java/com/gentics/contentnode/init/Initializer.java
+++ b/cms-oss-server/src/main/java/com/gentics/contentnode/init/Initializer.java
@@ -189,12 +189,6 @@ public void init() {
throw new RuntimeException(e);
}
- try {
- NodeConfigRuntimeConfiguration.initVelocity();
- } catch (Exception e) {
- throw new RuntimeException("Error while initializing Velocity Engine", e);
- }
-
// this is optional, but we rather preload the validation API on startup
// than waiting for the first user-input to happen. Loading the default
// configuration takes a while (the AntiSamy policy in particular).
diff --git a/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/PartType.java b/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/PartType.java
index 67faef4012..376d2afbc5 100644
--- a/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/PartType.java
+++ b/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/PartType.java
@@ -1,134 +1,109 @@
package com.gentics.contentnode.rest.model;
-import java.sql.ResultSet;
-import java.sql.SQLException;
import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class PartType {
- private int id;
- private String name;
- private String description;
- private boolean auto;
- private String javaClass;
- private boolean deprecated;
-
- /**
- * Method to create an instance from a ResultSet
- * @return fluent API
- */
- public PartType buildFromResultSet(ResultSet rs) throws SQLException {
- this.id = rs.getInt("id");
- this.name = rs.getString("name");
- this.description = rs.getString("description");
- this.auto = rs.getBoolean("auto");
- this.javaClass = rs.getString("javaclass");
- this.deprecated = rs.getBoolean("deprecated");
- return this;
- }
-
- /**
- * The name of the part type
- * @return name
- */
- public String getName() {
- return this.name;
- }
-
- /**
- * Set the name of the part type
- * @return fluent API
- */
- public PartType setName(String name) {
- this.name = name;
- return this;
- }
-
- /**
- * Get the id of the part type
- * @return the part type id
- */
- public int getId() {
- return id;
- }
-
-
- /**
- * Set the id of the part type
- * @return fluent API
- */
- public PartType setId(int id) {
- this.id = id;
- return this;
- }
-
- /**
- * Get the description of the part type
- * @return the description of the part type
- */
- public String getDescription() {
- return description;
- }
-
- /**
- * Set the description of the part type
- * @return fluent API
- */
- public PartType setDescription(String description) {
- this.description = description;
- return this;
- }
-
- /**
- * The auto flag
- * @return true if auto is set
- */
- public boolean isAuto() {
- return auto;
- }
-
- /**
- * The auto flag
- * @return fluent API
- */
- public PartType setAuto(boolean auto) {
- this.auto = auto;
- return this;
- }
-
- /**
- * Get the java class (implementation) of the part type
- * @return the implementation class
- */
- public String getJavaClass() {
- return javaClass;
- }
-
- /**
- * Set the java class (implementation) of the part type
- * @return fluent API
- */
- public PartType setJavaClass(String javaClass) {
- this.javaClass = javaClass;
- return this;
- }
-
- /**
- * The deprecation flag
- * @return ture if the part type is deprecated
- */
- public boolean isDeprecated() {
- return deprecated;
- }
-
- /**
- * Set the java class (implementation) of the part type
- * @return fluent API
- */
- public PartType setDeprecated(boolean deprecated) {
- this.deprecated = deprecated;
- return this;
- }
+ private int id;
+ private String name;
+ private String description;
+ private String javaClass;
+ private boolean deprecated;
+
+ /**
+ * The name of the part type
+ *
+ * @return name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Set the name of the part type
+ *
+ * @return fluent API
+ */
+ public PartType setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Get the id of the part type
+ *
+ * @return the part type id
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Set the id of the part type
+ *
+ * @return fluent API
+ */
+ public PartType setId(int id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * Get the description of the part type
+ *
+ * @return the description of the part type
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Set the description of the part type
+ *
+ * @return fluent API
+ */
+ public PartType setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ /**
+ * Get the java class (implementation) of the part type
+ *
+ * @return the implementation class
+ */
+ public String getJavaClass() {
+ return javaClass;
+ }
+
+ /**
+ * Set the java class (implementation) of the part type
+ *
+ * @return fluent API
+ */
+ public PartType setJavaClass(String javaClass) {
+ this.javaClass = javaClass;
+ return this;
+ }
+
+ /**
+ * The deprecation flag
+ *
+ * @return ture if the part type is deprecated
+ */
+ public boolean isDeprecated() {
+ return deprecated;
+ }
+
+ /**
+ * Set the java class (implementation) of the part type
+ *
+ * @return fluent API
+ */
+ public PartType setDeprecated(boolean deprecated) {
+ this.deprecated = deprecated;
+ return this;
+ }
}
\ No newline at end of file
diff --git a/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/request/DiffRequest.java b/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/request/DiffRequest.java
index eb12bd4230..b9bd6bb7c5 100644
--- a/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/request/DiffRequest.java
+++ b/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/request/DiffRequest.java
@@ -11,17 +11,17 @@ public class DiffRequest {
/**
* Default template for changes
*/
- public final static String DEFAULT_CHANGE_TEMPLATE = "$remove$insert ";
+ public final static String DEFAULT_CHANGE_TEMPLATE = "{{{remove}}}{{{insert}}} ";
/**
* Default template for inserts
*/
- public final static String DEFAULT_INSERT_TEMPLATE = "$insert ";
+ public final static String DEFAULT_INSERT_TEMPLATE = "{{{insert}}} ";
/**
* Default template for removals
*/
- public final static String DEFAULT_REMOVE_TEMPALTE = "$remove";
+ public final static String DEFAULT_REMOVE_TEMPALTE = "{{{remove}}}";
/**
* Default number of words before the change to be shown
diff --git a/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/response/PartTypeListResponse.java b/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/response/PartTypeListResponse.java
new file mode 100644
index 0000000000..e63cf6986d
--- /dev/null
+++ b/cms-restapi/src/main/java/com/gentics/contentnode/rest/model/response/PartTypeListResponse.java
@@ -0,0 +1,10 @@
+package com.gentics.contentnode.rest.model.response;
+
+import com.gentics.contentnode.rest.model.PartType;
+
+/**
+ * Response for part type list requests.
+ */
+public class PartTypeListResponse extends AbstractListResponse {
+ private static final long serialVersionUID = -3046448942974030989L;
+}
diff --git a/cms-restapi/src/main/java/com/gentics/contentnode/rest/resource/PartTypeResource.java b/cms-restapi/src/main/java/com/gentics/contentnode/rest/resource/PartTypeResource.java
index 3dd75671f6..310f735861 100644
--- a/cms-restapi/src/main/java/com/gentics/contentnode/rest/resource/PartTypeResource.java
+++ b/cms-restapi/src/main/java/com/gentics/contentnode/rest/resource/PartTypeResource.java
@@ -1,29 +1,33 @@
package com.gentics.contentnode.rest.resource;
-import com.gentics.contentnode.rest.model.PartType;
+import com.gentics.contentnode.rest.model.response.PartTypeListResponse;
import com.gentics.contentnode.rest.resource.parameter.FilterParameterBean;
-import java.util.List;
+import com.gentics.contentnode.rest.resource.parameter.PagingParameterBean;
+import com.gentics.contentnode.rest.resource.parameter.PartTypeListParameterBean;
+import com.gentics.contentnode.rest.resource.parameter.SortParameterBean;
+
import jakarta.ws.rs.BeanParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
-
/**
* Resource for part types
*/
@Path("/parttype")
public interface PartTypeResource {
- /**
- * List Part types
- *
- * @param filter filter parameters
- * @return list of part type
- * @throws Exception in case of errors
- */
- @GET
- List list(
- @BeanParam FilterParameterBean filter) throws Exception;
-
+ /**
+ * List Part types
+ *
+ * @param filter filter parameters
+ * @param sorting sorting parameters
+ * @param paging paging parameters
+ * @param partTypeFilter part type filter parameters
+ * @return list of part type
+ * @throws Exception in case of errors
+ */
+ @GET
+ PartTypeListResponse list(@BeanParam FilterParameterBean filter,
+ @BeanParam SortParameterBean sorting,
+ @BeanParam PagingParameterBean paging, @BeanParam PartTypeListParameterBean partTypeFilter) throws Exception;
}
-
diff --git a/cms-restapi/src/main/java/com/gentics/contentnode/rest/resource/parameter/PartTypeListParameterBean.java b/cms-restapi/src/main/java/com/gentics/contentnode/rest/resource/parameter/PartTypeListParameterBean.java
new file mode 100644
index 0000000000..45b146cd55
--- /dev/null
+++ b/cms-restapi/src/main/java/com/gentics/contentnode/rest/resource/parameter/PartTypeListParameterBean.java
@@ -0,0 +1,14 @@
+package com.gentics.contentnode.rest.resource.parameter;
+
+import jakarta.ws.rs.QueryParam;
+
+/**
+ * Parameter bean for part type list requests
+ */
+public class PartTypeListParameterBean {
+ /**
+ * Flag for filtering deprecated part types
+ */
+ @QueryParam("deprecated")
+ public Boolean deprecated;
+}