diff --git a/celements-xwiki-core/pom.xml b/celements-xwiki-core/pom.xml index 765d89302..70f77ea5b 100644 --- a/celements-xwiki-core/pom.xml +++ b/celements-xwiki-core/pom.xml @@ -76,6 +76,12 @@ 7.0-SNAPSHOT provided + + com.celements + celements-xwiki-rendering-api + 7.0-SNAPSHOT + provided + com.celements celements-servlet @@ -197,15 +203,15 @@ org.xwiki.platform - xwiki-core-script + xwiki-core-xml org.xwiki.platform - xwiki-core-bridge + xwiki-core-script org.xwiki.platform - xwiki-core-rendering-api + xwiki-core-bridge org.xwiki.platform diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/DocumentParser.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/DocumentParser.java index 499ae8fb7..45d04e10b 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/DocumentParser.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/DocumentParser.java @@ -28,7 +28,6 @@ /** * Parse document source content as typed by the user. - * *

* Note: This is a very basic parser which currently only parses wiki links. It should probably * not be developed further. Instead we should migrate to a proper parser such as diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/LinkParser.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/LinkParser.java index 8cc355798..46edc518a 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/LinkParser.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/LinkParser.java @@ -88,7 +88,6 @@ public Link parse(String contentToParse) throws ContentParserException { /** * Find out the alias part of the full link. - * *

* Note: As it's possible to specify a target we need a way to differentiate the following * 2 links: @@ -131,7 +130,6 @@ protected void parseAlias(StringBuffer content, Link link) { /** * Find out the target part of the full link. - * *

* Note: The target element must start with an underscore ("_"). See * {@link #parseAlias(StringBuffer, Link)} for more details as to why. diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/RenamePageReplaceLinkHandler.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/RenamePageReplaceLinkHandler.java index fdba5beca..6b4d718c2 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/RenamePageReplaceLinkHandler.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/content/parsers/RenamePageReplaceLinkHandler.java @@ -30,7 +30,6 @@ public class RenamePageReplaceLinkHandler implements ReplaceLinkHandler { /** * {@inheritDoc} - * *

* Two links are equal if they point to the same document and within the same location * in that document. @@ -74,7 +73,6 @@ public boolean compare(Link linkToLookFor, Link linkToReplace) { /** * {@inheritDoc} - * *

* Keep the query string, alias and target in the link to replace if they are not * specified in the new link. diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/notify/DocObjectChangedRule.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/notify/DocObjectChangedRule.java index 5cd964b0f..b0e2b890a 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/notify/DocObjectChangedRule.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/notify/DocObjectChangedRule.java @@ -56,7 +56,8 @@ public boolean hasEqualsObjectsFromClass(XWikiDocument newdoc, XWikiDocument old } for (int i = 0; i < vobj1.size(); i++) { if (((vobj1.get(i) != null) || (vobj2.get(i) != null))) { - if ((vobj1.get(i) == null) || (vobj2.get(i) == null) || !vobj1.get(i).equals(vobj2.get(i))) { + if ((vobj1.get(i) == null) || (vobj2.get(i) == null) + || !vobj1.get(i).equals(vobj2.get(i))) { return false; } } diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/objects/BaseStringProperty.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/objects/BaseStringProperty.java index b971ddc87..17d3d40ab 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/objects/BaseStringProperty.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/objects/BaseStringProperty.java @@ -23,7 +23,6 @@ /** * Base string XProperty which all types of string XProperties extend. - * * $Id$ */ public class BaseStringProperty extends BaseProperty { diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/objects/ElementComparator.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/objects/ElementComparator.java index c0a0083a4..df2adfd15 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/objects/ElementComparator.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/objects/ElementComparator.java @@ -27,7 +27,6 @@ /** * Compare and sort instances of ElementInterface by name. - * */ public class ElementComparator implements Comparator { diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/fileupload/FileUploadPlugin.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/fileupload/FileUploadPlugin.java index d38f1069a..468a1bc57 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/fileupload/FileUploadPlugin.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/fileupload/FileUploadPlugin.java @@ -110,7 +110,6 @@ public class FileUploadPlugin extends XWikiDefaultPlugin implements XWikiPluginI * the plugin classname (used in logs for example) * @param context * the XWiki Context - * * @see XWikiDefaultPlugin#XWikiDefaultPlugin(String,String,com.xpn.xwiki.XWikiContext) */ public FileUploadPlugin(String name, String className, XWikiContext context) { diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/fileupload/FileUploadPluginApi.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/fileupload/FileUploadPluginApi.java index 082b68f26..5fd9b39bc 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/fileupload/FileUploadPluginApi.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/fileupload/FileUploadPluginApi.java @@ -31,7 +31,6 @@ /** * Plugin that offers access to uploaded files. The uploaded files are automatically parsed and * preserved as a list of {@link org.apache.commons.fileupload.FileItem}s. - * * This is the wrapper accessible from in-document scripts. * * @version $Id$ diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/ldap/XWikiLDAPConnection.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/ldap/XWikiLDAPConnection.java index fe068ba30..f6d49d4f6 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/ldap/XWikiLDAPConnection.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/ldap/XWikiLDAPConnection.java @@ -394,7 +394,6 @@ protected void ldapToXWikiAttribute(List searchAttribu /** * Fully escape DN value (the part after the =). - * *

* For example, for the dn value "Acme, Inc", the escapeLDAPDNValue method * returns "Acme\, Inc". diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/packaging/DocumentInfoAPI.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/packaging/DocumentInfoAPI.java index 5c8d59f81..fb1c4533b 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/packaging/DocumentInfoAPI.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/packaging/DocumentInfoAPI.java @@ -58,7 +58,6 @@ public String getFullName() { /** * @return the language of the described document - * * @since 2.2M1 */ public String getLanguage() { diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/packaging/PackageAPI.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/packaging/PackageAPI.java index 5897dd3a1..6416f91ee 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/packaging/PackageAPI.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/packaging/PackageAPI.java @@ -217,12 +217,10 @@ public String export() throws IOException, XWikiException { * * @param data * the file to create the package from, as a byte array. - * * @return true if the package creation succeeded, false otherwise. If the package creation * failed, * the error message is placed in the velocity context under the import_error * key, - * * @since 2.2M1 */ public boolean importPackageFromByteArray(byte data[]) { @@ -288,7 +286,6 @@ public String toXml() { /** * @return a representation of this package under the JSON format - * * @since 2.2M1 */ public JSONObject toJSON() { diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPlugin.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPlugin.java index 77136b02b..69fc69d52 100755 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPlugin.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPlugin.java @@ -71,7 +71,6 @@ public class ZipExplorerPlugin extends XWikiDefaultPlugin { * the plugin classname (used in logs for example) * @param context * the XWiki Context - * * @see XWikiDefaultPlugin#XWikiDefaultPlugin(String,String,com.xpn.xwiki.XWikiContext) */ public ZipExplorerPlugin(String name, String className, XWikiContext context) { diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPluginAPI.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPluginAPI.java index 60de188b1..890ebbd00 100755 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPluginAPI.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/plugin/zipexplorer/ZipExplorerPluginAPI.java @@ -107,7 +107,6 @@ public List getFileList(Document document, String attachmentName) { * { id = "Directory/", value = "Directory", parent = ""} * { id = "Directory/File.txt", value = "File.txt", parent = "Directory/"} * { id = "File2.txt", value = "File2.txt", parent = ""} - * * * * @param document diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/store/XWikiHibernateBaseStore.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/store/XWikiHibernateBaseStore.java index d0cf6d7a3..01d74d22e 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/store/XWikiHibernateBaseStore.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/store/XWikiHibernateBaseStore.java @@ -101,7 +101,6 @@ public synchronized void initHibernate() throws HibernateException { * * @param context * @return - * * @deprecated since 6.0 instead use {@link #getSession()} */ @Deprecated @@ -126,7 +125,6 @@ public Session getSession() { * * @param session * @param context - * * @deprecated since 6.0 instead use {@link #setSession(Session)} */ @Deprecated @@ -152,7 +150,6 @@ public void setSession(Session session) { * * @param context * @return - * * @deprecated since 6.0 instead use {@link #getTransaction()} */ @Deprecated @@ -172,7 +169,6 @@ public Transaction getTransaction() { * * @param transaction * @param context - * * @deprecated since 6.0 instead use {@link #setTransaction(Transaction)} */ @Deprecated @@ -196,7 +192,6 @@ public void setTransaction(Transaction transaction) { * * @param context * @throws HibernateException - * * @deprecated since 6.0 instead use {@link #updateSchema(String)} */ @Deprecated @@ -220,7 +215,6 @@ public void updateSchema(WikiReference wikiRef) throws HibernateException { * @param force * defines wether or not to force the update despite the xwiki.cfg settings * @throws HibernateException - * * @deprecated since 6.0 instead use {@link #updateSchema(String, boolean)} */ @Deprecated @@ -268,7 +262,6 @@ public synchronized void updateSchema(WikiReference wikiRef, boolean force) * @param context * the XWiki context. * @return the database/schema name. - * * @deprecated since 6.0 instead use {@link #getSchemaFromWikiName(String)} */ @Deprecated @@ -312,7 +305,6 @@ public String getSchemaFromWikiName(WikiReference wikiRef) { * the XWiki context. * @return the database/schema name. * @since XWiki Core 1.1.2, XWiki Core 1.2M2 - * * @deprecated since 6.0 instead use {@link #getSchemaFromWikiName(String)} */ @Deprecated @@ -329,7 +321,6 @@ protected String getSchemaFromWikiName(XWikiContext context) { * @param context * @return * @throws HibernateException - * * @deprecated since 6.0 instead use {@link #getSchemaUpdateScript(Configuration, String)} */ @Deprecated @@ -420,7 +411,6 @@ private void updateSchema(String[] createSQL, WikiReference wikiRef) { * * @param context * @throws HibernateException - * * @deprecated since 6.0 instead use {@link #checkHibernate(String)} */ @Deprecated @@ -432,7 +422,6 @@ public void checkHibernate(XWikiContext context) throws HibernateException { * Initializes hibernate and calls updateSchema if necessary * * @throws HibernateException - * * @deprecated noop, bootstrap ensures hibernate is initialized */ @Deprecated(since = "6.5") @@ -447,7 +436,6 @@ public void checkHibernate() throws HibernateException { * @param context * the XWiki context. * @return true if multi-wiki, false otherwise. - * * @deprecated since 6.0 instead use xwikiCfg.isVirtualMode() */ @Deprecated @@ -461,7 +449,6 @@ protected boolean isVirtual(XWikiContext context) { * @param session * @param context * @throws XWikiException - * * @deprecated since 6.0 instead use {@link #setDatabase(Session, String)} */ @Deprecated @@ -522,7 +509,6 @@ private String getCurrentSchema(Connection connection) { * @param context * the XWiki context to get database engine identifier * @return the escaped version - * * @deprecated since 6.0 instead use {@link #escapeSchema(String)} */ @Deprecated @@ -546,7 +532,6 @@ protected String escapeSchema(String schema) { /** * Begins a transaction for the current database - * */ public boolean beginTransaction() throws HibernateException, XWikiException { try { @@ -564,7 +549,6 @@ public boolean beginTransaction() throws HibernateException, XWikiException { * @param context * @return * @throws XWikiException - * * @Deprecated since 6.0 instead use {@link #beginTransaction(String)} */ @Deprecated @@ -577,7 +561,6 @@ public boolean beginTransaction(XWikiContext context) throws XWikiException { * * @throws HibernateException * @throws XWikiException - * */ public boolean beginTransaction(@Nullable WikiReference wikiRef) throws HibernateException, WikiMissingException, XWikiException { @@ -591,7 +574,6 @@ public boolean beginTransaction(@Nullable WikiReference wikiRef) * @param context * @return * @throws XWikiException - * * @Deprecated since 6.0 instead use {@link #beginTransaction(String)} */ @Deprecated @@ -608,7 +590,6 @@ public boolean beginTransaction(boolean withTransaction, XWikiContext context) * @param context * @return * @throws XWikiException - * * @Deprecated since 6.0 instead use {@link #beginTransaction(SessionFactory, String)} */ @Deprecated @@ -625,7 +606,6 @@ public boolean beginTransaction(SessionFactory sfactory, boolean withTransaction * @return * @throws HibernateException * @throws XWikiException - * * @Deprecated since 6.0 instead use {@link #beginTransaction(SessionFactory, String)} */ @Deprecated @@ -645,7 +625,6 @@ public boolean beginTransaction(SessionFactory sfactory, XWikiContext context) * * @throws HibernateException * @throws XWikiException - * */ public boolean beginTransaction( @Nullable SessionFactory sfactory, @@ -676,7 +655,6 @@ public boolean beginTransaction( * @param context * @param commit * should we commit or not - * * @Deprecated since 6.0 instead use {@link #endTransaction(boolean)} */ @Deprecated @@ -691,7 +669,6 @@ public void endTransaction(XWikiContext context, boolean commit, boolean withTra * @param commit * should we commit or not * @throws HibernateException - * * @Deprecated since 6.0 instead use {@link #endTransaction(boolean)} */ @Deprecated @@ -852,7 +829,6 @@ public interface HibernateCallback { * - callback to execute * @throws XWikiException * if any error - * * @Deprecated since 6.0 instead use {@link #execute(String, boolean, boolean, HibernateCallback)} */ @Deprecated @@ -919,7 +895,6 @@ public T execute(WikiReference wikiRef, boolean bTransaction, boolean doComm * if any error * @see #execute(XWikiContext, boolean, boolean, * com.xpn.xwiki.store.XWikiHibernateBaseStore.HibernateCallback) - * * @Deprecated since 6.0 instead use {@link #executeRead(String, boolean, HibernateCallback)} */ @Deprecated @@ -959,7 +934,6 @@ public T executeRead(WikiReference wikiRef, boolean bTransaction, HibernateC * if any error * @see #execute(XWikiContext, boolean, boolean, * com.xpn.xwiki.store.XWikiHibernateBaseStore.HibernateCallback) - * * @Deprecated since 6.0 instead use {@link #executeWrite(String, boolean, HibernateCallback)} */ @Deprecated diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/store/XWikiStoreInterface.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/store/XWikiStoreInterface.java index 511ce704b..482308fa9 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/store/XWikiStoreInterface.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/store/XWikiStoreInterface.java @@ -557,7 +557,6 @@ void saveLinks(XWikiDocument doc, XWikiContext context, boolean bTransaction) * @return a list of XWikiDocument. * @throws XWikiException * in case of error while performing the query. - * * @deprecated since 6.0, instead use {@link QueryExecutor} */ @Deprecated @@ -588,7 +587,6 @@ void saveLinks(XWikiDocument doc, XWikiContext context, boolean bTransaction) * @throws XWikiException * in case of error while performing the query. * @since XWiki Core 1.1.2, XWiki Core 1.2M2 - * * @deprecated since 6.0, instead use {@link QueryExecutor} */ @Deprecated @@ -613,7 +611,6 @@ List search(String sql, int nb, int start, List parameterValues, XWiki * @return a list of XWikiDocument. * @throws XWikiException * in case of error while performing the query. - * * @deprecated since 6.0, instead use {@link QueryExecutor} */ @Deprecated @@ -649,7 +646,6 @@ List search(String sql, int nb, int start, Object[][] whereParams, XWikiC * @throws XWikiException * in case of error while performing the query. * @since XWiki Core 1.1.2, XWiki Core 1.2M2 - * * @deprecated since 6.0, instead use {@link QueryExecutor} */ @Deprecated @@ -683,7 +679,6 @@ List search(String sql, int nb, int start, Object[][] whereParams, List= 4340). This is because this * current migrator is because the old migrator was only executed in the main wiki, and there was diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/util/XWikiStubContextProvider.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/util/XWikiStubContextProvider.java index ae85a2cd6..fc14a1d59 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/util/XWikiStubContextProvider.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/util/XWikiStubContextProvider.java @@ -11,7 +11,6 @@ * Tool to create a stub XWikiContext. We call it a stub because it doesn't contain actual request * or response data. It's created from scratch on every call to avoid deep cloning or memory * poisoning via uncloned context content. - * */ @ComponentRole public interface XWikiStubContextProvider { diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/SkinAction.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/SkinAction.java index 699d3b11e..684149bdc 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/SkinAction.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/SkinAction.java @@ -134,7 +134,8 @@ public String render(String path, XWikiContext context) throws XWikiException, I // skin document. // Try in the resources directory. if (((!doc.getName().equals(defaultbaseskin) && !baseskin.equals(defaultbaseskin)) - && renderFileFromFilesystem(getSkinFilePath(filename, defaultbaseskin), context)) || renderFileFromFilesystem(getResourceFilePath(filename), context)) { + && renderFileFromFilesystem(getSkinFilePath(filename, defaultbaseskin), context)) + || renderFileFromFilesystem(getResourceFilePath(filename), context)) { found = true; break; } diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/Utils.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/Utils.java index fad6fbc59..e87044796 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/Utils.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/Utils.java @@ -795,7 +795,6 @@ public static Boolean isAjaxRequest(XWikiContext context) { * @param hint * a value to differentiate different component implementations for the same role * @return the component's instance - * * @deprecated instead use {@link #getComponent(Class, String)} */ @Deprecated @@ -814,7 +813,6 @@ public static Object getComponent(String role, String hint) { * @param role * the class (aka role) that the component implements * @return the component's instance - * * @deprecated instead use {@link #getComponent(Class)} */ @Deprecated diff --git a/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiRequestProcessor.java b/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiRequestProcessor.java index 12d0bd410..29879f22a 100644 --- a/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiRequestProcessor.java +++ b/celements-xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiRequestProcessor.java @@ -30,7 +30,6 @@ import org.apache.commons.logging.LogFactory; /** - * * @version $Id$ */ public class XWikiRequestProcessor extends org.apache.struts.action.RequestProcessor { diff --git a/celements-xwiki-core/src/test/java/com/xpn/xwiki/doc/XWikiDocumentTest.java b/celements-xwiki-core/src/test/java/com/xpn/xwiki/doc/XWikiDocumentTest.java index 54d9caa49..705007a49 100644 --- a/celements-xwiki-core/src/test/java/com/xpn/xwiki/doc/XWikiDocumentTest.java +++ b/celements-xwiki-core/src/test/java/com/xpn/xwiki/doc/XWikiDocumentTest.java @@ -206,7 +206,7 @@ public void testGetDisplayWhenTitleExists() { this.document.setTitle("Title"); expect(this.mockXWikiRenderingEngine.interpretText(EasyMock.eq("Title"), EasyMock.isA(XWikiDocument.class), EasyMock.isA(XWikiContext.class))).andReturn("Title") - .once(); + .once(); replayDefaults(); assertEquals("Title", this.document.getDisplayTitle(getContext())); verifyDefaults(); @@ -216,7 +216,7 @@ public void testGetDisplayWhenNoTitleButSectionExists() { this.document.setContent("Some content\n1 Title"); expect(this.mockXWikiRenderingEngine.interpretText(EasyMock.eq("Title"), EasyMock.isA(XWikiDocument.class), EasyMock.isA(XWikiContext.class))).andReturn("Title") - .once(); + .once(); replayDefaults(); assertEquals("Title", this.document.getDisplayTitle(getContext())); verifyDefaults(); @@ -230,8 +230,8 @@ public void testGetDisplayTitleWhenVelocityError() { this.document.setTitle("some content that generate a velocity error"); expect(this.mockXWikiRenderingEngine.interpretText(EasyMock.isA(String.class), EasyMock.isA(XWikiDocument.class), EasyMock.isA(XWikiContext.class))) - .andReturn("... blah blah ...

+ + + + + 4.0.0 + + com.celements + base-pom + 7.0-SNAPSHOT + + celements-xwiki-rendering-api + 7.0-SNAPSHOT + + + com.celements + celements-commons + 7.0-SNAPSHOT + provided + + + com.celements + celements-component + 7.0-SNAPSHOT + provided + + + com.celements + celements-reference + 7.0-SNAPSHOT + provided + + + com.celements + celements-config-source-api + 7.0-SNAPSHOT + provided + + + com.celements + celements-config-source + 7.0-SNAPSHOT + provided + + + com.celements + celements-observation + 7.0-SNAPSHOT + provided + + + com.celements + celements-xwiki-velocity + 7.0-SNAPSHOT + provided + + + com.celements + celements-servlet + 7.0-SNAPSHOT + provided + + + javax.servlet + javax.servlet-api + provided + + + struts + struts + + + + + org.springframework + spring-context + provided + + + org.springframework + spring-web + provided + + + + + commons-configuration + commons-configuration + + + commons-lang + commons-lang + provided + + + + + org.xwiki.platform + xwiki-core-properties + provided + + + org.xwiki.platform + xwiki-core-bridge + provided + + + org.xwiki.platform + xwiki-core-xml + provided + + + org.dom4j + dom4j + + + + + xerces + xercesImpl + provided + + + + + com.celements + celements-base-tests + 7.0-SNAPSHOT + test + + + + org.easymock + easymock + test + + + + + org.xwiki.platform + xwiki-core-shared-tests + test + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + test-jar + + test-jar + + + + **/scaffolding/**.class + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + org/xwiki/rendering/syntax/Syntax.java, + org/xwiki/rendering/syntax/SyntaxType.java, + org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java, + org/xwiki/rendering/renderer/printer/XMLWikiPrinter.java, + org/xwiki/rendering/renderer/printer/VoidWikiPrinter.java, + org/xwiki/rendering/renderer/printer/LookaheadWikiPrinter.java, + org/xwiki/rendering/renderer/printer/WrappingWikiPrinter.java, + org/xwiki/rendering/listener/chaining/LookaheadChainingListener.java, + org/xwiki/rendering/listener/chaining/TextOnNewLineStateChainingListener.java, + org/xwiki/rendering/listener/chaining/EventType.java, + org/xwiki/rendering/listener/chaining/EmptyBlockChainingListener.java, + org/xwiki/rendering/listener/chaining/BlockStateChainingListener.java, + org/xwiki/rendering/listener/chaining/GroupStateChainingListener.java, + org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxMacroRenderer.java, + org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxChainingRenderer.java, + org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxEscapeHandler.java, + org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxImageRenderer.java, + org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxResourceRenderer.java, + org/xwiki/rendering/internal/renderer/plain/PlainTextRenderer.java, + org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRenderer.java, + org/xwiki/rendering/internal/renderer/printer/XHTMLWriter.java, + org/xwiki/rendering/internal/renderer/printer/XWikiSyntaxEscapeWikiPrinter.java, + org/xwiki/rendering/internal/renderer/printer/WikiWriter.java, + org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/link/DefaultXHTMLLinkRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLBlockRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/XHTMLMacroRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/XHTMLBlockRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/image/DefaultXHTMLImageRenderer.java, + org/xwiki/rendering/internal/renderer/xhtml/image/AnnotatedXHTMLImageRenderer.java, + org/xwiki/rendering/internal/renderer/event/EventsChainingRenderer.java, + org/xwiki/rendering/internal/renderer/event/EventRendererFactory.java, + org/xwiki/rendering/internal/renderer/event/EventBlockRenderer.java, + org/xwiki/rendering/internal/parser/XDOMGeneratorListener.java + + + + + + diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractBlock.java new file mode 100644 index 000000000..28b29b5f1 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractBlock.java @@ -0,0 +1,544 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Implementation for Block operations. All blocks should extend this class. Supports the notion of + * generic parameters + * which can be added to a block (see {@link #getParameter(String)} for more details. + * + * @version $Id$ + * @since 1.5M2 + */ +public abstract class AbstractBlock implements Block { + + /** + * Store parameters, see {@link #getParameter(String)} for more explanations on what parameters + * are. + */ + private Map parameters = new LinkedHashMap(); + + /** + * The Blocks this Block contains. + */ + private List childrenBlocks = new ArrayList(); + + /** + * The Block containing this Block. + */ + private Block parentBlock; + + /** + * The next Sibling Block or null if no next sibling exists. + */ + private Block nextSiblingBlock; + + /** + * The previous Sibling Block or null if no previous sibling exists. + */ + private Block previousSiblingBlock; + + /** + * Empty constructor to construct an empty block. + */ + public AbstractBlock() { + // Nothing to do + } + + /** + * Construct a block with parameters. + * + * @param parameters + * the parameters to set + */ + public AbstractBlock(Map parameters) { + this.parameters.putAll(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#addChild(org.xwiki.rendering.block.Block) + */ + public void addChild(Block blockToAdd) { + insertChildAfter(blockToAdd, null); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#addChildren(java.util.List) + */ + public void addChildren(List blocksToAdd) { + for (Block blockToAdd : blocksToAdd) { + addChild(blockToAdd); + } + } + + /** + * {@inheritDoc} + * + * @see Block#setNextSiblingBlock(Block) + * @since 2.6RC1 + */ + public void setNextSiblingBlock(Block nextSiblingBlock) { + this.nextSiblingBlock = nextSiblingBlock; + } + + /** + * {@inheritDoc} + * + * @see Block#setPreviousSiblingBlock(Block) + * @since 2.6RC1 + */ + public void setPreviousSiblingBlock(Block previousSiblingBlock) { + this.previousSiblingBlock = previousSiblingBlock; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#insertChildBefore(org.xwiki.rendering.block.Block, + * org.xwiki.rendering.block.Block) + */ + public void insertChildBefore(Block blockToInsert, Block nextBlock) { + blockToInsert.setParent(this); + + if (nextBlock == null) { + // Last block becomes last but one + if (!this.childrenBlocks.isEmpty()) { + Block lastBlock = this.childrenBlocks.get(this.childrenBlocks.size() - 1); + blockToInsert.setPreviousSiblingBlock(lastBlock); + lastBlock.setNextSiblingBlock(blockToInsert); + } else { + blockToInsert.setPreviousSiblingBlock(null); + } + blockToInsert.setNextSiblingBlock(null); + this.childrenBlocks.add(blockToInsert); + } else { + // If there's a previous block to nextBlock then get it to set its next sibling + Block previousBlock = nextBlock.getPreviousSibling(); + if (previousBlock != null) { + previousBlock.setNextSiblingBlock(blockToInsert); + blockToInsert.setPreviousSiblingBlock(previousBlock); + } else { + blockToInsert.setPreviousSiblingBlock(null); + } + blockToInsert.setNextSiblingBlock(nextBlock); + nextBlock.setPreviousSiblingBlock(blockToInsert); + this.childrenBlocks.add(indexOfChild(nextBlock), blockToInsert); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#insertChildAfter(org.xwiki.rendering.block.Block, + * org.xwiki.rendering.block.Block) + */ + public void insertChildAfter(Block blockToInsert, Block previousBlock) { + if (previousBlock == null) { + insertChildBefore(blockToInsert, null); + } else { + // If there's a next block to previousBlock then get it to set its previous sibling + Block nextBlock = previousBlock.getNextSibling(); + if (nextBlock != null) { + nextBlock.setPreviousSiblingBlock(blockToInsert); + blockToInsert.setNextSiblingBlock(nextBlock); + } else { + blockToInsert.setNextSiblingBlock(null); + } + blockToInsert.setPreviousSiblingBlock(previousBlock); + previousBlock.setNextSiblingBlock(blockToInsert); + this.childrenBlocks.add(indexOfChild(previousBlock) + 1, blockToInsert); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#replaceChild(Block, Block) + */ + public void replaceChild(Block newBlock, Block oldBlock) { + replaceChild(Collections.singletonList(newBlock), oldBlock); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#replaceChild(List, Block) + */ + public void replaceChild(List newBlocks, Block oldBlock) { + int position = indexOfChild(oldBlock); + + if (position == -1) { + throw new InvalidParameterException("Provided Block to replace is not a child"); + } + + List blocks = getChildren(); + + // Remove old child + blocks.remove(position); + oldBlock.setParent(null); + + // Insert new children + Block previousBlock = oldBlock.getPreviousSibling(); + if (newBlocks.isEmpty()) { + previousBlock.setNextSiblingBlock(oldBlock.getNextSibling()); + } + Block lastBlock = null; + for (Block block : newBlocks) { + block.setParent(this); + block.setPreviousSiblingBlock(previousBlock); + if (previousBlock != null) { + previousBlock.setNextSiblingBlock(block); + } + previousBlock = block; + lastBlock = block; + } + Block nextBlock = oldBlock.getNextSibling(); + if (nextBlock != null) { + nextBlock.setPreviousSiblingBlock(lastBlock); + } + if (lastBlock != null) { + lastBlock.setNextSiblingBlock(nextBlock); + } + + blocks.addAll(position, newBlocks); + + oldBlock.setNextSiblingBlock(null); + oldBlock.setPreviousSiblingBlock(null); + } + + /** + * Get the position of the provided block in the list of children. + *

+ * Can't use {@link List#indexOf(Object)} since it's using {@link Object#equals(Object)} + * internally which is not + * what we want since two WordBlock with the same text or two spaces are equals for example but we + * want to be able + * to target one specific Block. + * + * @param block + * the block + * @return the position of the block, -1 if the block can't be found + */ + private int indexOfChild(Block block) { + return indexOfBlock(block, getChildren()); + } + + /** + * Get the position of the provided block in the provided list of blocks. + *

+ * Can't use {@link List#indexOf(Object)} since it's using {@link Object#equals(Object)} + * internally which is not + * what we want since two WordBlock with the same text or two spaces are equals for example but we + * want to be able + * to target one specific Block. + * + * @param block + * the block for which to find the position + * @param blocks + * the list of blocks in which to look for the passed block + * @return the position of the block, -1 if the block can't be found + */ + private int indexOfBlock(Block block, List blocks) { + int position = 0; + + for (Block child : blocks) { + if (child == block) { + return position; + } + ++position; + } + + return -1; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#getChildren() + */ + public List getChildren() { + return this.childrenBlocks; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#getParent() + */ + public Block getParent() { + return this.parentBlock; + } + + /** + * @return all parameters + */ + public Map getParameters() { + return Collections.unmodifiableMap(this.parameters); + } + + /** + * A Parameter is a generic key/value which can be used to add metadata to a block. What is done + * with the metadata + * depends on the Renderer's implementations. For example the XHTML Renderer adds them as Element + * attributes. + * + * @param name + * the name of the parameter to return + * @return the parameter or null if the parameter doesn't exist + */ + public String getParameter(String name) { + return this.parameters.get(name); + } + + /** + * Set a parameter on the current block. See {@link #getParameter(String)} for more details. + * + * @param name + * the parameter's name + * @param value + * the parameter's value + */ + public void setParameter(String name, String value) { + this.parameters.put(name, value); + } + + /** + * Set several parameters at once. + * + * @param parameters + * the parameters to set + * @see #getParameter(String) + * @since 1.7M2 + */ + public void setParameters(Map parameters) { + this.parameters.putAll(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#setParent(org.xwiki.rendering.block.Block) + */ + public void setParent(Block parentBlock) { + this.parentBlock = parentBlock; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#getRoot() + */ + public Block getRoot() { + Block block = this; + + while (block.getParent() != null) { + block = block.getParent(); + } + + return block; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#getChildrenByType(java.lang.Class, boolean) + */ + public List getChildrenByType(Class blockClass, boolean recurse) { + List typedBlocks = new ArrayList(); + for (Block block : getChildren()) { + if (blockClass.isAssignableFrom(block.getClass())) { + typedBlocks.add(blockClass.cast(block)); + } + if (recurse && !block.getChildren().isEmpty()) { + typedBlocks.addAll(block.getChildrenByType(blockClass, true)); + } + } + + return typedBlocks; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#getPreviousBlockByType(java.lang.Class, boolean) + */ + public T getPreviousBlockByType(Class blockClass, boolean recurse) { + if (getParent() == null) { + return null; + } + + int index = indexOfBlock(this, getParent().getChildren()); + + // test previous brothers + List blocks = getParent().getChildren(); + for (int i = index - 1; i >= 0; --i) { + Block previousBlock = blocks.get(i); + if (blockClass.isAssignableFrom(previousBlock.getClass())) { + return blockClass.cast(previousBlock); + } + } + + // test parent + if (blockClass.isAssignableFrom(getParent().getClass())) { + return blockClass.cast(getParent()); + } + + // recurse + return recurse ? getParent().getPreviousBlockByType(blockClass, true) : null; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#getParentBlockByType(java.lang.Class) + */ + public T getParentBlockByType(Class blockClass) { + Block parent = getParent(); + + if (parent == null || blockClass.isAssignableFrom(parent.getClass())) { + return blockClass.cast(parent); + } + + return parent.getParentBlockByType(blockClass); + } + + /** + * {@inheritDoc} + * + * @see Block#getNextSibling() + * @since 2.6RC1 + */ + public Block getNextSibling() { + return this.nextSiblingBlock; + } + + /** + * {@inheritDoc} + * + * @see Block#getPreviousSibling() + * @since 2.6RC1 + */ + public Block getPreviousSibling() { + return this.previousSiblingBlock; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#removeBlock(Block) + * @since 2.6RC1 + */ + public void removeBlock(Block childBlockToRemove) { + getChildren().remove(childBlockToRemove); + if (childBlockToRemove != null) { + Block previousBlock = childBlockToRemove.getPreviousSibling(); + if (previousBlock != null) { + previousBlock.setNextSiblingBlock(childBlockToRemove.getNextSibling()); + } + Block nextBlock = childBlockToRemove.getNextSibling(); + if (nextBlock != null) { + nextBlock.setPreviousSiblingBlock(previousBlock); + } + childBlockToRemove.setNextSiblingBlock(null); + childBlockToRemove.setPreviousSiblingBlock(null); + } + } + + /** + * {@inheritDoc} + * + * @see EqualsBuilder#reflectionEquals(Object, Object) + */ + @Override + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + /** + * {@inheritDoc} + * + * @see HashCodeBuilder#reflectionHashCode(Object) + */ + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#clone() + */ + @Override + public Block clone() { + return clone(null); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#clone(org.xwiki.rendering.block.BlockFilter) + * @since 1.8RC2 + */ + public Block clone(BlockFilter blockFilter) { + Block block; + try { + block = (AbstractBlock) super.clone(); + } catch (CloneNotSupportedException e) { + // Should never happen + throw new RuntimeException("Failed to clone object", e); + } + + ((AbstractBlock) block).parameters = new LinkedHashMap(this.parameters); + + ((AbstractBlock) block).childrenBlocks = new ArrayList(this.childrenBlocks.size()); + for (Block childBlock : this.childrenBlocks) { + if (blockFilter != null) { + Block clonedChildBlocks = childBlock.clone(blockFilter); + + List filteredBlocks = blockFilter.filter(clonedChildBlocks); + + if (filteredBlocks.size() == 0) { + filteredBlocks = clonedChildBlocks.getChildren(); + } + + block.addChildren(filteredBlocks); + } else { + block.addChild(childBlock.clone()); + } + } + + return block; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractFatherBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractFatherBlock.java new file mode 100644 index 000000000..6d37344c6 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/AbstractFatherBlock.java @@ -0,0 +1,73 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * Default implementation for {@link FatherBlock}. + * + * @version $Id$ + * @since 1.5M2 + */ +public abstract class AbstractFatherBlock extends AbstractBlock implements FatherBlock { + + /** + * Constructs a block with children blocks. + * + * @param childrenBlocks + * the list of children blocks of the block to construct + */ + public AbstractFatherBlock(List childrenBlocks) { + this(childrenBlocks, Collections.emptyMap()); + } + + /** + * Construct a block with children blocks and parameters. + * + * @param childrenBlocks + * the list of children blocks of the block to construct + * @param parameters + * the parameters to set + */ + public AbstractFatherBlock(List childrenBlocks, Map parameters) { + super(parameters); + addChildren(childrenBlocks); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener) + */ + public void traverse(Listener listener) { + before(listener); + + for (Block block : getChildren()) { + block.traverse(listener); + } + + after(listener); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/Block.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/Block.java new file mode 100644 index 000000000..9b61cf9d6 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/Block.java @@ -0,0 +1,249 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents an element of a XWiki Document's content. For example there are Blocks for Paragraphs, + * Bold parts, + * Sections, Links, etc. A block has a parent and can have children too for Blocks which are wrapper + * around other blocks + * (e.g. Paragraph blocks, List blocks, Bold blocks). + * + * @version $Id$ + * @since 1.5M2 + */ +public interface Block extends Cloneable { + + /** + * Let the block send {@link Listener} events corresponding to its content. For example a + * Paragraph block will send + * the {@link org.xwiki.rendering.listener.Listener#beginParagraph} and + * {@link org.xwiki.rendering.listener.Listener#endParagraph} events when this method is called. + * + * @param listener + * the listener to which to send the events to. + */ + void traverse(Listener listener); + + /** + * Helper method to add a single child block to the end of the children list of the current block. + * For adding + * several blocks at once use {@link #addChildren(java.util.List)}. + * + * @param blockToAdd + * the child block to add + */ + void addChild(Block blockToAdd); + + /** + * Adds several children blocks to the end of the children list of the current block. For example + * a bold sentence is + * made up of a Bold block to which the different words making up the text have been added to. + * + * @param blocksToAdd + * the children blocks to add + */ + void addChildren(List blocksToAdd); + + /** + * Helper method to add a single child block to the current block before the provided existing + * child block. For + * adding several blocks at once use {@link #addChildren(java.util.List)}. + * + * @param blockToInsert + * the child block to add + * @param nextBlock + * the child block that will be just after the added block + * @since 1.6M1 + */ + void insertChildBefore(Block blockToInsert, Block nextBlock); + + /** + * Helper method to add a single child block to the current block after the provided existing + * child block. For + * adding several blocks at once use {@link #addChildren(java.util.List)}. + * + * @param blockToInsert + * the child block to add + * @param previousBlock + * the child block that will be just before the added block + * @since 1.6M1 + */ + void insertChildAfter(Block blockToInsert, Block previousBlock); + + /** + * Replaces an existing children block with the passed new block. Also sets the new block's parent + * to be the current + * block. + * + * @param newBlock + * the new block to replace the old block with + * @param oldBlock + * the block to replace with the new block + */ + void replaceChild(Block newBlock, Block oldBlock); + + /** + * Replaces an existing children block with the passed new blocks. Also sets the new block's + * parents to be the + * current block. + * + * @param newBlocks + * the new blocks to replace the old block with + * @param oldBlock + * the block to replace with the new blocks + */ + void replaceChild(List newBlocks, Block oldBlock); + + /** + * Get the parent block. All blocks have a parent and the top level parent is the {@link XDOM} + * object. + * + * @return the parent block + */ + Block getParent(); + + /** + * Sets the parent block. + * + * @param parentBlock + * the parent block + */ + void setParent(Block parentBlock); + + /** + * Gets all children blocks. + * + * @return the children blocks + * @see #addChildren(java.util.List) + */ + List getChildren(); + + /** + * Gets the top level Block. If the current block is the top level Block, it return itself. + * + * @return the top level Block + */ + Block getRoot(); + + /** + * Gets all the Blocks in the tree which are of the passed Block class. + * + * @param + * the class of the Blocks to return + * @param blockClass + * the block class to look for + * @param recurse + * if true also search recursively children + * @return all the matching blocks + * @since 1.6M1 + */ + List getChildrenByType(Class blockClass, boolean recurse); + + /** + * Look upward to find a block which inherit or is provided type. + *

+ * The difference with {@link #getParentBlockByType(Class)} is that this one look also at previous + * block in the same + * parent when {@link #getParentBlockByType(Class)} only look at parents. + * + * @param + * the class of the Blocks to return + * @param blockClass + * the block class to look for + * @param recurse + * if true also search in parents levels + * @return the found block, null if nothing is found + * @since 1.6M1 + */ + T getPreviousBlockByType(Class blockClass, boolean recurse); + + /** + * Recursively look at parents to find a block which inherits or is provided type. + *

+ * The difference with {@link #getPreviousBlockByType(Class, boolean)} is that this one only look + * at parent when + * {@link #getPreviousBlockByType(Class, boolean)} look at previous block in the same parent. + * + * @param + * the class of the Blocks to return + * @param blockClass + * the block class to look for + * @return the found block, null if nothing is found + * @since 1.9.1 + */ + T getParentBlockByType(Class blockClass); + + /** + * Removes a Block. + * + * @param childBlockToRemove + * the child block to remove + * @since 2.6RC1 + */ + void removeBlock(Block childBlockToRemove); + + /** + * @return the next sibling block or null if there's no next sibling + * @since 2.6RC1 + */ + Block getNextSibling(); + + /** + * @param nextSiblingBlock + * see {@link #getNextSibling()} + * @since 2.6RC1 + */ + void setNextSiblingBlock(Block nextSiblingBlock); + + /** + * @return the previous sibling block or null if there's no previous sibling + * @since 2.6RC1 + */ + Block getPreviousSibling(); + + /** + * @param previousSiblingBlock + * see {@link #getPreviousSibling()} ()} + * @since 2.6RC1 + */ + void setPreviousSiblingBlock(Block previousSiblingBlock); + + /** + * Return a copy of the block with filtered children. + * + * @param blockFilter + * the Block filter. + * @return the filtered Block. + * @since 1.8RC2 + */ + Block clone(BlockFilter blockFilter); + + /** + * {@inheritDoc} + * + * @see Object#clone() + */ + Block clone(); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BlockFilter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BlockFilter.java new file mode 100644 index 000000000..73289c4e0 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BlockFilter.java @@ -0,0 +1,50 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; + +/** + * Filter provided block into one or more block. + *

+ * The block filter is generally called for each block in a block list and is asked to return a + * filtered version of the + * provided block. This means: + *

    + *
  • an empty list if the block as to be removed
  • + *
  • the block itself in a list if the filter does not have anything particular to filter on + * it
  • + *
  • or even a list of new block to replace the provided block
  • + *
+ * + * @version $Id$ + * @since 1.8RC2 + */ +public interface BlockFilter { + + /** + * Filter provided block into zero or more block. + * + * @param block + * the block to filter. + * @return should never be null. The filtered blocks or empty list. + */ + List filter(Block block); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BulletedListBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BulletedListBlock.java new file mode 100644 index 000000000..317cca90d --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/BulletedListBlock.java @@ -0,0 +1,77 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a Bulleted list. + * + * @version $Id$ + * @since 1.5M2 + */ +public class BulletedListBlock extends AbstractFatherBlock implements ListBLock { + + /** + * Construct a Bulleted List Block with no parameters. + * + * @param childrenBlocks + * the blocks making the list + */ + public BulletedListBlock(List childrenBlocks) { + super(childrenBlocks); + } + + /** + * Construct a Bulleted List Block with parameters. + * + * @param childrenBlocks + * the blocks making the list + * @param parameters + * see {@link org.xwiki.rendering.block.AbstractBlock#getParameter(String)} for more + * details on + * parameters + */ + public BulletedListBlock(List childrenBlocks, Map parameters) { + super(childrenBlocks, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginList(ListType.BULLETED, getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endList(ListType.BULLETED, getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionDescriptionBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionDescriptionBlock.java new file mode 100644 index 000000000..9ad3be305 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionDescriptionBlock.java @@ -0,0 +1,61 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; + +import java.util.List; + +/** + * Represents a definition description. For exampe in HTML this is the equivalent of <dd>. + * + * @version $Id$ + * @since 1.6M2 + */ +public class DefinitionDescriptionBlock extends AbstractFatherBlock { + + /** + * Construct a Definition Description block. + * + * @param childrenBlocks + * the blocks making the description + */ + public DefinitionDescriptionBlock(List childrenBlocks) { + super(childrenBlocks); + } + + /** + * {@inheritDoc} + * + * @see AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endDefinitionDescription(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionListBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionListBlock.java new file mode 100644 index 000000000..1f629c8df --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionListBlock.java @@ -0,0 +1,76 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; + +import java.util.List; +import java.util.Map; + +/** + * Represents a definition list. For example in HTML this is the equivalent of <dl>. + * + * @version $Id$ + * @since 1.6M2 + */ +public class DefinitionListBlock extends AbstractFatherBlock implements ListBLock { + + /** + * Construct a Definition List block with no parameters. + * + * @param childrenBlocks + * the blocks making the Definition list + */ + public DefinitionListBlock(List childrenBlocks) { + super(childrenBlocks); + } + + /** + * Construct a Definition List Block with parameters. + * + * @param childrenBlocks + * the blocks making the Definition list + * @param parameters + * see {@link org.xwiki.rendering.block.AbstractBlock#getParameter(String)} for more + * details on + * parameters + */ + public DefinitionListBlock(List childrenBlocks, Map parameters) { + super(childrenBlocks, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginDefinitionList(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endDefinitionList(getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionTermBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionTermBlock.java new file mode 100644 index 000000000..878cd228e --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/DefinitionTermBlock.java @@ -0,0 +1,61 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; + +import java.util.List; + +/** + * Represents a definition description. For exampe in HTML this is the equivalent of <dt>. + * + * @version $Id$ + * @since 1.6M2 + */ +public class DefinitionTermBlock extends AbstractFatherBlock { + + /** + * Construct a Definition Term block. + * + * @param childrenBlocks + * the blocks making the Definition Term + */ + public DefinitionTermBlock(List childrenBlocks) { + super(childrenBlocks); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endDefinitionTerm(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/EmptyLinesBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/EmptyLinesBlock.java new file mode 100644 index 000000000..c2adedc9e --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/EmptyLinesBlock.java @@ -0,0 +1,70 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents an empty line between 2 standalone Blocks. A standalone block is block that is not + * included in another + * block. Standalone blocks are Paragraph, Standalone Macro, Lists, Table, etc. + * + * @version $Id$ + * @since 1.6M2 + */ +public class EmptyLinesBlock extends AbstractBlock { + + /** + * Number of empty lines between 2 standalone Blocks. + */ + private int count; + + /** + * @param count + * the number of empty lines between 2 standalone Blocks + */ + public EmptyLinesBlock(int count) { + setEmptyLinesCount(count); + } + + /** + * @return the number of empty lines between 2 standalone Blocks + */ + public int getEmptyLinesCount() { + return this.count; + } + + /** + * @param count + * the number of empty lines between 2 standalone Blocks + */ + public void setEmptyLinesCount(int count) { + this.count = count; + } + + /** + * {@inheritDoc} + * + * @see AbstractBlock#traverse(Listener) + */ + public void traverse(Listener listener) { + listener.onEmptyLines(getEmptyLinesCount()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FatherBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FatherBlock.java new file mode 100644 index 000000000..a7335ac17 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FatherBlock.java @@ -0,0 +1,58 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; + +/** + * A type of {@link Block} that has children Blocks. For example the Paragraph Block, the Bold + * Block, the List Block, + * etc. + * + * @version $Id$ + * @since 1.5M2 + */ +public interface FatherBlock extends Block { + + /** + * Send {@link org.xwiki.rendering.listener.Listener} events corresponding to the start of the + * father block. For + * example for a Bold block, this allows an XHTML Listener (aka a Renderer) to output + * <b>. + * + * @param listener + * the listener that will receive the events sent by the father block before the children + * blocks have + * emitted their own events. + */ + void before(Listener listener); + + /** + * Send {@link Listener} events corresponding to the end of the father block. For example for a + * Bold block, this + * allows an XHTML Listener (aka a Renderer) to output </b>. + * + * @param listener + * the listener that will receive the events sent by the father block after the children + * blocks have + * emitted their own events. + */ + void after(Listener listener); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FormatBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FormatBlock.java new file mode 100644 index 000000000..b4552667c --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/FormatBlock.java @@ -0,0 +1,89 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a text formatting block (bold, italic, etc). + * + * @version $Id$ + * @since 1.6M1 + */ +public class FormatBlock extends AbstractFatherBlock { + + /** + * The formatting to apply to the children blocks. + */ + private Format format; + + /** + * @param childrenBlocks + * the nested children blocks + * @param format + * the formatting to apply to the children blocks + */ + public FormatBlock(List childrenBlocks, Format format) { + this(childrenBlocks, format, Collections.emptyMap()); + } + + /** + * @param childrenBlocks + * the nested children blocks + * @param format + * the formatting to apply to the children blocks + * @param parameters + * the custom parameters + */ + public FormatBlock(List childrenBlocks, Format format, Map parameters) { + super(childrenBlocks, parameters); + this.format = format; + } + + /** + * @return the formatting to apply to the children blocks + */ + public Format getFormat() { + return this.format; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginFormat(getFormat(), getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endFormat(getFormat(), getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/GroupBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/GroupBlock.java new file mode 100644 index 000000000..0e1a1b7ee --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/GroupBlock.java @@ -0,0 +1,92 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a grouping of blocks. + * + * @version $Id$ + * @since 1.8.3 + */ +public class GroupBlock extends AbstractFatherBlock { + + /** + * Create an empty group block with no children. This is useful when the user wants to call + * {@link #addChild(Block)} + * manually for adding children one by one after the block is constructed. + */ + public GroupBlock() { + this(Collections.emptyList()); + } + + /** + * Create an empty group block with no children. This is useful when the user wants to call + * {@link #addChild(Block)} + * manually for adding children one by one after the block is constructed. + * + * @param parameters + * the parameters of the group + */ + public GroupBlock(Map parameters) { + this(Collections.emptyList(), parameters); + } + + /** + * @param blocks + * the children blocks of the group + */ + public GroupBlock(List blocks) { + super(blocks); + } + + /** + * @param blocks + * the children blocks of the group + * @param parameters + * the parameters of the group + */ + public GroupBlock(List blocks, Map parameters) { + super(blocks, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginGroup(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endGroup(getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HeaderBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HeaderBlock.java new file mode 100644 index 000000000..f5f645765 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HeaderBlock.java @@ -0,0 +1,139 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; +import org.xwiki.rendering.listener.HeaderLevel; + +/** + * @version $Id$ + * @since 1.5M2 + */ +public class HeaderBlock extends AbstractFatherBlock { + + /** + * The level of the header. + */ + private HeaderLevel level; + + /** + * The id of the header. + */ + private String id; + + /** + * @param childBlocks + * the children of the header. + * @param level + * the level of the header + */ + public HeaderBlock(List childBlocks, HeaderLevel level) { + super(childBlocks); + + this.level = level; + } + + /** + * @param childBlocks + * the children of the header. + * @param level + * the level of the header + * @param parameters + * the parameters of the header + */ + public HeaderBlock(List childBlocks, HeaderLevel level, Map parameters) { + super(childBlocks, parameters); + + this.level = level; + } + + /** + * @param childBlocks + * the children of the header. + * @param level + * the level of the header + * @param id + * the id of the header. + */ + public HeaderBlock(List childBlocks, HeaderLevel level, String id) { + this(childBlocks, level); + + this.id = id; + } + + /** + * @param childBlocks + * the children of the header. + * @param level + * the level of the header + * @param parameters + * the parameters of the header + * @param id + * the id of the header. + */ + public HeaderBlock(List childBlocks, HeaderLevel level, Map parameters, + String id) { + this(childBlocks, level, parameters); + + this.id = id; + } + + /** + * @return the level of the header + */ + public HeaderLevel getLevel() { + return this.level; + } + + /** + * @return the id of the header. + */ + public String getId() { + return this.id; + } + + /** + * @return the {@link SectionBlock} corresponding to this header + */ + public SectionBlock getSection() { + return (SectionBlock) getParent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginHeader(getLevel(), getId(), getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endHeader(getLevel(), getId(), getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HorizontalLineBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HorizontalLineBlock.java new file mode 100644 index 000000000..a71e8004a --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/HorizontalLineBlock.java @@ -0,0 +1,61 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a Horizontal line. + * + * @version $Id$ + * @since 1.6M1 + */ +public class HorizontalLineBlock extends AbstractBlock { + + /** + * Construct a Horizontal Line Block with no parameters. + */ + public HorizontalLineBlock() { + super(); + } + + /** + * Construct a Horizontal Line Block with parameters. + * + * @param parameters + * see {@link org.xwiki.rendering.block.AbstractBlock#getParameter(String)} for more + * details on + * parameters + */ + public HorizontalLineBlock(Map parameters) { + super(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener) + */ + public void traverse(Listener listener) { + listener.onHorizontalLine(getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/IdBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/IdBlock.java new file mode 100644 index 000000000..11a11d766 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/IdBlock.java @@ -0,0 +1,63 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; + +/** + * A reference/location in a page. In HTML for example this is called an Anchor. It allows pointing + * to that location, + * for example in links. + * + * @version $Id$ + * @since 1.6M1 + * @see Listener#onId(String) + */ +public class IdBlock extends AbstractBlock { + + /** + * The unique name for the reference/location. + */ + private String name; + + /** + * @param name + * the unique name for the reference/location. + */ + public IdBlock(String name) { + this.name = name; + } + + /** + * @return the reference/location name + */ + public String getName() { + return this.name; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener) + */ + public void traverse(Listener listener) { + listener.onId(getName()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ImageBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ImageBlock.java new file mode 100644 index 000000000..4cce9af65 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ImageBlock.java @@ -0,0 +1,116 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.Collections; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Represents an image. + * + * @version $Id$ + * @since 1.7M2 + */ +public class ImageBlock extends AbstractBlock { + + /** + * A reference to the image target. See + * {@link org.xwiki.rendering.listener.reference.ResourceReference} for more + * details. + */ + private ResourceReference reference; + + /** + * If true then the image is defined as a free standing URI directly in the text. + */ + private boolean isFreeStandingURI; + + /** + * @param reference + * the image reference + * @param isFreeStandingURI + * indicate if the image syntax is simple a full descriptive syntax (detail depending of + * the syntax) + * @since 2.5RC1 + */ + public ImageBlock(ResourceReference reference, boolean isFreeStandingURI) { + this(reference, isFreeStandingURI, Collections.emptyMap()); + } + + /** + * @param reference + * the image reference + * @param isFreeStandingURI + * indicate if the image syntax is simple a full descriptive syntax (detail depending of + * the syntax) + * @param parameters + * the custom parameters + * @since 2.5RC1 + */ + public ImageBlock(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + super(parameters); + + this.reference = reference; + this.isFreeStandingURI = isFreeStandingURI; + } + + /** + * @return the reference to the image + * @see org.xwiki.rendering.listener.reference.ResourceReference + * @since 2.5RC1 + */ + public ResourceReference getReference() { + return this.reference; + } + + /** + * @return true if the image is defined as a free standing URI directly in the text, false + * otherwise + */ + public boolean isFreeStandingURI() { + return this.isFreeStandingURI; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#traverse(org.xwiki.rendering.listener.Listener) + */ + public void traverse(Listener listener) { + listener.onImage(getReference(), isFreeStandingURI(), getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractBlock#clone(org.xwiki.rendering.block.BlockFilter) + * @since 1.8RC2 + */ + @Override + public ImageBlock clone(BlockFilter blockFilter) { + ImageBlock clone = (ImageBlock) super.clone(blockFilter); + clone.reference = getReference().clone(); + return clone; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/LinkBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/LinkBlock.java new file mode 100644 index 000000000..d1ed1885c --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/LinkBlock.java @@ -0,0 +1,128 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Represents a Link element in a page. + * + * @version $Id$ + * @since 1.5M2 + */ +public class LinkBlock extends AbstractFatherBlock { + + /** + * A reference to the link target. See + * {@link org.xwiki.rendering.listener.reference.ResourceReference} for more + * details. + */ + private ResourceReference reference; + + /** + * If true then the link is a free standing URI directly in the text. + */ + private boolean isFreeStandingURI; + + /** + * @param childrenBlocks + * the nested children blocks + * @param reference + * the reference to the target resource to link to + * @param isFreeStandingURI + * if true then the link is a free standing URI directly in the text + * @since 2.5RC1 + */ + public LinkBlock(List childrenBlocks, ResourceReference reference, + boolean isFreeStandingURI) { + this(childrenBlocks, reference, isFreeStandingURI, Collections.emptyMap()); + } + + /** + * @param childrenBlocks + * the nested children blocks + * @param reference + * the reference to the target resource to link to + * @param isFreeStandingURI + * if true then the link is a free standing URI directly in the text + * @param parameters + * the parameters to set + * @since 2.5RC1 + */ + public LinkBlock(List childrenBlocks, ResourceReference reference, + boolean isFreeStandingURI, + Map parameters) { + super(childrenBlocks, parameters); + this.reference = reference; + this.isFreeStandingURI = isFreeStandingURI; + } + + /** + * @return the reference to the target to link to + * @see org.xwiki.rendering.listener.reference.ResourceReference + * @since 2.5RC1 + */ + public ResourceReference getReference() { + return this.reference; + } + + /** + * @return true if the link is a free standing URI directly in the text, false otherwise + */ + public boolean isFreeStandingURI() { + return this.isFreeStandingURI; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginLink(getReference(), isFreeStandingURI(), getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endLink(getReference(), isFreeStandingURI(), getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractBlock#clone(org.xwiki.rendering.block.BlockFilter) + * @since 1.8RC2 + */ + @Override + public LinkBlock clone(BlockFilter blockFilter) { + LinkBlock clone = (LinkBlock) super.clone(blockFilter); + clone.reference = getReference().clone(); + return clone; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListBLock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListBLock.java new file mode 100644 index 000000000..45fd88828 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListBLock.java @@ -0,0 +1,30 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +/** + * Represents any type of Lists (numbered list, bulleted list, etc). + * + * @version $Id$ + * @since 1.5M2 + */ +public interface ListBLock extends Block { + // This is currently only a tagging interface and thus it has no methods. +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListItemBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListItemBlock.java new file mode 100644 index 000000000..7b8bdbde4 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ListItemBlock.java @@ -0,0 +1,61 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a List item element in a page. + * + * @version $Id$ + * @since 1.5M2 + */ +public class ListItemBlock extends AbstractFatherBlock { + + /** + * Constructs a list item Block. + * + * @param childrenBlocks + * the blocks representing the list item content + */ + public ListItemBlock(List childrenBlocks) { + super(childrenBlocks); + } + + /** + * {@inheritDoc} + * + * @see AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginListItem(); + } + + /** + * {@inheritDoc} + * + * @see AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endListItem(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroBlock.java new file mode 100644 index 000000000..59e07642c --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroBlock.java @@ -0,0 +1,128 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a Macro (standalone or inline) defined in a page. + *

+ * Note: You can get macro parameters using {@link #getParameters()} for example. Macro block is + * reusing Block standard + * custom parameters API since macro by definition already have parameters and don't need also block + * parameters. So in + * this case MacroBlock parameters and Block parameters are the same thing. + * + * @version $Id$ + * @since 1.8M2 + */ +public class MacroBlock extends AbstractBlock { + + /** + * @see #getId + */ + private String id; + + /** + * The macro content for macro that have content. Otherwise it's null. + */ + private String content; + + /** + * The macro is located in a inline content (like paragraph, etc.). + */ + private boolean isInline; + + /** + * @param id + * the id of the macro + * @param parameters + * the parameters of the macro + * @param isInline + * indicate if the macro is located in a inline content (like paragraph, etc.) + */ + public MacroBlock(String id, Map parameters, boolean isInline) { + this(id, parameters, null, isInline); + } + + /** + * @param id + * the id of the macro + * @param parameters + * the parameters of the macro + * @param content + * the content of the macro. Null if the macro does not have content + * @param isInline + * indicate if the macro is located in a inline content (like paragraph, etc.) + */ + public MacroBlock(String id, Map parameters, String content, boolean isInline) { + super(parameters); + + this.id = id; + this.content = content; + this.isInline = isInline; + } + + /** + * @return the macro id (eg "toc" for the TOC Macro). + * @since 2.0M3 + */ + public String getId() { + return this.id; + } + + /** + * @return the macro content. + */ + public String getContent() { + return this.content; + } + + /** + * @return if true the macro is located in a inline content (like paragraph, etc.). + */ + public boolean isInline() { + return this.isInline; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener) + */ + public void traverse(Listener listener) { + // Don't do anything here since we want the Macro Transformer component to take in charge + // Macro execution. This is because Macro execution is a complex process that involves: + // * computing the order in which the macros should be evaluated. For example the TOC macro + // should evaluate last since other macros can contribute headers/sections blocks. + // * some macros need to modify blocks in the XDOM object + // * macro execution is a multi-pass process + // In essence the Macro Transformer will replace all MacroBlock blocks with other Blocks + // generated from the execution of the Macros when XDOM.traverse() is called there + // won't be any MacroBlock.traverse() method called at all. + + // Note: We're calling the event to let other listener downstream decide what to do with it. + // In practice as described above this method will never get called when the whole rendering + // process is executed. This does get called during our unit tests though. + listener.onMacro(getId(), getParameters(), getContent(), isInline()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroMarkerBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroMarkerBlock.java new file mode 100644 index 000000000..6bbe586d3 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/MacroMarkerBlock.java @@ -0,0 +1,139 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * A special block that Macro Blocks generate when they are executed so that it's possible to + * reconstruct the initial + * syntax even after Macros have been executed. For example this is important in a WYSWIYG editor + * where you want to show + * the Macro's rendered result and also let users modify the macro content. + * + * @version $Id$ + * @since 1.5M2 + */ +public class MacroMarkerBlock extends AbstractFatherBlock { + + /** + * The macro name that we are preserving. + */ + private String id; + + /** + * The macro content that we are preserving. + */ + private String content; + + /** + * The macro is located in a inline content (like paragraph, etc.). + */ + private boolean isInline; + + /** + * @param id + * the name of the macro + * @param parameters + * the parameters of the macro + * @param childBlocks + * the list of children blocks generated by the macro + * @param isInline + * indicate if the macro is located in a inline content (like paragraph, etc.) + */ + public MacroMarkerBlock(String id, Map parameters, List childBlocks, + boolean isInline) { + this(id, parameters, null, childBlocks, isInline); + } + + /** + * @param id + * the name of the macro + * @param parameters + * the parameters of the macro + * @param content + * the content of the macro. Null if the macro does not have content + * @param childBlocks + * the list of children blocks generated by the macro + * @param isInline + * indicate if the macro is located in a inline content (like paragraph, etc.) + */ + public MacroMarkerBlock(String id, Map parameters, String content, + List childBlocks, + boolean isInline) { + super(childBlocks, parameters); + + this.id = id; + this.content = content; + this.isInline = isInline; + } + + /** + * @return the macro name. + * @deprecated since 2.4M1 use {@link #getId()} instead + */ + @Deprecated + public String getName() { + return getId(); + } + + /** + * @return the macro identifier. + * @since 2.4M1 + */ + public String getId() { + return this.id; + } + + /** + * @return the macro content. + */ + public String getContent() { + return this.content; + } + + /** + * @return if true the macro is located in a inline content (like paragraph, etc.). + */ + public boolean isInline() { + return this.isInline; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginMacroMarker(getName(), getParameters(), getContent(), isInline()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endMacroMarker(getName(), getParameters(), getContent(), isInline()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NewLineBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NewLineBlock.java new file mode 100644 index 000000000..f826f88d0 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NewLineBlock.java @@ -0,0 +1,55 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a new line or line break (it's up to the Renderers to decide if it should be outputted + * as a new line or as + * a line break in the given syntax). + * + * @version $Id$ + * @since 1.5M2 + */ +public final class NewLineBlock extends AbstractBlock { + + /** + * A new line block. Note that we don't make NewLineBlock a singleton since that would cause + * problems when using + * Block APIs to manipulate a tree of blocks (for example to find the position of a new line block + * in a list using + * {@link java.util.List#indexOf(Object)} wich would always return the first new line block). + * + * @since 2.6RC1 + */ + public NewLineBlock() { + // We need to keep this constructor to override the ones in AbstractBlock + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener) + */ + public void traverse(Listener listener) { + listener.onNewLine(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NumberedListBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NumberedListBlock.java new file mode 100644 index 000000000..04d954363 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/NumberedListBlock.java @@ -0,0 +1,77 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a numbered List. + * + * @version $Id$ + * @since 1.5M2 + */ +public class NumberedListBlock extends AbstractFatherBlock implements ListBLock { + + /** + * Construct a Numbered List Block with no parameters. + * + * @param childrenBlocks + * the blocks making the list + */ + public NumberedListBlock(List childrenBlocks) { + super(childrenBlocks); + } + + /** + * Construct a Numbered List Block with parameters. + * + * @param childrenBlocks + * the blocks making the list + * @param parameters + * see {@link org.xwiki.rendering.block.AbstractBlock#getParameter(String)} for more + * details on + * parameters + */ + public NumberedListBlock(List childrenBlocks, Map parameters) { + super(childrenBlocks, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginList(ListType.NUMBERED, getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endList(ListType.NUMBERED, getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ParagraphBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ParagraphBlock.java new file mode 100644 index 000000000..b40eaa611 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/ParagraphBlock.java @@ -0,0 +1,68 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * @version $Id$ + * @since 1.5M2 + */ +public class ParagraphBlock extends AbstractFatherBlock { + + /** + * @param blocks + * the children blocks of the paragraph + */ + public ParagraphBlock(List blocks) { + super(blocks); + } + + /** + * @param blocks + * the children blocks of the paragraph + * @param parameters + * the parameters of the paragraph + */ + public ParagraphBlock(List blocks, Map parameters) { + super(blocks, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginParagraph(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endParagraph(getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/PlainTextBlockFilter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/PlainTextBlockFilter.java new file mode 100644 index 000000000..852eebc41 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/PlainTextBlockFilter.java @@ -0,0 +1,110 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.io.StringReader; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; +import org.xwiki.rendering.parser.ParseException; +import org.xwiki.rendering.parser.Parser; +import org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator; + +/** + * Used to filter plain text blocks. + * + * @version $Id$ + * @since 1.9M1 + */ +public class PlainTextBlockFilter implements BlockFilter { + + /** + * The set of valid Block classes as toc item content. + */ + private static final Set> VALID_PLAINTEXT_BLOCKS = new HashSet>() { + + { + add(WordBlock.class); + add(SpaceBlock.class); + add(SpecialSymbolBlock.class); + add(NewLineBlock.class); + } + }; + + /** + * A parser that knows how to parse plain text; this is used to transform link labels into plain + * text. + */ + private Parser plainTextParser; + + /** + * Generate link label. + */ + private LinkLabelGenerator linkLabelGenerator; + + /** + * @param plainTextParser + * a plain text parser used to transform link labels into plain text + * @param linkLabelGenerator + * generate link label. + * @since 2.0M3 + */ + public PlainTextBlockFilter(Parser plainTextParser, LinkLabelGenerator linkLabelGenerator) { + this.plainTextParser = plainTextParser; + this.linkLabelGenerator = linkLabelGenerator; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.BlockFilter#filter(org.xwiki.rendering.block.Block) + */ + public List filter(Block block) { + if (VALID_PLAINTEXT_BLOCKS.contains(block.getClass())) { + return Collections.singletonList(block); + } else if (block.getClass() == LinkBlock.class && block.getChildren().size() == 0) { + ResourceReference reference = ((LinkBlock) block).getReference(); + + try { + String label; + + if (reference.getType().equals(ResourceType.DOCUMENT)) { + label = this.linkLabelGenerator.generate(reference); + } else { + label = reference.getReference(); + } + + return this.plainTextParser.parse(new StringReader(label)).getChildren().get(0) + .getChildren(); + } catch (ParseException e) { + // This shouldn't happen since the parser cannot throw an exception since the source is a + // memory + // String. + throw new RuntimeException("Failed to parse link label as plain text", e); + } + } else { + return Collections.emptyList(); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationBlock.java new file mode 100644 index 000000000..b6111659d --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationBlock.java @@ -0,0 +1,71 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a quotation. There are one or several quotation lines inside a quotation block. + * + * @version $Id$ + * @since 1.6M2 + */ +public class QuotationBlock extends AbstractFatherBlock { + + /** + * @param blocks + * the children of the quotation + */ + public QuotationBlock(List blocks) { + super(blocks, Collections.emptyMap()); + } + + /** + * @param blocks + * the children of the quotation + * @param parameters + * the parameters of the quotation + */ + public QuotationBlock(List blocks, Map parameters) { + super(blocks, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginQuotation(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endQuotation(getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationLineBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationLineBlock.java new file mode 100644 index 000000000..df20ff420 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/QuotationLineBlock.java @@ -0,0 +1,59 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a quotation line. There can be several quotation lines in a quotation block. + * + * @version $Id$ + * @since 1.6M2 + */ +public class QuotationLineBlock extends AbstractFatherBlock { + + /** + * @param blocks + * the children of the quotation line + */ + public QuotationLineBlock(List blocks) { + super(blocks); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endQuotationLine(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/RawBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/RawBlock.java new file mode 100644 index 000000000..f94f7cad8 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/RawBlock.java @@ -0,0 +1,80 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Represents some raw content that shouldn't be parsed or modified and that should be injected as + * is in any output. The + * content depends on a syntax and listeners decide if they can handle that syntax or not. For + * example if it's in + * "xhtml/1.0" syntax then the XHTML Renderer can insert it directly in the XHTML output. + * + * @version $Id$ + * @since 1.8.3 + */ +public class RawBlock extends AbstractBlock { + + /** + * @see #getRawContent() + */ + private String rawContent; + + /** + * @see #getSyntax() + */ + private Syntax syntax; + + /** + * @param rawContent + * the content to inject as is into the listener (it won't be modified) + * @param syntax + * the syntax in which the content is written + */ + public RawBlock(String rawContent, Syntax syntax) { + this.rawContent = rawContent; + this.syntax = syntax; + } + + /** + * {@inheritDoc} + * + * @see AbstractBlock#traverse(Listener) + */ + public void traverse(Listener listener) { + listener.onRawText(getRawContent(), getSyntax()); + } + + /** + * @return the content to inject as is into the listener (it won't be modified) + */ + public String getRawContent() { + return this.rawContent; + } + + /** + * @return the syntax in which the content is written + */ + public Syntax getSyntax() { + return this.syntax; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SectionBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SectionBlock.java new file mode 100644 index 000000000..20f1346a3 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SectionBlock.java @@ -0,0 +1,86 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * @version $Id$ + * @since 1.5M2 + */ +public class SectionBlock extends AbstractFatherBlock { + + /** + * @param childBlocks + * the children of the section + */ + public SectionBlock(List childBlocks) { + super(childBlocks); + } + + /** + * @param childBlocks + * the children of the section + * @param parameters + * the parameters of the section + */ + public SectionBlock(List childBlocks, Map parameters) { + super(childBlocks, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginSection(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endSection(getParameters()); + } + + /** + * @return the title block of the section. + */ + public HeaderBlock getHeaderBlock() { + HeaderBlock headerBlock = null; + + List children = getChildren(); + + if (children.size() > 0) { + Block firstChild = children.get(0); + if (firstChild instanceof HeaderBlock) { + headerBlock = (HeaderBlock) firstChild; + } + } + + return headerBlock; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpaceBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpaceBlock.java new file mode 100644 index 000000000..051bde552 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpaceBlock.java @@ -0,0 +1,63 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a space. + * + * @version $Id$ + * @since 1.5M2 + */ +public final class SpaceBlock extends AbstractBlock { + + /** + * A space block. Note that we don't make SpaceBlock a singleton since that would cause problems + * when using Block + * APIs to manipulate a tree of blocks (for example to find the position of a space block in a + * list using + * {@link java.util.List#indexOf(Object)} wich would always return the first space block). + * + * @since 2.6RC1 + */ + public SpaceBlock() { + // We need to keep this constructor to override the ones in AbstractBlock + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#traverse(org.xwiki.rendering.listener.Listener) + */ + public void traverse(Listener listener) { + listener.onSpace(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractBlock#clone() + */ + @Override + public Block clone() { + return this; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpecialSymbolBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpecialSymbolBlock.java new file mode 100644 index 000000000..128b53d2d --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/SpecialSymbolBlock.java @@ -0,0 +1,71 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represent a non-alphanumeric and non-space symbol (>, ]...). + * + * @version $Id$ + * @since 1.5M2 + */ +public class SpecialSymbolBlock extends AbstractBlock { + + /** + * The symbol. + */ + private char symbol; + + /** + * @param symbol + * the symbol + */ + public SpecialSymbolBlock(char symbol) { + this.symbol = symbol; + } + + /** + * @return the symbol + */ + public char getSymbol() { + return this.symbol; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.Block#traverse(org.xwiki.rendering.listener.Listener) + */ + public void traverse(Listener listener) { + listener.onSpecialSymbol(getSymbol()); + } + + /** + * {@inheritDoc} + * + * @see java.lang.Object#toString() + * @since 1.8RC2 + */ + @Override + public String toString() { + return String.valueOf(getSymbol()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableBlock.java new file mode 100644 index 000000000..ef09b7653 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableBlock.java @@ -0,0 +1,63 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a table. + * + * @version $Id$ + * @since 1.6M2 + */ +public class TableBlock extends AbstractFatherBlock { + + /** + * @param list + * the list of children blocks of the table block (generally a list of + * {@link TableRowBlock}). + * @param parameters + * the parameters of the table. + */ + public TableBlock(List list, Map parameters) { + super(list, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginTable(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endTable(getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableCellBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableCellBlock.java new file mode 100644 index 000000000..9526c05e6 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableCellBlock.java @@ -0,0 +1,62 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a cell of a table. + * + * @version $Id$ + * @since 1.6M2 + */ +public class TableCellBlock extends AbstractFatherBlock { + + /** + * @param list + * the list of children blocks of the table head cell block. + * @param parameters + * the parameters of the table row. + */ + public TableCellBlock(List list, Map parameters) { + super(list, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginTableCell(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endTableCell(getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableHeadCellBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableHeadCellBlock.java new file mode 100644 index 000000000..62bbe628a --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableHeadCellBlock.java @@ -0,0 +1,64 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a head of a row or column of a table. + * + * @version $Id$ + * @since 1.6M2 + */ +public class TableHeadCellBlock extends TableCellBlock { + + /** + * @param list + * the list of children blocks of the table cell block. + * @param parameters + * the parameters of the table head cell. + */ + public TableHeadCellBlock(List list, Map parameters) { + super(list, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.TableCellBlock#before(org.xwiki.rendering.listener.Listener) + */ + @Override + public void before(Listener listener) { + listener.beginTableHeadCell(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.TableCellBlock#after(org.xwiki.rendering.listener.Listener) + */ + @Override + public void after(Listener listener) { + listener.endTableHeadCell(getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableRowBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableRowBlock.java new file mode 100644 index 000000000..c7ac7b99f --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/TableRowBlock.java @@ -0,0 +1,63 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents the row of a table. Contains {@link TableCellBlock} objects. + * + * @version $Id$ + * @since 1.6M2 + */ +public class TableRowBlock extends AbstractFatherBlock { + + /** + * @param list + * the list of children blocks of the table row block (generally a list of + * {@link TableCellBlock}). + * @param parameters + * the parameters of the table row. + */ + public TableRowBlock(List list, Map parameters) { + super(list, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginTableRow(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.FatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endTableRow(getParameters()); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/VerbatimBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/VerbatimBlock.java new file mode 100644 index 000000000..c0fcde9d2 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/VerbatimBlock.java @@ -0,0 +1,103 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.util.Map; + +import org.xwiki.rendering.listener.Listener; + +/** + * A Verbatim block. + * + * @version $Id$ + * @since 1.8M2 + */ +public class VerbatimBlock extends AbstractBlock { + + /** + * The string to protect from rendering. + */ + private String protectedString; + + /** + * If true the macro is located in a inline content (like paragraph, etc.). + */ + private boolean isInline; + + /** + * @param protectedString + * the string to protect from rendering. + * @param isInline + * if true the macro is located in a inline content (like paragraph, etc.). + */ + public VerbatimBlock(String protectedString, boolean isInline) { + this.protectedString = protectedString; + this.isInline = isInline; + } + + /** + * @param protectedString + * the string to protect from rendering. + * @param parameters + * the custom parameters + * @param isInline + * if true the macro is located in a inline content (like paragraph, etc.). + */ + public VerbatimBlock(String protectedString, Map parameters, boolean isInline) { + super(parameters); + + this.protectedString = protectedString; + this.isInline = isInline; + } + + /** + * @return the string to protect from rendering + */ + public String getProtectedString() { + return this.protectedString; + } + + /** + * @return if true the macro is located in a inline content (like paragraph, etc.). + */ + public boolean isInline() { + return this.isInline; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractBlock#traverse(org.xwiki.rendering.listener.Listener) + */ + public void traverse(Listener listener) { + listener.onVerbatim(getProtectedString(), isInline(), getParameters()); + } + + /** + * {@inheritDoc} + * + * @see java.lang.Object#toString() + * @since 1.8RC2 + */ + @Override + public String toString() { + return getProtectedString(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/WordBlock.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/WordBlock.java new file mode 100644 index 000000000..f4baf4454 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/WordBlock.java @@ -0,0 +1,73 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; + +/** + * Represents a word. + * + * @version $Id$ + * @since 1.5M2 + */ +public class WordBlock extends AbstractBlock { + + /** + * @see #getWord() + */ + private String word; + + /** + * @param word + * the word wrapped by this block. Note that this is supposed to be a single word and + * space or special + * symbols should be represented by other blocks + */ + public WordBlock(String word) { + this.word = word; + } + + /** + * {@inheritDoc} + * + * @see AbstractBlock#traverse(Listener) + */ + public void traverse(Listener listener) { + listener.onWord(getWord()); + } + + /** + * @return the word wrapped by this block + */ + public String getWord() { + return this.word; + } + + /** + * {@inheritDoc} + * + * @see java.lang.Object#toString() + * @since 1.8RC2 + */ + @Override + public String toString() { + return getWord(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/XDOM.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/XDOM.java new file mode 100644 index 000000000..b4a89712e --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/block/XDOM.java @@ -0,0 +1,132 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import org.xwiki.rendering.listener.Listener; +import org.xwiki.rendering.util.IdGenerator; + +import java.util.List; +import java.util.Collections; +import java.util.Map; + +/** + * Contains the full tree of {@link Block} that represent a XWiki Document's content. + * + * @version $Id$ + * @since 1.5M2 + */ +public class XDOM extends AbstractFatherBlock { + + /** + * Constructs an empty XDOM. Useful for example when calling a macro that doesn't use the XDOM + * parameter passed to + * it. + */ + public static final XDOM EMPTY = new XDOM(Collections.emptyList()); + + /** + * Stateful id generator for this document. We store it in the XDOM because it is the only object + * which remains the + * same between parsing, transformation and rendering, and we need to generate ids during parsing + * and during + * transformation. + */ + private IdGenerator idGenerator; + + /** + * @param childBlocks + * the list of children blocks of the block to construct + * @param parameters + * the parameters to set + * @see AbstractFatherBlock#AbstractFatherBlock(List) + */ + public XDOM(List childBlocks, Map parameters) { + super(childBlocks, parameters); + + this.idGenerator = new IdGenerator(); + } + + /** + * @param childBlocks + * the list of children blocks of the block to construct + * @see AbstractFatherBlock#AbstractFatherBlock(List) + */ + public XDOM(List childBlocks) { + super(childBlocks); + + this.idGenerator = new IdGenerator(); + } + + /** + * @param childBlocks + * the list of children blocks of the block to construct + * @param idGenerator + * a sateful id generator for this document + */ + public XDOM(List childBlocks, IdGenerator idGenerator) { + super(childBlocks); + + this.idGenerator = idGenerator; + } + + /** + * @return a stateful id generator for the whole document. + */ + public IdGenerator getIdGenerator() { + return this.idGenerator; + } + + /** + * @param idGenerator + * a stateful id generator for the whole document. + * @since 2.1M1 + */ + public void setIdGenerator(IdGenerator idGenerator) { + this.idGenerator = idGenerator; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#before(org.xwiki.rendering.listener.Listener) + */ + public void before(Listener listener) { + listener.beginDocument(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractFatherBlock#after(org.xwiki.rendering.listener.Listener) + */ + public void after(Listener listener) { + listener.endDocument(getParameters()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.AbstractBlock#clone() + */ + @Override + public XDOM clone() { + return (XDOM) super.clone(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/configuration/RenderingConfiguration.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/configuration/RenderingConfiguration.java new file mode 100644 index 000000000..ce64c1753 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/configuration/RenderingConfiguration.java @@ -0,0 +1,77 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.configuration; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.transformation.Transformation; + +import java.util.List; +import java.util.Properties; + +/** + * Configuration properties for the Rendering module. + *

+ * You can override the default values for each of the configuration properties below by defining + * them in XWiki's global + * configuration file using a prefix of "rendering" followed by the property name. For example: + * rendering.linkLabelFormat = %s.%p + * + * @version $Id$ + * @since 1.6M1 + */ +@ComponentRole +public interface RenderingConfiguration { + + /** + * A link label format is the format used to decide how to display links that have no label. By + * default the page + * name is displayed. However it's possible to customize it using the following tokens: + *

    + *
  • %w: wiki name
  • + *
  • %s: space name
  • + *
  • %p: page name
  • + *
  • %P: page name with spaces between camel case words, i.e. "My Page" if the + * page name is + * "MyPage"
  • + *
  • %t: page title
  • + *
+ * Note that if the page title is empty or not defined then it defaults to %p. This is also the + * case if the title + * cannot be retrieved for the document. The default is "%p". Some examples: "%s.%p", "%w:%s.%p". + * + * @return the format to use to display link labels when the user hasn't specified a label + */ + String getLinkLabelFormat(); + + /** + * @return the list of InterWiki definitions. Each InterWiki definition is made of an alias and a + * base URL. + * @see org.xwiki.rendering.listener.reference.InterWikiResourceReference + */ + Properties getInterWikiDefinitions(); + + /** + * @return the list of transformations to execute when rendering document content, ordered by + * transformation + * priority (highest priority first) + * @since 2.6RC1 + */ + List getTransformations(); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/ConversionException.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/ConversionException.java new file mode 100644 index 000000000..a4fec547d --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/ConversionException.java @@ -0,0 +1,60 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.converter; + +/** + * Encapsulate a conversion error. + * + * @version $Id$ + * @since 2.0M3 + */ +public class ConversionException extends Exception { + + /** + * Class ID for serialization. + */ + private static final long serialVersionUID = 1L; + + /** + * Construct a new ParseException with the specified detail message. + * + * @param message + * The detailed message. This can later be retrieved by the Throwable.getMessage() + * method. + */ + public ConversionException(String message) { + super(message); + } + + /** + * Construct a new ParseException with the specified detail message and cause. + * + * @param message + * The detailed message. This can later be retrieved by the Throwable.getMessage() + * method. + * @param throwable + * the cause. This can be retrieved later by the Throwable.getCause() method. (A null + * value is permitted, + * and indicates that the cause is nonexistent or unknown.) + */ + public ConversionException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/Converter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/Converter.java new file mode 100644 index 000000000..c023971ca --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/converter/Converter.java @@ -0,0 +1,53 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.converter; + +import java.io.Reader; +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * Convert source content in a given Syntax to another Syntax. + * + * @version $Id$ + * @since 2.0M3 + */ +@ComponentRole +public interface Converter { + + /** + * Converts content from a Syntax to another and execute all registered Macro Transformations on + * the parsed content. + * + * @param source + * the content to be converted + * @param sourceSyntax + * the Syntax in which the content is represented + * @param targetSyntax + * the Syntax to which to convert to + * @param printer + * the printer that will receive the result of the conversion + * @throws ConversionException + * in case of a conversion error (invalid Syntax, etc) + */ + void convert(Reader source, Syntax sourceSyntax, Syntax targetSyntax, WikiPrinter printer) + throws ConversionException; +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/block/ProtectedBlockFilter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/block/ProtectedBlockFilter.java new file mode 100644 index 000000000..1bd743982 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/block/ProtectedBlockFilter.java @@ -0,0 +1,117 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.block; + +import java.util.ArrayList; +import java.util.List; + +import org.xwiki.rendering.block.Block; +import org.xwiki.rendering.block.BlockFilter; +import org.xwiki.rendering.block.MacroMarkerBlock; + +/** + * Used to manipulate Blocks but by filtering out protected blocks. + *

+ * Note: This API is a work in progress and currently a protected block is a code macro marker + * block. In the future we + * need to make this more generic and since we also need to review Transformations to make them more + * performant this + * class may go away which is why it's currently located in an internal package. + *

+ * + * @version $Id$ + * @since 2.6 + */ +public class ProtectedBlockFilter implements BlockFilter { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.block.BlockFilter#filter(org.xwiki.rendering.block.Block) + */ + public List filter(Block block) { + List blocks = new ArrayList(); + if (!isProtectedBlock(block)) { + blocks.add(block); + } + return blocks; + } + + /** + * @param blocks + * the blocks to filter + * @return the filtered blocks + */ + public List filter(List blocks) { + List filteredBlocks = new ArrayList(); + for (Block block : blocks) { + filteredBlocks.addAll(filter(block)); + } + return filteredBlocks; + } + + /** + * @param block + * the block to filter out + * @return the next sibling that is not a protected block or null if not found + */ + public Block getNextSibling(Block block) { + Block sibling = block.getNextSibling(); + while (sibling != null && isProtectedBlock(sibling)) { + sibling = sibling.getNextSibling(); + } + return sibling; + } + + /** + * @param block + * the block to filter out + * @param blockClass + * the type of Blocks to look for + * @param recurse + * if true also search recursively children + * @param + * the class of the Blocks to return + * @return the filtered blocks matching the passed Block class + */ + public List getChildrenByType(Block block, Class blockClass, + boolean recurse) { + List typedBlocks = new ArrayList(); + for (Block child : filter(block.getChildren())) { + if (blockClass.isAssignableFrom(child.getClass())) { + typedBlocks.add(blockClass.cast(child)); + } + if (recurse && !child.getChildren().isEmpty()) { + typedBlocks.addAll(getChildrenByType(child, blockClass, true)); + } + } + + return typedBlocks; + } + + /** + * @param block + * the block to test + * @return true if the passed block is a protected block or false otherwise + */ + private boolean isProtectedBlock(Block block) { + return (block instanceof MacroMarkerBlock) && ((MacroMarkerBlock) block).getId().equals("code"); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/configuration/DefaultRenderingConfiguration.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/configuration/DefaultRenderingConfiguration.java new file mode 100644 index 000000000..717e9a7af --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/configuration/DefaultRenderingConfiguration.java @@ -0,0 +1,127 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.configuration; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.Requirement; +import org.xwiki.component.phase.Initializable; +import org.xwiki.component.phase.InitializationException; +import org.xwiki.rendering.configuration.RenderingConfiguration; +import org.xwiki.rendering.transformation.Transformation; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; + +/** + * Basic default implementation to be used when using the XWiki Rendering system standalone. + * + * @version $Id$ + * @since 2.0M1 + */ +@Component +public class DefaultRenderingConfiguration implements RenderingConfiguration, Initializable { + + /** + * Holds the list of transformations to apply, sorted by priority in {@link #initialize()}. + */ + @Requirement + private List transformations = new ArrayList(); + + /** + * @see #getLinkLabelFormat() + */ + private String linkLabelFormat = "%p"; + + /** + * @see #getInterWikiDefinitions() + */ + private Properties interWikiDefinitions = new Properties(); + + /** + * {@inheritDoc} + * + * @see Initializable#initialize() + */ + public void initialize() throws InitializationException { + // Sort transformations by priority. + Collections.sort(this.transformations); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.configuration.RenderingConfiguration#getLinkLabelFormat() + */ + public String getLinkLabelFormat() { + return this.linkLabelFormat; + } + + /** + * @param linkLabelFormat + * the format used to decide how to display links that have no label + */ + public void setLinkLabelFormat(String linkLabelFormat) { + // This method is useful for those using the XWiki Rendering in standalone mode since it allows + // the rendering + // to work even without a configuration store. + this.linkLabelFormat = linkLabelFormat; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.configuration.RenderingConfiguration#getInterWikiDefinitions() + */ + public Properties getInterWikiDefinitions() { + return this.interWikiDefinitions; + } + + /** + * @param interWikiAlias + * see {@link org.xwiki.rendering.listener.reference.InterWikiResourceReference} + * @param interWikiURL + * see {@link org.xwiki.rendering.listener.reference.InterWikiResourceReference} + */ + public void addInterWikiDefinition(String interWikiAlias, String interWikiURL) { + // This method is useful for those using the XWiki Rendering in standalone mode since it allows + // the rendering + // to work even without a configuration store. + this.interWikiDefinitions.setProperty(interWikiAlias, interWikiURL); + } + + /** + * @param transformations + * the explicit list of transformations to execute (overrides the default list) + */ + public void setTransformations(List transformations) { + this.transformations = transformations; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.configuration.RenderingConfiguration#getTransformations() + */ + public List getTransformations() { + return this.transformations; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/converter/DefaultConverter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/converter/DefaultConverter.java new file mode 100644 index 000000000..e60fec698 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/converter/DefaultConverter.java @@ -0,0 +1,78 @@ +package org.xwiki.rendering.internal.converter; + +import java.io.Reader; +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.Requirement; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.converter.ConversionException; +import org.xwiki.rendering.converter.Converter; +import org.xwiki.rendering.parser.ParseException; +import org.xwiki.rendering.parser.Parser; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.renderer.BlockRenderer; +import org.xwiki.rendering.renderer.printer.WikiPrinter; +import org.xwiki.rendering.transformation.TransformationContext; +import org.xwiki.rendering.transformation.TransformationException; +import org.xwiki.rendering.transformation.TransformationManager; + +/** + * Default implementation for {@link Converter}. + * + * @version $Id$ + */ +@Component +public class DefaultConverter implements Converter { + + /** + * Used to lookup parser and renderer. + */ + @Requirement + private ComponentManager componentManager; + + /** + * Used to execute transformations. + */ + @Requirement + private TransformationManager transformationManager; + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.converter.Converter#convert(java.io.Reader, + * org.xwiki.rendering.syntax.Syntax, + * org.xwiki.rendering.syntax.Syntax, org.xwiki.rendering.renderer.printer.WikiPrinter) + */ + public void convert(Reader source, Syntax sourceSyntax, Syntax targetSyntax, WikiPrinter printer) + throws ConversionException { + // Step 1: Find the parser and generate a XDOM + XDOM xdom; + try { + Parser parser = this.componentManager.lookup(Parser.class, sourceSyntax.toIdString()); + xdom = parser.parse(source); + } catch (ComponentLookupException e) { + throw new ConversionException("Failed to locate Parser for syntax [" + sourceSyntax + "]", e); + } catch (ParseException e) { + throw new ConversionException("Failed to parse input source", e); + } + + // Step 2: Run transformations + try { + TransformationContext context = new TransformationContext(xdom, sourceSyntax); + this.transformationManager.performTransformations(xdom, context); + } catch (TransformationException e) { + throw new ConversionException("Failed to execute some transformations", e); + } + + // Step 3: Locate the Renderer and render the content in the passed printer + BlockRenderer renderer; + try { + renderer = this.componentManager.lookup(BlockRenderer.class, targetSyntax.toIdString()); + } catch (ComponentLookupException e) { + throw new ConversionException("Failed to locate Renderer for syntax [" + targetSyntax + "]", + e); + } + renderer.render(xdom, printer); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/AbstractBlockParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/AbstractBlockParser.java new file mode 100644 index 000000000..37318c70e --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/AbstractBlockParser.java @@ -0,0 +1,73 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.parser; + +import java.io.Reader; + +import org.xwiki.component.annotation.Requirement; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.parser.ParseException; +import org.xwiki.rendering.parser.Parser; +import org.xwiki.rendering.parser.StreamParser; + +/** + * Common code for {@link Parser} implementation that produce a {@link XDOM} from + * {@link StreamParser}. + * + * @version $Id$ + * @since 2.1M1 + */ +public abstract class AbstractBlockParser implements Parser { + + /** + * Used to lookup the {@link StreamParser} for the syntax. + */ + @Requirement + private ComponentManager componentManager; + + /** + * @return the {@link StreamParser} to use to parser the input content + */ + protected StreamParser getStreamParser() { + StreamParser streamParser; + try { + streamParser = this.componentManager.lookup(StreamParser.class, getSyntax().toIdString()); + } catch (ComponentLookupException e) { + throw new RuntimeException("Failed to create [" + getSyntax().toString() + "] renderer", e); + } + + return streamParser; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.parser.Parser#parse(java.io.Reader) + */ + public XDOM parse(Reader source) throws ParseException { + XDOMGeneratorListener listener = new XDOMGeneratorListener(); + + getStreamParser().parse(source, listener); + + return listener.getXDOM(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextBlockParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextBlockParser.java new file mode 100644 index 000000000..d1d138e6e --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextBlockParser.java @@ -0,0 +1,42 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.parser; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Plain Text Parser to convert a text source into a XDOM object. + * + * @version $Id$ + * @since 2.1M1 + */ +@Component("plain/1.0") +public class PlainTextBlockParser extends AbstractBlockParser { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.parser.Parser#getSyntax() + */ + public Syntax getSyntax() { + return Syntax.PLAIN_1_0; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextStreamParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextStreamParser.java new file mode 100644 index 000000000..28396d72d --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/PlainTextStreamParser.java @@ -0,0 +1,129 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.parser; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.util.regex.Pattern; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.listener.Listener; +import org.xwiki.rendering.parser.ParseException; +import org.xwiki.rendering.parser.StreamParser; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Plain Text Parser to convert a text source into a events. + * + * @version $Id$ + * @since 2.1M1 + */ +@Component("plain/1.0") +public class PlainTextStreamParser implements StreamParser { + + /** + * The characters which are considered as "special" symbols for + * {@link org.xwiki.rendering.block.SpecialSymbolBlock} + * . + */ + public static final Pattern SPECIALSYMBOL_PATTERN = Pattern + .compile("[!\"#$%&'()*+,-./:;<=>?@\\[\\]^_`{|}~]"); + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.parser.Parser#getSyntax() + */ + public Syntax getSyntax() { + return Syntax.PLAIN_1_0; + } + + /** + * Read a single char from an Reader source. + * + * @param source + * the input to read from + * @return the char read + * @throws ParseException + * in case of reading error + */ + private int readChar(Reader source) throws ParseException { + int c; + + try { + c = source.read(); + } catch (IOException e) { + throw new ParseException("Failed to read input source", e); + } + + return c; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.parser.StreamParser#parse(java.io.Reader, + * org.xwiki.rendering.listener.Listener) + */ + public void parse(Reader source, Listener listener) throws ParseException { + StringBuffer word = new StringBuffer(); + BufferedReader bufferedSource = new BufferedReader(source); + int charAsInt; + + listener.beginParagraph(Listener.EMPTY_PARAMETERS); + + while ((charAsInt = readChar(bufferedSource)) != -1) { + char c = (char) charAsInt; + if (c == '\n') { + if (word.length() > 0) { + listener.onWord(word.toString()); + } + listener.onNewLine(); + + word.setLength(0); + } else if (c == '\r') { + // Do nothing, skip it + } else if (c == ' ') { + if (word.length() > 0) { + listener.onWord(word.toString()); + } + listener.onSpace(); + + word.setLength(0); + } else if (SPECIALSYMBOL_PATTERN.matcher(String.valueOf(c)).matches()) { + if (word.length() > 0) { + listener.onWord(word.toString()); + } + listener.onSpecialSymbol(c); + + word.setLength(0); + } else { + word.append(c); + } + } + + if (word.length() > 0) { + listener.onWord(word.toString()); + } + + listener.endParagraph(Listener.EMPTY_PARAMETERS); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/XDOMGeneratorListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/XDOMGeneratorListener.java new file mode 100644 index 000000000..5fccef087 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/parser/XDOMGeneratorListener.java @@ -0,0 +1,579 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.parser; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import org.xwiki.rendering.block.AbstractBlock; +import org.xwiki.rendering.block.Block; +import org.xwiki.rendering.block.BulletedListBlock; +import org.xwiki.rendering.block.DefinitionDescriptionBlock; +import org.xwiki.rendering.block.DefinitionListBlock; +import org.xwiki.rendering.block.DefinitionTermBlock; +import org.xwiki.rendering.block.EmptyLinesBlock; +import org.xwiki.rendering.block.FormatBlock; +import org.xwiki.rendering.block.GroupBlock; +import org.xwiki.rendering.block.HeaderBlock; +import org.xwiki.rendering.block.HorizontalLineBlock; +import org.xwiki.rendering.block.IdBlock; +import org.xwiki.rendering.block.ImageBlock; +import org.xwiki.rendering.block.LinkBlock; +import org.xwiki.rendering.block.ListItemBlock; +import org.xwiki.rendering.block.MacroBlock; +import org.xwiki.rendering.block.MacroMarkerBlock; +import org.xwiki.rendering.block.NewLineBlock; +import org.xwiki.rendering.block.NumberedListBlock; +import org.xwiki.rendering.block.ParagraphBlock; +import org.xwiki.rendering.block.QuotationBlock; +import org.xwiki.rendering.block.QuotationLineBlock; +import org.xwiki.rendering.block.RawBlock; +import org.xwiki.rendering.block.SectionBlock; +import org.xwiki.rendering.block.SpaceBlock; +import org.xwiki.rendering.block.SpecialSymbolBlock; +import org.xwiki.rendering.block.TableBlock; +import org.xwiki.rendering.block.TableCellBlock; +import org.xwiki.rendering.block.TableHeadCellBlock; +import org.xwiki.rendering.block.TableRowBlock; +import org.xwiki.rendering.block.VerbatimBlock; +import org.xwiki.rendering.block.WordBlock; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.listener.Listener; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Produce a {@link XDOM} based on events. + * + * @version $Id$ + * @since 2.1M1 + */ +public class XDOMGeneratorListener implements Listener { + + private Stack stack = new Stack(); + + private final MarkerBlock marker = new MarkerBlock(); + + private static class MarkerBlock extends AbstractBlock { + + /** + * {@inheritDoc} + * + * @see AbstractBlock#traverse(Listener) + */ + public void traverse(Listener listener) { + // Nothing to do since this block is only used as a marker. + } + } + + public XDOM getXDOM() { + return new XDOM(generateListFromStack()); + } + + private List generateListFromStack() { + List blocks = new ArrayList(); + while (!this.stack.empty()) { + if (this.stack.peek() != this.marker) { + blocks.add(this.stack.pop()); + } else { + this.stack.pop(); + break; + } + } + Collections.reverse(blocks); + return blocks; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionDescription() + */ + public void beginDefinitionDescription() { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionList(java.util.Map) + */ + public void beginDefinitionList(Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionTerm() + */ + public void beginDefinitionTerm() { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDocument(java.util.Map) + */ + public void beginDocument(Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + public void beginFormat(Format format, Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginGroup(java.util.Map) + */ + public void beginGroup(Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + public void beginHeader(HeaderLevel level, String id, Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void beginList(ListType listType, Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginListItem() + */ + public void beginListItem() { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void beginMacroMarker(String name, Map macroParameters, String content, + boolean isInline) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginParagraph(java.util.Map) + */ + public void beginParagraph(Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotation(java.util.Map) + */ + public void beginQuotation(Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotationLine() + */ + public void beginQuotationLine() { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginSection(java.util.Map) + */ + public void beginSection(Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTable(java.util.Map) + */ + public void beginTable(Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableCell(java.util.Map) + */ + public void beginTableCell(Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableHeadCell(java.util.Map) + */ + public void beginTableHeadCell(Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableRow(java.util.Map) + */ + public void beginTableRow(Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.LinkListener#beginLink(org.xwiki.rendering.listener.reference.ResourceReference + * , boolean, java.util.Map) + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.stack.push(this.marker); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionDescription() + */ + public void endDefinitionDescription() { + this.stack.push(new DefinitionDescriptionBlock(generateListFromStack())); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionList(java.util.Map) + */ + public void endDefinitionList(Map parameters) { + this.stack.push(new DefinitionListBlock(generateListFromStack(), parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionTerm() + */ + public void endDefinitionTerm() { + this.stack.push(new DefinitionTermBlock(generateListFromStack())); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDocument(java.util.Map) + */ + public void endDocument(Map parameters) { + // Do nothing. This is supposed to append only once for the hole document + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + public void endFormat(Format format, Map parameters) { + this.stack.push(new FormatBlock(generateListFromStack(), format, parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endGroup(java.util.Map) + */ + public void endGroup(Map parameters) { + this.stack.push(new GroupBlock(generateListFromStack(), parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, + * java.util.Map) + */ + public void endHeader(HeaderLevel level, String id, Map parameters) { + this.stack.push(new HeaderBlock(generateListFromStack(), level, parameters, id)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void endList(ListType listType, Map parameters) { + if (listType == ListType.BULLETED) { + this.stack.push(new BulletedListBlock(generateListFromStack(), parameters)); + } else { + this.stack.push(new NumberedListBlock(generateListFromStack(), parameters)); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endListItem() + */ + public void endListItem() { + this.stack.push(new ListItemBlock(generateListFromStack())); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void endMacroMarker(String name, Map macroParameters, String content, + boolean isInline) { + this.stack.push( + new MacroMarkerBlock(name, macroParameters, content, generateListFromStack(), isInline)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endParagraph(java.util.Map) + */ + public void endParagraph(Map parameters) { + this.stack.push(new ParagraphBlock(generateListFromStack(), parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotation(java.util.Map) + */ + public void endQuotation(Map parameters) { + this.stack.push(new QuotationBlock(generateListFromStack(), parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotationLine() + */ + public void endQuotationLine() { + this.stack.push(new QuotationLineBlock(generateListFromStack())); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endSection(java.util.Map) + */ + public void endSection(Map parameters) { + this.stack.push(new SectionBlock(generateListFromStack(), parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTable(java.util.Map) + */ + public void endTable(Map parameters) { + this.stack.push(new TableBlock(generateListFromStack(), parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableCell(java.util.Map) + */ + public void endTableCell(Map parameters) { + this.stack.push(new TableCellBlock(generateListFromStack(), parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableHeadCell(java.util.Map) + */ + public void endTableHeadCell(Map parameters) { + this.stack.push(new TableHeadCellBlock(generateListFromStack(), parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableRow(java.util.Map) + */ + public void endTableRow(Map parameters) { + this.stack.push(new TableRowBlock(generateListFromStack(), parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.LinkListener#endLink(org.xwiki.rendering.listener.reference.ResourceReference + * , + * boolean, java.util.Map) + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.stack + .push(new LinkBlock(generateListFromStack(), reference, isFreeStandingURI, parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onEmptyLines(int) + */ + public void onEmptyLines(int count) { + this.stack.push(new EmptyLinesBlock(count)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onHorizontalLine(java.util.Map) + */ + public void onHorizontalLine(Map parameters) { + this.stack.push(new HorizontalLineBlock(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onId(java.lang.String) + */ + public void onId(String name) { + this.stack.push(new IdBlock(name)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onMacro(java.lang.String, java.util.Map, + * java.lang.String, boolean) + */ + public void onMacro(String id, Map macroParameters, String content, + boolean isInline) { + this.stack.push(new MacroBlock(id, macroParameters, content, isInline)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onNewLine() + */ + public void onNewLine() { + this.stack.push(new NewLineBlock()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onRawText(java.lang.String, + * org.xwiki.rendering.syntax.Syntax) + */ + public void onRawText(String rawContent, Syntax syntax) { + this.stack.push(new RawBlock(rawContent, syntax)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpace() + */ + public void onSpace() { + this.stack.push(new SpaceBlock()); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpecialSymbol(char) + */ + public void onSpecialSymbol(char symbol) { + this.stack.push(new SpecialSymbolBlock(symbol)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onVerbatim(java.lang.String, boolean, java.util.Map) + */ + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.stack.push(new VerbatimBlock(protectedString, parameters, isInline)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onWord(java.lang.String) + */ + public void onWord(String word) { + this.stack.push(new WordBlock(word)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.ImageListener#onImage(org.xwiki.rendering.listener.reference.ResourceReference + * , boolean, java.util.Map) + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.stack.push(new ImageBlock(reference, isFreeStandingURI, parameters)); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractBlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractBlockRenderer.java new file mode 100644 index 000000000..bf698e30b --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractBlockRenderer.java @@ -0,0 +1,65 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer; + +import java.util.Collection; +import java.util.Collections; +import org.xwiki.rendering.block.Block; +import org.xwiki.rendering.renderer.BlockRenderer; +import org.xwiki.rendering.renderer.PrintRendererFactory; +import org.xwiki.rendering.renderer.printer.WikiPrinter; +import org.xwiki.rendering.renderer.PrintRenderer; + +/** + * Common code for BlockRender implementation that uses Print Renderer Factory. + * + * @version $Id$ + * @since 2.0M3 + */ +public abstract class AbstractBlockRenderer implements BlockRenderer { + + /** + * @return provide the factory to use to create a new {@link PrintRenderer}. + */ + protected abstract PrintRendererFactory getPrintRendererFactory(); + + /** + * {@inheritDoc} + * + * @see BlockRenderer#render(org.xwiki.rendering.block.Block, + * org.xwiki.rendering.renderer.printer.WikiPrinter) + */ + public void render(Block block, WikiPrinter printer) { + render(Collections.singletonList(block), printer); + } + + /** + * {@inheritDoc} + * + * @see BlockRenderer#render(java.util.Collection, + * org.xwiki.rendering.renderer.printer.WikiPrinter) + */ + public void render(Collection blocks, WikiPrinter printer) { + PrintRenderer renderer = getPrintRendererFactory().createRenderer(printer); + for (Block block : blocks) { + block.traverse(renderer); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractPrintRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractPrintRendererFactory.java new file mode 100644 index 000000000..37d4b5566 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/AbstractPrintRendererFactory.java @@ -0,0 +1,62 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer; + +import org.xwiki.component.annotation.Requirement; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; +import org.xwiki.rendering.renderer.PrintRenderer; +import org.xwiki.rendering.renderer.PrintRendererFactory; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * Common code for {@link org.xwiki.rendering.renderer.PrintRendererFactory}, implements the logic + * to lookup and call + * the matching Print Renderer. + * + * @version $Id$ + * @since 2.0M3 + */ +public abstract class AbstractPrintRendererFactory implements PrintRendererFactory { + + /** + * Used to lookup the {@link PrintRenderer}. + */ + @Requirement + private ComponentManager componentManager; + + /** + * {@inheritDoc} + * + * @see PrintRendererFactory#createRenderer(org.xwiki.rendering.renderer.printer.WikiPrinter) + */ + public PrintRenderer createRenderer(WikiPrinter printer) { + PrintRenderer renderer; + try { + renderer = this.componentManager.lookup(PrintRenderer.class, getSyntax().toIdString()); + } catch (ComponentLookupException e) { + throw new RuntimeException("Failed to create [" + getSyntax().toString() + "] renderer", e); + } + + renderer.setPrinter(printer); + + return renderer; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultAttachmentURILabelGenerator.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultAttachmentURILabelGenerator.java new file mode 100644 index 000000000..d5260a675 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultAttachmentURILabelGenerator.java @@ -0,0 +1,44 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.reference.link.URILabelGenerator; + +/** + * Generate link labels for ATTACH URIs. + * + * @version $Id: DefaultAttachmentURILabelGenerator.java 31386 2010-09-27 09:42:32Z vmassol $ + * @since 2.5RC1 + */ +@Component("attach") +public class DefaultAttachmentURILabelGenerator implements URILabelGenerator { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.link.URILabelGenerator#generateLabel( + * org.xwiki.rendering.listener.reference.ResourceReference) + */ + public String generateLabel(ResourceReference reference) { + return reference.getReference(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultLinkLabelGenerator.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultLinkLabelGenerator.java new file mode 100644 index 000000000..a9b0359f6 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/DefaultLinkLabelGenerator.java @@ -0,0 +1,46 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator; + +/** + * Basic default implementation to be used when the XWiki Rendering is used standalone, outside of + * XWiki. + * + * @version $Id$ + * @since 2.0M1 + */ +@Component +public class DefaultLinkLabelGenerator implements LinkLabelGenerator { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator#generate( + * org.xwiki.rendering.listener.reference.ResourceReference) + * @since 2.5RC1 + */ + public String generate(ResourceReference reference) { + return reference.getReference(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/MailtoURILabelGenerator.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/MailtoURILabelGenerator.java new file mode 100644 index 000000000..953b7ea30 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/MailtoURILabelGenerator.java @@ -0,0 +1,46 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer; + +import org.apache.commons.lang.StringUtils; +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.renderer.reference.link.URILabelGenerator; + +/** + * Generate link labels for MAILTO URIs. + * + * @version $Id$ + * @since 2.2RC1 + */ +@Component("mailto") +public class MailtoURILabelGenerator implements URILabelGenerator { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.reference.link.URILabelGenerator#generateLabel( + * org.xwiki.rendering.listener.reference.ResourceReference) + */ + public String generateLabel(ResourceReference reference) { + // Remove the query string (if any). + return StringUtils.substringBefore(reference.getReference(), "?"); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/ParametersPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/ParametersPrinter.java new file mode 100644 index 000000000..488bf5c2e --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/ParametersPrinter.java @@ -0,0 +1,83 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer; + +import java.util.Map; + +/** + * Generates syntax for a parameters group like macros and links. + * + * @version $Id$ + * @since 1.9RC2 + */ +public class ParametersPrinter { + + /** + * Quote character. + */ + private static final String QUOTE = "\""; + + /** + * Print the parameters as a String. + * + * @param parameters + * the parameters to print + * @param escapeChar + * the character used in front of a special character when need to escape it + * @return the printed parameters + */ + public String print(Map parameters, char escapeChar) { + StringBuffer buffer = new StringBuffer(); + for (Map.Entry entry : parameters.entrySet()) { + String value = entry.getValue(); + String key = entry.getKey(); + + if (key != null && value != null) { + if (buffer.length() > 0) { + buffer.append(' '); + } + buffer.append(print(key, value, escapeChar)); + } + } + + return buffer.toString(); + } + + /** + * Print a parameter as a String. + * + * @param parameterName + * the name of the parameter to print + * @param parameterValue + * the value of the parameter to print + * @param escapeChar + * the character used in front of a special character when need to escape it + * @return the printed parameter + */ + public String print(String parameterName, String parameterValue, char escapeChar) { + // escape the escaping character + String value = parameterValue.replace(String.valueOf(escapeChar), + String.valueOf(escapeChar) + escapeChar); + // escape quote + value = value.replace(QUOTE, String.valueOf(escapeChar) + QUOTE); + + return parameterName + "=" + QUOTE + value + QUOTE; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventBlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventBlockRenderer.java new file mode 100644 index 000000000..71410a398 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventBlockRenderer.java @@ -0,0 +1,37 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer.event; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.Requirement; +import org.xwiki.rendering.internal.renderer.AbstractBlockRenderer; +import org.xwiki.rendering.renderer.PrintRendererFactory; + +@Component("event/1.0") +public class EventBlockRenderer extends AbstractBlockRenderer { + + @Requirement("event/1.0") + private PrintRendererFactory eventRendererFactory; + + @Override + protected PrintRendererFactory getPrintRendererFactory() { + return this.eventRendererFactory; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRenderer.java new file mode 100644 index 000000000..01a39a00e --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRenderer.java @@ -0,0 +1,59 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer.event; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.InstantiationStrategy; +import org.xwiki.component.descriptor.ComponentInstantiationStrategy; +import org.xwiki.component.phase.Initializable; +import org.xwiki.component.phase.InitializationException; +import org.xwiki.rendering.listener.chaining.ListenerChain; +import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer; + +/** + * Print names of events. Useful for debugging and tracing in general. Note that this class is not + * located in the test + * source tree since it's currently used at runtime by the WYSIWYG editor for its runtime debug + * mode. + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("event/1.0") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class EventRenderer extends AbstractChainingPrintRenderer implements Initializable { + + /** + * {@inheritDoc} + * + * @see Initializable#initialize() + * @since 2.0M3 + */ + public void initialize() throws InitializationException { + ListenerChain chain = new ListenerChain(); + setListenerChain(chain); + + // Construct the listener chain in the right order. Listeners early in the chain are called + // before listeners + // placed later in the chain. + chain.addListener(this); + chain.addListener(new EventsChainingRenderer(chain)); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRendererFactory.java new file mode 100644 index 000000000..80a3506ad --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventRendererFactory.java @@ -0,0 +1,43 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer.event; + +import org.xwiki.rendering.internal.renderer.*; +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Create XHTML Renderers. + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("event/1.0") +public class EventRendererFactory extends AbstractPrintRendererFactory { + + /** + * {@inheritDoc} + * + * @see AbstractPrintRendererFactory#getSyntax() + */ + public Syntax getSyntax() { + return Syntax.EVENT_1_0; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventsChainingRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventsChainingRenderer.java new file mode 100644 index 000000000..326ad800b --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/event/EventsChainingRenderer.java @@ -0,0 +1,651 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer.event; + +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.listener.chaining.ListenerChain; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer; + +/** + * Prints listener event names in a format useful for testing and debugging. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class EventsChainingRenderer extends AbstractChainingPrintRenderer { + + public EventsChainingRenderer(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + // Events + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDocument(java.util.Map) + */ + @Override + public void beginDocument(Map parameters) { + getPrinter().println("beginDocument" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + getPrinter().print("endDocument" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(Map) + */ + @Override + public void beginGroup(Map parameters) { + getPrinter().println("beginGroup" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(Map) + */ + @Override + public void endGroup(Map parameters) { + getPrinter().println("endGroup" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void beginFormat(Format format, Map parameters) { + getPrinter().println("beginFormat [" + format + "]" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void endFormat(Format format, Map parameters) { + getPrinter().println("endFormat [" + format + "]" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + getPrinter().println("beginParagraph" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + getPrinter().println("endParagraph" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onNewLine() + */ + @Override + public void onNewLine() { + getPrinter().println("onNewLine"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + */ + @Override + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + getPrinter() + .println("beginLink [" + reference + "] [" + isFreeStandingURI + "]" + + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + getPrinter() + .println("endLink [" + reference + "] [" + isFreeStandingURI + "]" + + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onMacro(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + printMacroData("onMacro", id, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginSection(java.util.Map) + */ + @Override + public void beginSection(Map parameters) { + getPrinter().println("beginSection" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * String, java.util.Map) + */ + @Override + public void beginHeader(HeaderLevel level, String id, Map parameters) { + getPrinter() + .println("beginHeader [" + level + ", " + id + "]" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endSection(java.util.Map) + */ + @Override + public void endSection(Map parameters) { + getPrinter().println("endSection" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endHeader( + * org.xwiki.rendering.listener.HeaderLevel, String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + getPrinter().println("endHeader [" + level + ", " + id + "]" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onWord(java.lang.String) + */ + @Override + public void onWord(String word) { + getPrinter().println("onWord [" + getEscaped(word) + "]"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void beginList(ListType listType, Map parameters) { + getPrinter().println("beginList [" + listType + "]" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginListItem() + */ + @Override + public void beginListItem() { + getPrinter().println("beginListItem"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void endList(ListType listType, Map parameters) { + getPrinter().println("endList [" + listType + "]" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endListItem() + */ + @Override + public void endListItem() { + getPrinter().println("endListItem"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onSpace() + */ + @Override + public void onSpace() { + getPrinter().println("onSpace"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + getPrinter().println("onSpecialSymbol [" + symbol + "]"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onRawText(String, Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + getPrinter().println("onRawText [" + text + "] [" + syntax.toIdString() + "]"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginMacroMarker(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void beginMacroMarker(String name, Map parameters, String content, + boolean isInline) { + printMacroData("beginMacroMarker", name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endMacroMarker(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void endMacroMarker(String name, Map parameters, String content, + boolean isInline) { + printMacroData("endMacroMarker", name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onId(java.lang.String) + */ + @Override + public void onId(String name) { + getPrinter().println("onId [" + name + "]"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + getPrinter().println("onHorizontalLine" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + getPrinter().println("onEmptyLines [" + count + "]"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + getPrinter() + .println("onVerbatim [" + protectedString + "] [" + isInline + "]" + + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + getPrinter().println("beginDefinitionList" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void endDefinitionList(Map parameters) { + getPrinter().println("endDefinitionList" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + getPrinter().println("beginDefinitionTerm"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + getPrinter().println("beginDefinitionDescription"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + getPrinter().println("endDefinitionTerm"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + getPrinter().println("endDefinitionDescription"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginQuotation(java.util.Map) + */ + @Override + public void beginQuotation(Map parameters) { + getPrinter().println("beginQuotation" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endQuotation(java.util.Map) + */ + @Override + public void endQuotation(Map parameters) { + getPrinter().println("endQuotation" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + getPrinter().println("beginQuotationLine"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endQuotationLine() + */ + @Override + public void endQuotationLine() { + getPrinter().println("endQuotationLine"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + getPrinter().println("beginTable" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + getPrinter().println("beginTableCell" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + getPrinter().println("beginTableHeadCell" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + getPrinter().println("beginTableRow" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + getPrinter().println("endTable" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + getPrinter().println("endTableCell" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + getPrinter().println("endTableHeadCell" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#endTableRow(java.util.Map) + */ + @Override + public void endTableRow(Map parameters) { + getPrinter().println("endTableRow" + serializeParameters(parameters)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + getPrinter() + .println("onImage [" + reference + "] [" + isFreeStandingURI + "]" + + serializeParameters(parameters)); + } + + public String getEscaped(String str) { + String printableStr; + + if (str == null) { + printableStr = null; + } else if (StringUtils.isAsciiPrintable(str)) { + printableStr = str; + } else { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c > 126) { + buffer.append("(((").append((int) c).append(")))"); + } else { + buffer.append(c); + } + } + printableStr = buffer.toString(); + } + + return printableStr; + } + + private void printMacroData(String eventName, String name, Map parameters, + String content, + boolean isInline) { + StringBuffer parametersBuffer = new StringBuffer(); + for (Iterator paramsIt = parameters.keySet().iterator(); paramsIt.hasNext();) { + String paramName = paramsIt.next(); + parametersBuffer.append(paramName).append("=").append(parameters.get(paramName)); + if (paramsIt.hasNext()) { + parametersBuffer.append("|"); + } + } + + StringBuffer macroBuffer = new StringBuffer(); + + macroBuffer.append(eventName); + macroBuffer.append(isInline ? "Inline" : "Standalone"); + + macroBuffer.append(" ["); + macroBuffer.append(name); + macroBuffer.append("]"); + + macroBuffer.append(" ["); + macroBuffer.append(parametersBuffer); + macroBuffer.append("]"); + + if (content != null) { + macroBuffer.append(" ["); + macroBuffer.append(content); + macroBuffer.append("]"); + } + + getPrinter().println(macroBuffer.toString()); + } + + private String serializeParameters(Map parameters) { + StringBuffer parametersStr = new StringBuffer(); + for (Map.Entry entry : parameters.entrySet()) { + String value = entry.getValue(); + String key = entry.getKey(); + + if (key != null && value != null) { + parametersStr.append('[').append(getEscaped(entry.getKey())).append(']').append('=') + .append('[') + .append(getEscaped(entry.getValue())).append(']'); + } + } + + if (parametersStr.length() > 0) { + StringBuffer buffer = new StringBuffer(); + buffer.append(' ').append('['); + buffer.append(parametersStr); + buffer.append(']'); + return buffer.toString(); + } else { + return ""; + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextBlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextBlockRenderer.java new file mode 100644 index 000000000..5586010a1 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextBlockRenderer.java @@ -0,0 +1,55 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer.plain; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.Requirement; +import org.xwiki.rendering.internal.renderer.AbstractBlockRenderer; +import org.xwiki.rendering.renderer.PrintRendererFactory; + +/** + * Print only plain text information. For example it remove anything which need a specific syntax a + * simple plain text + * editor can't support like the style, link, image, etc. This renderer is mainly used to generate a + * simple as possible + * label like in a TOC. + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("plain/1.0") +public class PlainTextBlockRenderer extends AbstractBlockRenderer { + + /** + * Used to create new plain/1.0 {@link org.xwiki.rendering.renderer.PrintRenderer}s. + */ + @Requirement("plain/1.0") + private PrintRendererFactory plainTextRendererFactory; + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.internal.renderer.AbstractBlockRenderer#getPrintRendererFactory() + */ + @Override + protected PrintRendererFactory getPrintRendererFactory() { + return this.plainTextRendererFactory; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRenderer.java new file mode 100644 index 000000000..5e95b13a0 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextChainingRenderer.java @@ -0,0 +1,338 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer.plain; + +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.listener.chaining.BlockStateChainingListener; +import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener; +import org.xwiki.rendering.listener.chaining.ListenerChain; +import org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator; +import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer; + +/** + * Print only plain text information. For example it remove anything which need a specific syntax a + * simple plain text + * editor can't support like the style, link, image, etc. This renderer is mainly used to generate a + * simple as possible + * label like in a TOC. + * + * @version $Id$ + * @since 1.9M1 + */ +public class PlainTextChainingRenderer extends AbstractChainingPrintRenderer { + + /** + * New Line character. + */ + private static final String NL = "\n"; + + private boolean isFirstElementRendered; + + /** + * Generate link label. + */ + private LinkLabelGenerator linkLabelGenerator; + + /** + * The plain text renderer supports when no link label generator is set. + */ + public PlainTextChainingRenderer(ListenerChain listenerChain) { + this(null, listenerChain); + } + + public PlainTextChainingRenderer(LinkLabelGenerator linkLabelGenerator, + ListenerChain listenerChain) { + setListenerChain(listenerChain); + + this.linkLabelGenerator = linkLabelGenerator; + } + + // State + + private BlockStateChainingListener getBlockState() { + return (BlockStateChainingListener) getListenerChain() + .getListener(BlockStateChainingListener.class); + } + + protected EmptyBlockChainingListener getEmptyBlockState() { + return (EmptyBlockChainingListener) getListenerChain() + .getListener(EmptyBlockChainingListener.class); + } + + // Events + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + printEmptyLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onNewLine() + */ + @Override + public void onNewLine() { + getPrinter().print(NL); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + if (getEmptyBlockState().isCurrentContainerBlockEmpty()) { + if (reference.getType().equals(ResourceType.DOCUMENT) && this.linkLabelGenerator != null) { + getPrinter().print(this.linkLabelGenerator.generate(reference)); + } else { + getPrinter().print(reference.getReference()); + } + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * String, java.util.Map) + */ + @Override + public void beginHeader(HeaderLevel level, String id, Map parameters) { + printEmptyLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onWord(java.lang.String) + */ + @Override + public void onWord(String word) { + getPrinter().print(word); + } + + @Override + public void beginList(ListType listType, Map parameters) { + if (getBlockState().getListDepth() == 1) { + printEmptyLine(); + } else { + getPrinter().print(NL); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginListItem() + */ + @Override + public void beginListItem() { + if (getBlockState().getListItemIndex() > 0) { + getPrinter().print(NL); + } + + // TODO: maybe add some syntax here like a - or not + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onSpace() + */ + @Override + public void onSpace() { + getPrinter().print(" "); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + getPrinter().print(String.valueOf(symbol)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + printEmptyLine(); + getPrinter().print("----"); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + getPrinter().print(StringUtils.repeat(NL, count)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + getPrinter().print(protectedString); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + if (getBlockState().getDefinitionListDepth() == 1 && !getBlockState().isInList()) { + printEmptyLine(); + } else { + getPrinter().print(NL); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + if (getBlockState().getDefinitionListItemIndex() > 0) { + getPrinter().print(NL); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + if (getBlockState().getDefinitionListItemIndex() > 0) { + getPrinter().print(NL); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + if (getBlockState().getQuotationLineIndex() > 0) { + getPrinter().print(NL); + } else { + printEmptyLine(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + printEmptyLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + if (getBlockState().getCellCol() > 0) { + getPrinter().print("\t"); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + beginTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + if (getBlockState().getCellRow() > 0) { + getPrinter().print(NL); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.AbstractChainingPrintRenderer#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + // TODO: maybe something could be done here + } + + private void printEmptyLine() { + if (this.isFirstElementRendered) { + getPrinter().print(NL + NL); + } else { + this.isFirstElementRendered = true; + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRenderer.java new file mode 100644 index 000000000..a1d12a089 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRenderer.java @@ -0,0 +1,69 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer.plain; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.InstantiationStrategy; +import org.xwiki.component.annotation.Requirement; +import org.xwiki.component.descriptor.ComponentInstantiationStrategy; +import org.xwiki.component.phase.Initializable; +import org.xwiki.component.phase.InitializationException; +import org.xwiki.rendering.listener.chaining.BlockStateChainingListener; +import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener; +import org.xwiki.rendering.listener.chaining.ListenerChain; +import org.xwiki.rendering.renderer.reference.link.LinkLabelGenerator; +import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer; + +/** + * Print only plain text information. For example it remove anything which need a specific syntax a + * simple plain text + * editor can't support like the style, link, image, etc. This renderer is mainly used to generate a + * simple as possible + * label like in a TOC. + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("plain/1.0") +@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) +public class PlainTextRenderer extends AbstractChainingPrintRenderer implements Initializable { + + @Requirement + private LinkLabelGenerator linkLabelGenerator; + + /** + * {@inheritDoc} + * + * @see Initializable#initialize() + * @since 2.0M3 + */ + public void initialize() throws InitializationException { + ListenerChain chain = new ListenerChain(); + setListenerChain(chain); + + // Construct the listener chain in the right order. Listeners early in the chain are called + // before listeners + // placed later in the chain. + chain.addListener(this); + chain.addListener(new BlockStateChainingListener(chain)); + chain.addListener(new EmptyBlockChainingListener(chain)); + chain.addListener(new PlainTextChainingRenderer(this.linkLabelGenerator, chain)); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRendererFactory.java new file mode 100644 index 000000000..08696b739 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/plain/PlainTextRendererFactory.java @@ -0,0 +1,43 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer.plain; + +import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.internal.renderer.AbstractPrintRendererFactory; + +/** + * Create Plain Text Renderers. + * + * @version $Id$ + * @since 2.0M3 + */ +@Component("plain/1.0") +public class PlainTextRendererFactory extends AbstractPrintRendererFactory { + + /** + * {@inheritDoc} + * + * @see AbstractPrintRendererFactory#getSyntax() + */ + public Syntax getSyntax() { + return Syntax.PLAIN_1_0; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/WikiWriter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/WikiWriter.java new file mode 100644 index 000000000..12d603615 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/WikiWriter.java @@ -0,0 +1,90 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer.printer; + +import java.io.IOException; +import java.io.Writer; + +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * Bridge so that {@link WikiPrinter} can be used in a tools supporting {@link Writer} api. + * + * @version $Id$ + */ +public class WikiWriter extends Writer { + + public WikiWriter(WikiPrinter printer) { + super(printer); + } + + public void setWikiPrinter(WikiPrinter printer) { + this.lock = printer; + } + + public WikiPrinter getWikiPrinter() { + return (WikiPrinter) this.lock; + } + + /** + * {@inheritDoc} + * + * @see java.io.Writer#close() + */ + @Override + public void close() throws IOException { + // WikiPrinter does not support stream close + } + + /** + * {@inheritDoc} + * + * @see java.io.Writer#flush() + */ + @Override + public void flush() throws IOException { + // WikiPrinter does not support stream flush + } + + /** + * {@inheritDoc} + * + * @see java.io.Writer#write(char[], int, int) + */ + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + getWikiPrinter().print(new String(cbuf, off, len)); + } + + /** + * {@inheritDoc} + *

+ * Override it to improve speed a little. Otherwise the String is transformed in char table passed + * to the over + * methods which recreate a String. + * + * @see java.io.Writer#write(java.lang.String) + */ + @Override + public void write(String str) throws IOException { + getWikiPrinter().print(str); + } + +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/XHTMLWriter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/XHTMLWriter.java new file mode 100644 index 000000000..5be64c032 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/renderer/printer/XHTMLWriter.java @@ -0,0 +1,62 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.renderer.printer; + +import java.io.UnsupportedEncodingException; +import java.io.Writer; + +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; + +/** + * XHTMLWriter is an helper to configure XMLWriter to format a DOM4J tree as XHTML. + * + * @version $Id$ + */ +public class XHTMLWriter extends XMLWriter { + + protected static final OutputFormat DEFAULT_XHTML_FORMAT; + + static { + DEFAULT_XHTML_FORMAT = new OutputFormat(); + DEFAULT_XHTML_FORMAT.setXHTML(true); + } + + public XHTMLWriter(Writer writer) throws UnsupportedEncodingException { + super(writer, DEFAULT_XHTML_FORMAT); + + // escape all non US-ASCII to have as less encoding problems as possible + setMaximumAllowedCharacter(-1); + } + + /** + * Escapes a string to be used as an attribute value. Unlike the original method in + * {@link XMLWriter}, apostrophes + * are replaced by a numerical entity &#38;, since &apos; is not valid in HTML documents. + * + * @param text + * the attribute value to escape + * @return the text with all occurrences of special XML characters replaced by entity references. + */ + @Override + protected String escapeAttributeEntities(String text) { + return super.escapeAttributeEntities(text).replace("'", "&"); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/syntax/DefaultSyntaxFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/syntax/DefaultSyntaxFactory.java new file mode 100644 index 000000000..44fbd29b8 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/syntax/DefaultSyntaxFactory.java @@ -0,0 +1,69 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.syntax; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.logging.AbstractLogEnabled; +import org.xwiki.rendering.parser.ParseException; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.syntax.SyntaxFactory; +import org.xwiki.rendering.syntax.SyntaxType; + +/** + * @version $Id$ + * @since 1.5M2 + */ +@Component +public class DefaultSyntaxFactory extends AbstractLogEnabled implements SyntaxFactory { + + /** + * Used to cut the syntax identifier into syntax name and syntax version. + */ + private static final Pattern SYNTAX_PATTERN = Pattern.compile("(.*)\\/(.*)"); + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.syntax.SyntaxFactory#createSyntaxFromIdString(java.lang.String) + */ + public Syntax createSyntaxFromIdString(String syntaxIdAsString) throws ParseException { + if (syntaxIdAsString == null) { + throw new ParseException("The passed Syntax cannot be NULL"); + } + + Matcher matcher = SYNTAX_PATTERN.matcher(syntaxIdAsString); + if (!matcher.matches()) { + throw new ParseException("Invalid Syntax format [" + syntaxIdAsString + "]"); + } + + String syntaxId = matcher.group(1); + String version = matcher.group(2); + + // Use the id as both the human readable name and the technical id (since the syntax string + // doesn't contain + // any information about the pretty name of a syntax type). + SyntaxType syntaxType = new SyntaxType(syntaxId, syntaxId); + + return new Syntax(syntaxType, version); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManager.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManager.java new file mode 100644 index 000000000..63f1f519b --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManager.java @@ -0,0 +1,86 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.transformation; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.annotation.Requirement; +import org.xwiki.component.logging.AbstractLogEnabled; +import org.xwiki.rendering.block.Block; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.configuration.RenderingConfiguration; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.transformation.Transformation; +import org.xwiki.rendering.transformation.TransformationContext; +import org.xwiki.rendering.transformation.TransformationException; +import org.xwiki.rendering.transformation.TransformationManager; + +/** + * Calls all existing transformations (executed by priority) on an existing XDOM object to generate + * a new transformed + * XDOM. + * + * @version $Id$ + * @since 1.5M2 + */ +@Component +public class DefaultTransformationManager extends AbstractLogEnabled + implements TransformationManager { + + /** + * Used to get the ordered list of transformations to execute. + */ + @Requirement + private RenderingConfiguration configuration; + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.transformation.TransformationManager#performTransformations(org.xwiki.rendering.block.XDOM, + * org.xwiki.rendering.syntax.Syntax) + */ + public void performTransformations(XDOM dom, Syntax syntax) throws TransformationException { + performTransformations(dom, new TransformationContext(dom, syntax)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.transformation.TransformationManager#performTransformations(org.xwiki.rendering.block.Block, + * org.xwiki.rendering.transformation.TransformationContext) + */ + public void performTransformations(Block block, TransformationContext context) + throws TransformationException { + boolean error = false; + for (Transformation transformation : this.configuration.getTransformations()) { + try { + transformation.transform(block, context); + } catch (Exception e) { + // Continue running the other transformations + getLogger().error("Failed to execute transformation", e); + error = true; + } + } + if (error) { + throw new TransformationException( + "One or several transformations failed to execute properly. " + + "See the logs for details."); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/CompositeListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/CompositeListener.java new file mode 100644 index 000000000..ee46591b3 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/CompositeListener.java @@ -0,0 +1,626 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Send events to a list of {@link Listener}s. + * + * @version $Id$ + * @since 2.1M1 + */ +public class CompositeListener implements Listener { + + /** + * The listeners. + */ + private List listeners = new ArrayList(); + + /** + * Add a nex listener to the list. + * + * @param listener + * a listener + */ + public void addListener(Listener listener) { + this.listeners.add(listener); + } + + /** + * Get listener at the provided position in the list. + * + * @param i + * the index of the listener in the list + * @return the listener + */ + public Listener getListener(int i) { + return this.listeners.get(i); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionDescription() + */ + public void beginDefinitionDescription() { + for (Listener listener : listeners) { + listener.beginDefinitionDescription(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionList(java.util.Map) + */ + public void beginDefinitionList(Map parameters) { + for (Listener listener : listeners) { + listener.beginDefinitionList(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionTerm() + */ + public void beginDefinitionTerm() { + for (Listener listener : listeners) { + listener.beginDefinitionTerm(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDocument(java.util.Map) + */ + public void beginDocument(Map parameters) { + for (Listener listener : listeners) { + listener.beginDocument(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + public void beginFormat(Format format, Map parameters) { + for (Listener listener : listeners) { + listener.beginFormat(format, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginGroup(java.util.Map) + */ + public void beginGroup(Map parameters) { + for (Listener listener : listeners) { + listener.beginGroup(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + public void beginHeader(HeaderLevel level, String id, Map parameters) { + for (Listener listener : listeners) { + listener.beginHeader(level, id, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void beginList(ListType listType, Map parameters) { + for (Listener listener : listeners) { + listener.beginList(listType, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginListItem() + */ + public void beginListItem() { + for (Listener listener : listeners) { + listener.beginListItem(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void beginMacroMarker(String name, Map macroParameters, String content, + boolean isInline) { + for (Listener listener : listeners) { + listener.beginMacroMarker(name, macroParameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginParagraph(java.util.Map) + */ + public void beginParagraph(Map parameters) { + for (Listener listener : listeners) { + listener.beginParagraph(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotation(java.util.Map) + */ + public void beginQuotation(Map parameters) { + for (Listener listener : listeners) { + listener.beginQuotation(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotationLine() + */ + public void beginQuotationLine() { + for (Listener listener : listeners) { + listener.beginQuotationLine(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginSection(java.util.Map) + */ + public void beginSection(Map parameters) { + for (Listener listener : listeners) { + listener.beginSection(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTable(java.util.Map) + */ + public void beginTable(Map parameters) { + for (Listener listener : listeners) { + listener.beginTable(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableCell(java.util.Map) + */ + public void beginTableCell(Map parameters) { + for (Listener listener : listeners) { + listener.beginTableCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableHeadCell(java.util.Map) + */ + public void beginTableHeadCell(Map parameters) { + for (Listener listener : listeners) { + listener.beginTableHeadCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableRow(java.util.Map) + */ + public void beginTableRow(Map parameters) { + for (Listener listener : listeners) { + listener.beginTableRow(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionDescription() + */ + public void endDefinitionDescription() { + for (Listener listener : listeners) { + listener.endDefinitionDescription(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionList(java.util.Map) + */ + public void endDefinitionList(Map parameters) { + for (Listener listener : listeners) { + listener.endDefinitionList(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionTerm() + */ + public void endDefinitionTerm() { + for (Listener listener : listeners) { + listener.endDefinitionTerm(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDocument(java.util.Map) + */ + public void endDocument(Map parameters) { + for (Listener listener : listeners) { + listener.endDocument(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + public void endFormat(Format format, Map parameters) { + for (Listener listener : listeners) { + listener.endFormat(format, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endGroup(java.util.Map) + */ + public void endGroup(Map parameters) { + for (Listener listener : listeners) { + listener.endGroup(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, + * java.util.Map) + */ + public void endHeader(HeaderLevel level, String id, Map parameters) { + for (Listener listener : listeners) { + listener.endHeader(level, id, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void endList(ListType listType, Map parameters) { + for (Listener listener : listeners) { + listener.endList(listType, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endListItem() + */ + public void endListItem() { + for (Listener listener : listeners) { + listener.endListItem(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void endMacroMarker(String name, Map macroParameters, String content, + boolean isInline) { + for (Listener listener : listeners) { + listener.endMacroMarker(name, macroParameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endParagraph(java.util.Map) + */ + public void endParagraph(Map parameters) { + for (Listener listener : listeners) { + listener.endParagraph(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotation(java.util.Map) + */ + public void endQuotation(Map parameters) { + for (Listener listener : listeners) { + listener.endQuotation(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotationLine() + */ + public void endQuotationLine() { + for (Listener listener : listeners) { + listener.endQuotationLine(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endSection(java.util.Map) + */ + public void endSection(Map parameters) { + for (Listener listener : listeners) { + listener.endSection(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTable(java.util.Map) + */ + public void endTable(Map parameters) { + for (Listener listener : listeners) { + listener.endTable(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableCell(java.util.Map) + */ + public void endTableCell(Map parameters) { + for (Listener listener : listeners) { + listener.endTableCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableHeadCell(java.util.Map) + */ + public void endTableHeadCell(Map parameters) { + for (Listener listener : listeners) { + listener.endTableHeadCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableRow(java.util.Map) + */ + public void endTableRow(Map parameters) { + for (Listener listener : listeners) { + listener.endTableRow(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onEmptyLines(int) + */ + public void onEmptyLines(int count) { + for (Listener listener : listeners) { + listener.onEmptyLines(count); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onHorizontalLine(java.util.Map) + */ + public void onHorizontalLine(Map parameters) { + for (Listener listener : listeners) { + listener.onHorizontalLine(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onId(java.lang.String) + */ + public void onId(String name) { + for (Listener listener : listeners) { + listener.onId(name); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onMacro(java.lang.String, java.util.Map, + * java.lang.String, boolean) + */ + public void onMacro(String id, Map macroParameters, String content, + boolean isInline) { + for (Listener listener : listeners) { + listener.onMacro(id, macroParameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onNewLine() + */ + public void onNewLine() { + for (Listener listener : listeners) { + listener.onNewLine(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onRawText(java.lang.String, + * org.xwiki.rendering.syntax.Syntax) + */ + public void onRawText(String text, Syntax syntax) { + for (Listener listener : listeners) { + listener.onRawText(text, syntax); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpace() + */ + public void onSpace() { + for (Listener listener : listeners) { + listener.onSpace(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpecialSymbol(char) + */ + public void onSpecialSymbol(char symbol) { + for (Listener listener : listeners) { + listener.onSpecialSymbol(symbol); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onVerbatim(java.lang.String, boolean, java.util.Map) + */ + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + for (Listener listener : listeners) { + listener.onVerbatim(protectedString, isInline, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onWord(java.lang.String) + */ + public void onWord(String word) { + for (Listener listener : listeners) { + listener.onWord(word); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.LinkListener#beginLink(org.xwiki.rendering.listener.reference.ResourceReference + * , boolean, java.util.Map) + * @since 2.5RC1 + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + for (Listener listener : listeners) { + listener.beginLink(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.LinkListener#endLink(ResourceReference , boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + for (Listener listener : listeners) { + listener.endLink(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.ImageListener#onImage(ResourceReference, boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + for (Listener listener : listeners) { + listener.onImage(reference, isFreeStandingURI, parameters); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Format.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Format.java new file mode 100644 index 000000000..b3ddfcfea --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Format.java @@ -0,0 +1,68 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener; + +/** + * Represents a text formatting (bold, italic, etc). + * + * @version $Id$ + * @since 1.6M1 + */ +public enum Format { + /** + * Bold style. + */ + BOLD, + + /** + * Italic style. + */ + ITALIC, + + /** + * Underlined style. + */ + UNDERLINED, + + /** + * Strikedout style. + */ + STRIKEDOUT, + + /** + * Superscript style. + */ + SUPERSCRIPT, + + /** + * Subscript style. + */ + SUBSCRIPT, + + /** + * Monospace style. + */ + MONOSPACE, + + /** + * No style. + */ + NONE +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/HeaderLevel.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/HeaderLevel.java new file mode 100644 index 000000000..abb58b21b --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/HeaderLevel.java @@ -0,0 +1,110 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener; + +/** + * @version $Id$ + * @since 1.5M2 + */ +public enum HeaderLevel { + + /** + * Header of level 1. + */ + LEVEL1, + + /** + * Header of level 2. + */ + LEVEL2, + + /** + * Header of level 3. + */ + LEVEL3, + + /** + * Header of level 4. + */ + LEVEL4, + + /** + * Header of level 5. + */ + LEVEL5, + + /** + * Header of level 6. + */ + LEVEL6; + + /** + * @return the header level as integer + */ + public int getAsInt() { + return this.ordinal() + 1; + } + + /** + * {@inheritDoc} + * + * @see java.lang.Enum#toString() + */ + @Override + public String toString() { + return "" + getAsInt(); + } + + /** + * Convert provided integer into the corresponding header level enum entry. + * + * @param value + * the header level as integer + * @return the header level as enum entry + */ + public static HeaderLevel parseInt(int value) { + HeaderLevel result; + switch (value) { + case 1: + result = HeaderLevel.LEVEL1; + break; + case 2: + result = HeaderLevel.LEVEL2; + break; + case 3: + result = HeaderLevel.LEVEL3; + break; + case 4: + result = HeaderLevel.LEVEL4; + break; + case 5: + result = HeaderLevel.LEVEL5; + break; + case 6: + result = HeaderLevel.LEVEL6; + break; + default: + throw new IllegalArgumentException( + "Invalid level [" + value + "]. Only levels 1 to 6 are allowed."); + } + + return result; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ImageListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ImageListener.java new file mode 100644 index 000000000..57835ede8 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ImageListener.java @@ -0,0 +1,49 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener; + +import java.util.Map; + +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Contains callback events for Images,called when a document has been parsed and when it needs to + * be modified or + * rendered. + * + * @version $Id$ + * @since 1.8RC3 + * @see Listener + */ +public interface ImageListener { + + /** + * An image. + * + * @param reference + * the image reference + * @param isFreeStandingURI + * if true then the image is defined directly as a URI in the text + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/InlineFilterListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/InlineFilterListener.java new file mode 100644 index 000000000..626774f97 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/InlineFilterListener.java @@ -0,0 +1,91 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener; + +import java.util.Map; + +/** + * Wrap a listener and skip begin/endDocument events. + * + * @version $Id$ + * @since 2.7.1 + */ +public class InlineFilterListener extends WrappingListener { + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#beginDocument(java.util.Map) + */ + @Override + public void beginDocument(Map parameters) { + // Disable this event + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + // Disable this event + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#beginSection(java.util.Map) + */ + @Override + public void beginSection(Map parameters) { + // Filter + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#endSection(java.util.Map) + */ + @Override + public void endSection(Map parameters) { + // Filter + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + // Filter + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.WrappingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + // Filter + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/LinkListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/LinkListener.java new file mode 100644 index 000000000..9b80aa6b6 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/LinkListener.java @@ -0,0 +1,66 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener; + +import java.util.Map; + +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Contains callback events for Links, called when a document has been parsed and when it needs to + * be modified or + * rendered. + * + * @version $Id$ + * @since 1.8RC3 + * @see Listener + */ +public interface LinkListener { + + /** + * Start of a link. + * + * @param reference + * the link reference + * @param isFreeStandingURI + * if true then the link is a free standing URI directly in the text + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see ResourceReference + * @since 2.5RC1 + */ + void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters); + + /** + * End of a link. + * + * @param reference + * the link reference + * @param isFreeStandingURI + * if true then the link is a free standing URI directly in the text + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see ResourceReference + * @since 2.5RC1 + */ + void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ListType.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ListType.java new file mode 100644 index 000000000..3b7409149 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/ListType.java @@ -0,0 +1,36 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener; + +/** + * @version $Id$ + * @since 1.5M2 + */ +public enum ListType { + /** + * Each list item start with an incremented number. + */ + NUMBERED, + + /** + * Each list item start with a bullet. + */ + BULLETED +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Listener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Listener.java new file mode 100644 index 000000000..2ee04c98d --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/Listener.java @@ -0,0 +1,506 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener; + +import java.util.Collections; +import java.util.Map; + +import org.xwiki.rendering.syntax.Syntax; + +/** + * Contains callback events called when a document has been parsed and when it needs to be modified + * or rendered. More + * specifically when a document is parsed it generates an {@link org.xwiki.rendering.block.XDOM} + * object. That object has + * a {@link org.xwiki.rendering.block.XDOM#traverse(Listener)} method that accepts a + * {@link Listener} object. For each + * {@link org.xwiki.rendering.block.Block} element found in the document its + * {@link org.xwiki.rendering.block.Block#traverse} method is called leading to the generation of + * events from this + * interface. + *

+ * Here's an example of usage: + *

+ * + *
+ * <code>
+ *   XDOM dom = parser.parse(source);
+ *   MyListener listener = new MyListener(...);
+ *   dom.traverse(listener);
+ *   // At this stage all events have been sent to MyListener.
+ * </code>
+ * 
+ * + * @version $Id$ + * @since 1.5M2 + */ +public interface Listener extends LinkListener, ImageListener { + + /** + * To use when there is no parameters. + */ + Map EMPTY_PARAMETERS = Collections.emptyMap(); + + /** + * Start of the document. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void beginDocument(Map parameters); + + /** + * End of the document. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void endDocument(Map parameters); + + /** + * Start a group of elements. Groups are used to allow using standalone elements in list items, + * table cells, etc. + * They can also be used to set parameters on a group of standalone elements. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @since 1.8.3 + */ + void beginGroup(Map parameters); + + /** + * End of the group. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @since 1.8.3 + */ + void endGroup(Map parameters); + + /** + * End of a text formatting block. + * + * @param format + * the formatting type (bold, italic, etc) + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see Format + */ + void beginFormat(Format format, Map parameters); + + /** + * End of a text formatting block. + * + * @param format + * the formatting type (bold, italic, etc) + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see Format + */ + void endFormat(Format format, Map parameters); + + /** + * Start of a paragraph. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void beginParagraph(Map parameters); + + /** + * End of a paragraph. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void endParagraph(Map parameters); + + /** + * Start of a list. + * + * @param listType + * the type of list (bulleted, numbered, etc) + * @param parameters + * a generic list of parameters for the list. Example: "style"/"background-color: blue" + * @see ListType + */ + void beginList(ListType listType, Map parameters); + + /** + * Start of a definition list. For example in HTML this is the equivalent of <dl>. + * + * @param parameters + * a generic list of parameters for the list. Example: "style"/"background-color: blue" + * @since 2.0RC1 + */ + void beginDefinitionList(Map parameters); + + /** + * End of a list. + * + * @param listType + * the type of list (bulleted, numbered, etc) + * @param parameters + * a generic list of parameters for the list. Example: "style"/"background-color: blue" + * @see ListType + */ + void endList(ListType listType, Map parameters); + + /** + * End of a definition list. For example in HTML this is the equivalent of </dl>. + * + * @param parameters + * a generic list of parameters for the list. Example: "style"/"background-color: blue" + * @since 2.0RC1 + */ + void endDefinitionList(Map parameters); + + /** + * Start of a list item. + */ + void beginListItem(); + + /** + * Start of a definition list term. For example in HTML this is the equivalent of <dt>. + * + * @since 1.6M2 + */ + void beginDefinitionTerm(); + + /** + * Start of a definition list description. For example in HTML this is the equivalent of + * <dd>. + * + * @since 1.6M2 + */ + void beginDefinitionDescription(); + + /** + * End of a list item. + */ + void endListItem(); + + /** + * End of a definition list term. For example in HTML this is the equivalent of </dt>. + * + * @since 1.6M2 + */ + void endDefinitionTerm(); + + /** + * End of a definition list description. For example in HTML this is the equivalent of + * </dd>. + * + * @since 1.6M2 + */ + void endDefinitionDescription(); + + /** + * Start of a table. + * + * @param parameters + * a generic list of parameters for the table. + * @since 1.6M2 + */ + void beginTable(Map parameters); + + /** + * Start of a table row. + * + * @param parameters + * a generic list of parameters for the table row. + * @since 1.6M2 + */ + void beginTableRow(Map parameters); + + /** + * Start of a table cell. + * + * @param parameters + * a generic list of parameters for the table cell. + * @since 1.6M2 + */ + void beginTableCell(Map parameters); + + /** + * Start of a table head cell. + * + * @param parameters + * a generic list of parameters for the table head cell. + * @since 1.6M2 + */ + void beginTableHeadCell(Map parameters); + + /** + * End of a table. + * + * @param parameters + * a generic list of parameters for the table. + * @since 1.6M2 + */ + void endTable(Map parameters); + + /** + * End of a table row. + * + * @param parameters + * a generic list of parameters for the table row. + * @since 1.6M2 + */ + void endTableRow(Map parameters); + + /** + * End of a table cell. + * + * @param parameters + * a generic list of parameters for the table cell. + * @since 1.6M2 + */ + void endTableCell(Map parameters); + + /** + * End of a table head cell. + * + * @param parameters + * a generic list of parameters for the table head cell. + * @since 1.6M2 + */ + void endTableHeadCell(Map parameters); + + /** + * Start of a section. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see org.xwiki.rendering.listener.HeaderLevel + */ + void beginSection(Map parameters); + + /** + * End of a section. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see org.xwiki.rendering.listener.HeaderLevel + */ + void endSection(Map parameters); + + /** + * Start of a header. + * + * @param level + * the header level (1, 2, 3, etc) + * @param id + * the header unique identifier + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see org.xwiki.rendering.listener.HeaderLevel + * @since 1.9M1 + */ + void beginHeader(HeaderLevel level, String id, Map parameters); + + /** + * End of a header. + * + * @param level + * the header level (1, 2, 3, etc) + * @param id + * the header unique identifier + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @see org.xwiki.rendering.listener.HeaderLevel + * @since 1.9M1 + */ + void endHeader(HeaderLevel level, String id, Map parameters); + + /** + * Start of marker containing a macro definition. This is a special that Macro Blocks emits when + * they are executed + * so that it's possible to reconstruct the initial macro syntax even after Macros have been + * executed. This is used + * for exemple by the WYSIWYG editor to let use see the result of executing a macro and still let + * them modify the + * macro definition. + * + * @param name + * the macro name + * @param macroParameters + * the macro parameters + * @param content + * the macro content + * @param isInline + * if true the macro is located in a inline content (like paragraph, etc.) + * @see #onMacro(String, java.util.Map, String, boolean) + */ + void beginMacroMarker(String name, Map macroParameters, String content, + boolean isInline); + + /** + * End of marker containing a macro definition. + * + * @param name + * the macro name + * @param macroParameters + * the macro parameters + * @param content + * the macro content + * @param isInline + * if true the macro is located in a inline content (like paragraph, etc.) + * @see #beginMacroMarker(String, java.util.Map, String, boolean) + */ + void endMacroMarker(String name, Map macroParameters, String content, + boolean isInline); + + /** + * Start of a quotation. There are one or several quotation lines inside a quotation block. + * + * @param parameters + * a generic list of parameters for the quotation. Example: "style"/"background-color: + * blue" + */ + void beginQuotation(Map parameters); + + /** + * End of a quotation. + * + * @param parameters + * a generic list of parameters for the quotation. Example: "style"/"background-color: + * blue" + */ + void endQuotation(Map parameters); + + /** + * Start of a quotation line. There can be several quotation lines in a quotation block. + */ + void beginQuotationLine(); + + /** + * End of a quotation line. + */ + void endQuotationLine(); + + /** + * A new line or line break (it's up to the renderers to decide if it should be outputted as a new + * line or as a line + * break in the given syntax). + */ + void onNewLine(); + + /** + * A {@link org.xwiki.rendering.macro.Macro} by itself on a line (ie not inside another Block). + * + * @param id + * the macro id (eg "toc" for the TOC macro) + * @param macroParameters + * the macro parameters + * @param content + * the macro content + * @param isInline + * if true the macro is located in a inline content (like paragraph, etc.) + * @since 1.6M2 + */ + void onMacro(String id, Map macroParameters, String content, boolean isInline); + + /** + * A word. Note that sentences ar broken into different events: word events, special symbols + * events, space events, + * etc. This allows fine-grained actions for listeners. + * + * @param word + * the word encountered + */ + void onWord(String word); + + /** + * A space. + */ + void onSpace(); + + /** + * A special symbol ("*", "<", ">", "=", quote, etc). Any non alpha numeric character is a special + * symbol. + * + * @param symbol + * the symbol encountered + */ + void onSpecialSymbol(char symbol); + + /** + * A reference/location in a page. In HTML for example this is called an Anchor. It allows + * pointing to that + * location, for example in links. Note that there is no wiki syntax for this in general and it's + * often generated by + * Macros (such as the TOC Macro). + * + * @param name + * the location name. + * @since 1.6M1 + */ + void onId(String name); + + /** + * Represents an horizontal line. + * + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + * @since 1.6M1 + */ + void onHorizontalLine(Map parameters); + + /** + * Represents an empty line between 2 standalone Blocks. A standalone block is block that is not + * included in another + * block. Standalone blocks are Paragraph, Standalone Macro, Lists, Table, etc. + * + * @param count + * the number of empty lines between 2 standalone Blocks + */ + void onEmptyLines(int count); + + /** + * A portion of text. + * + * @param protectedString + * the string to protected from rendering + * @param isInline + * if true the text content is located in a inline content (like paragraph, etc.) + * @param parameters + * a generic list of parameters. Example: style="background-color: blue" + */ + void onVerbatim(String protectedString, boolean isInline, Map parameters); + + /** + * Some text to inject directly into the listener output without parsing it. For example a HTML + * macro could inject + * directly some HTML entered by the user into the rendered HTML output. Note that it's not + * recommended to use this + * event in most cases since it can lead to invalid content being generated and in addition most + * listener + * implementations will not understand the injected text and will just ignore it. + * + * @param rawContent + * the text to inject + * @param syntax + * the syntax in which the text is written. This is useful so that listener + * implementations can decide + * whether they can handle direct inject for that syntax + */ + void onRawText(String rawContent, Syntax syntax); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/QueueListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/QueueListener.java new file mode 100644 index 000000000..6e0353e74 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/QueueListener.java @@ -0,0 +1,576 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener; + +import java.util.LinkedList; +import java.util.Map; + +import org.xwiki.rendering.listener.chaining.EventType; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Manage a {@link java.util.Queue} of events. + * + * @version $Id$ + * @since 2.1M1 + */ +public class QueueListener extends LinkedList implements Listener { + + /** + * Class ID for serialization. + */ + private static final long serialVersionUID = 2869508092440006345L; + + /** + * An event. + * + * @version $Id$ + */ + public class Event { + + /** + * The type of the event. + */ + public EventType eventType; + + /** + * The parameters of the event. + */ + public Object[] eventParameters; + + /** + * @param eventType + * the type of the event + * @param eventParameters + * the parameters of the event + */ + public Event(EventType eventType, Object[] eventParameters) { + this.eventType = eventType; + this.eventParameters = eventParameters; + } + } + + /** + * Returns the event at the specified position in this queue. + * + * @param depth + * index of event to return. + * @return the evnet at the specified position in this queue. + */ + public Event getEvent(int depth) { + Event event = null; + + if (depth > 0 && size() > depth - 1) { + event = get(depth - 1); + } + + return event; + } + + /** + * Send all stored events to provided {@link Listener}. + * + * @param listener + * the {@link Listener} on which to send events + */ + public void consumeEvents(Listener listener) { + while (!isEmpty()) { + Event event = remove(); + event.eventType.fireEvent(listener, event.eventParameters); + } + } + + /** + * Store provided event. + * + * @param eventType + * the type of the event + * @param objects + * the parameters of the event + */ + private void saveEvent(EventType eventType, Object... objects) { + offer(new Event(eventType, objects)); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionDescription() + */ + public void beginDefinitionDescription() { + saveEvent(EventType.BEGIN_DEFINITION_DESCRIPTION); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void beginDefinitionList(Map parameters) { + saveEvent(EventType.BEGIN_DEFINITION_LIST, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionTerm() + */ + public void beginDefinitionTerm() { + saveEvent(EventType.BEGIN_DEFINITION_TERM); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDocument(java.util.Map) + */ + public void beginDocument(Map parameters) { + saveEvent(EventType.BEGIN_DOCUMENT, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginGroup(Map) + */ + public void beginGroup(Map parameters) { + saveEvent(EventType.BEGIN_GROUP, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + public void beginFormat(Format format, Map parameters) { + saveEvent(EventType.BEGIN_FORMAT, format, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + public void beginHeader(HeaderLevel level, String id, Map parameters) { + saveEvent(EventType.BEGIN_HEADER, level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginLink(ResourceReference , boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + saveEvent(EventType.BEGIN_LINK, reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void beginList(ListType listType, Map parameters) { + saveEvent(EventType.BEGIN_LIST, listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginListItem() + */ + public void beginListItem() { + saveEvent(EventType.BEGIN_LIST_ITEM); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void beginMacroMarker(String name, Map parameters, String content, + boolean isInline) { + saveEvent(EventType.BEGIN_MACRO_MARKER, name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginParagraph(java.util.Map) + */ + public void beginParagraph(Map parameters) { + saveEvent(EventType.BEGIN_PARAGRAPH, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotation(java.util.Map) + */ + public void beginQuotation(Map parameters) { + saveEvent(EventType.BEGIN_QUOTATION, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotationLine() + */ + public void beginQuotationLine() { + saveEvent(EventType.BEGIN_QUOTATION_LINE); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginSection(java.util.Map) + */ + public void beginSection(Map parameters) { + saveEvent(EventType.BEGIN_SECTION, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTable(java.util.Map) + */ + public void beginTable(Map parameters) { + saveEvent(EventType.BEGIN_TABLE, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableCell(java.util.Map) + */ + public void beginTableCell(Map parameters) { + saveEvent(EventType.BEGIN_TABLE_CELL, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableHeadCell(java.util.Map) + */ + public void beginTableHeadCell(Map parameters) { + saveEvent(EventType.BEGIN_TABLE_HEAD_CELL, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableRow(java.util.Map) + */ + public void beginTableRow(Map parameters) { + saveEvent(EventType.BEGIN_TABLE_ROW, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionDescription() + */ + public void endDefinitionDescription() { + saveEvent(EventType.END_DEFINITION_DESCRIPTION); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void endDefinitionList(Map parameters) { + saveEvent(EventType.END_DEFINITION_LIST, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionTerm() + */ + public void endDefinitionTerm() { + saveEvent(EventType.END_DEFINITION_TERM); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDocument(java.util.Map) + */ + public void endDocument(Map parameters) { + saveEvent(EventType.END_DOCUMENT, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endGroup(Map) + */ + public void endGroup(Map parameters) { + saveEvent(EventType.END_GROUP, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + public void endFormat(Format format, Map parameters) { + saveEvent(EventType.END_FORMAT, format, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, + * java.util.Map) + */ + public void endHeader(HeaderLevel level, String id, Map parameters) { + saveEvent(EventType.END_HEADER, level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endLink(ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + saveEvent(EventType.END_LINK, reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void endList(ListType listType, Map parameters) { + saveEvent(EventType.END_LIST, listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endListItem() + */ + public void endListItem() { + saveEvent(EventType.END_LIST_ITEM); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void endMacroMarker(String name, Map parameters, String content, + boolean isInline) { + saveEvent(EventType.END_MACRO_MARKER, name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endParagraph(java.util.Map) + */ + public void endParagraph(Map parameters) { + saveEvent(EventType.END_PARAGRAPH, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotation(java.util.Map) + */ + public void endQuotation(Map parameters) { + saveEvent(EventType.END_QUOTATION, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotationLine() + */ + public void endQuotationLine() { + saveEvent(EventType.END_QUOTATION_LINE); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endSection(java.util.Map) + */ + public void endSection(Map parameters) { + saveEvent(EventType.END_SECTION, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTable(java.util.Map) + */ + public void endTable(Map parameters) { + saveEvent(EventType.END_TABLE, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableCell(java.util.Map) + */ + public void endTableCell(Map parameters) { + saveEvent(EventType.END_TABLE_CELL, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableHeadCell(java.util.Map) + */ + public void endTableHeadCell(Map parameters) { + saveEvent(EventType.END_TABLE_HEAD_CELL, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableRow(java.util.Map) + */ + public void endTableRow(Map parameters) { + saveEvent(EventType.END_TABLE_ROW, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onRawText(String, Syntax) + */ + public void onRawText(String text, Syntax syntax) { + saveEvent(EventType.ON_RAW_TEXT, text, syntax); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onEmptyLines(int) + */ + public void onEmptyLines(int count) { + saveEvent(EventType.ON_EMPTY_LINES, count); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onHorizontalLine(java.util.Map) + */ + public void onHorizontalLine(Map parameters) { + saveEvent(EventType.ON_HORIZONTAL_LINE, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onId(java.lang.String) + */ + public void onId(String name) { + saveEvent(EventType.ON_ID, name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onImage(ResourceReference, boolean, java.util.Map) + * @since 2.5RC1 + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + saveEvent(EventType.ON_IMAGE, reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onMacro(java.lang.String, java.util.Map, + * java.lang.String, boolean) + */ + public void onMacro(String id, Map parameters, String content, boolean isInline) { + saveEvent(EventType.ON_MACRO, id, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onNewLine() + */ + public void onNewLine() { + saveEvent(EventType.ON_NEW_LINE); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpace() + */ + public void onSpace() { + saveEvent(EventType.ON_SPACE); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpecialSymbol(char) + */ + public void onSpecialSymbol(char symbol) { + saveEvent(EventType.ON_SPECIAL_SYMBOL, symbol); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onVerbatim(String, boolean, Map) + */ + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + saveEvent(EventType.ON_VERBATIM, protectedString, isInline, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onWord(java.lang.String) + */ + public void onWord(String word) { + saveEvent(EventType.ON_WORD, word); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/WrappingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/WrappingListener.java new file mode 100644 index 000000000..1d5bdc982 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/WrappingListener.java @@ -0,0 +1,524 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener; + +import java.util.Map; + +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.syntax.Syntax; + +/** + * A Listener wrapping another Listener. + * + * @version $Id$ + */ +public class WrappingListener implements Listener { + + /** + * The Listener to wrap. + */ + private Listener listener; + + /** + * @param listener + * the Listener to wrap + */ + public void setWrappedListener(Listener listener) { + this.listener = listener; + } + + /** + * @return the Listener to wrap + */ + public Listener getWrappedListener() { + return this.listener; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDocument(java.util.Map) + */ + public void beginDocument(Map parameters) { + this.listener.beginDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDocument(java.util.Map) + */ + public void endDocument(Map parameters) { + this.listener.endDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginGroup(Map) + */ + public void beginGroup(Map parameters) { + this.listener.beginGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endGroup(Map) + */ + public void endGroup(Map parameters) { + this.listener.endGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginFormat(Format, Map) + */ + public void beginFormat(Format format, Map parameters) { + this.listener.beginFormat(format, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void beginList(ListType listType, Map parameters) { + this.listener.beginList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginListItem() + */ + public void beginListItem() { + this.listener.beginListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void beginMacroMarker(String name, Map parameters, String content, + boolean isInline) { + this.listener.beginMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginParagraph(java.util.Map) + */ + public void beginParagraph(Map parameters) { + this.listener.beginParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginSection(java.util.Map) + */ + public void beginSection(Map parameters) { + this.listener.beginSection(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + public void beginHeader(HeaderLevel level, String id, Map parameters) { + this.listener.beginHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endFormat(Format, Map) + */ + public void endFormat(Format format, Map parameters) { + this.listener.endFormat(format, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + public void endList(ListType listType, Map parameters) { + this.listener.endList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endListItem() + */ + public void endListItem() { + this.listener.endListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endMacroMarker(java.lang.String, java.util.Map, + * java.lang.String, + * boolean) + */ + public void endMacroMarker(String name, Map parameters, String content, + boolean isInline) { + this.listener.endMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endParagraph(java.util.Map) + */ + public void endParagraph(Map parameters) { + this.listener.endParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endSection(java.util.Map) + */ + public void endSection(Map parameters) { + this.listener.endSection(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, + * java.util.Map) + */ + public void endHeader(HeaderLevel level, String id, Map parameters) { + this.listener.endHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.LinkListener#beginLink(ResourceReference , boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.listener.beginLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.LinkListener#endLink(ResourceReference , boolean, + * java.util.Map) + * @since 2.5RC1 + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.listener.endLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onMacro(java.lang.String, java.util.Map, + * java.lang.String, boolean) + */ + public void onMacro(String id, Map parameters, String content, boolean isInline) { + this.listener.onMacro(id, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onNewLine() + */ + public void onNewLine() { + this.listener.onNewLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpace() + */ + public void onSpace() { + this.listener.onSpace(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onSpecialSymbol(char) + */ + public void onSpecialSymbol(char symbol) { + this.listener.onSpecialSymbol(symbol); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onWord(java.lang.String) + */ + public void onWord(String word) { + this.listener.onWord(word); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onId(java.lang.String) + */ + public void onId(String name) { + this.listener.onId(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onHorizontalLine(Map) + */ + public void onHorizontalLine(Map parameters) { + this.listener.onHorizontalLine(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onEmptyLines(int) + */ + public void onEmptyLines(int count) { + this.listener.onEmptyLines(count); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onVerbatim(String, boolean, Map) + */ + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.listener.onVerbatim(protectedString, isInline, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onRawText(String, Syntax) + */ + public void onRawText(String text, Syntax syntax) { + this.listener.onRawText(text, syntax); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void beginDefinitionList(Map parameters) { + this.listener.beginDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void endDefinitionList(Map parameters) { + this.listener.endDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see Listener#beginDefinitionTerm() + * @since 1.6M2 + */ + public void beginDefinitionTerm() { + this.listener.beginDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see Listener#beginDefinitionDescription() + * @since 1.6M2 + */ + public void beginDefinitionDescription() { + this.listener.beginDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see Listener#endDefinitionTerm() + * @since 1.6M2 + */ + public void endDefinitionTerm() { + this.listener.endDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see Listener#endDefinitionDescription() + * @since 1.6M2 + */ + public void endDefinitionDescription() { + this.listener.endDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see Listener#beginQuotation(java.util.Map) + * @since 1.6M2 + */ + public void beginQuotation(Map parameters) { + this.listener.beginQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see Listener#endQuotation(java.util.Map) + * @since 1.6M2 + */ + public void endQuotation(Map parameters) { + this.listener.endQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginQuotationLine() + * @since 1.6M2 + */ + public void beginQuotationLine() { + this.listener.beginQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endQuotationLine() + * @since 1.6M2 + */ + public void endQuotationLine() { + this.listener.endQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTable(java.util.Map) + */ + public void beginTable(Map parameters) { + this.listener.beginTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableCell(java.util.Map) + */ + public void beginTableCell(Map parameters) { + this.listener.beginTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableHeadCell(java.util.Map) + */ + public void beginTableHeadCell(Map parameters) { + this.listener.beginTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginTableRow(java.util.Map) + */ + public void beginTableRow(Map parameters) { + this.listener.beginTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTable(java.util.Map) + */ + public void endTable(Map parameters) { + this.listener.endTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableCell(java.util.Map) + */ + public void endTableCell(Map parameters) { + this.listener.endTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableHeadCell(java.util.Map) + */ + public void endTableHeadCell(Map parameters) { + this.listener.endTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endTableRow(java.util.Map) + */ + public void endTableRow(Map parameters) { + this.listener.endTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#onImage(ResourceReference, boolean, java.util.Map) + * @since 2.5RC1 + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.listener.onImage(reference, isFreeStandingURI, parameters); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/AbstractChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/AbstractChainingListener.java new file mode 100644 index 000000000..6b8e74ce0 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/AbstractChainingListener.java @@ -0,0 +1,661 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import java.util.Map; + +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Default and basic implementation of a chaining listener that knows how to delegate event calls to + * the next listener + * in the chain. + * + * @version $Id$ + * @since 1.8RC1 + */ +public abstract class AbstractChainingListener implements ChainingListener { + + /** + * The chain to use to know the next listener to call on events. + */ + private ListenerChain listenerChain; + + /** + * @param listenerChain + * see {@link #getListenerChain()} + * @since 2.0M3 + */ + public void setListenerChain(ListenerChain listenerChain) { + this.listenerChain = listenerChain; + } + + /** + * @return the listener chain used to know the next listener to call on events + */ + public ListenerChain getListenerChain() { + return this.listenerChain; + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginDefinitionDescription() + */ + public void beginDefinitionDescription() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginDefinitionDescription(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void beginDefinitionList(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginDefinitionList(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginDefinitionTerm() + */ + public void beginDefinitionTerm() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginDefinitionTerm(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#beginDocument(java.util.Map) + */ + public void beginDocument(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginDocument(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginGroup(Map) + */ + public void beginGroup(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginGroup(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginFormat(Format, Map) + */ + public void beginFormat(Format format, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginFormat(format, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginHeader(HeaderLevel, String, Map) + */ + public void beginHeader(HeaderLevel level, String id, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginHeader(level, id, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginLink(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, Map) + * @since 2.5RC1 + */ + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginLink(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginList(ListType, Map) + */ + public void beginList(ListType listType, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginList(listType, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginListItem() + */ + public void beginListItem() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginListItem(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginMacroMarker(String, Map, String, boolean) + */ + public void beginMacroMarker(String name, Map parameters, String content, + boolean isInline) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginMacroMarker(name, parameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginParagraph(Map) + */ + public void beginParagraph(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginParagraph(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginQuotation(Map) + */ + public void beginQuotation(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginQuotation(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginQuotationLine() + */ + public void beginQuotationLine() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginQuotationLine(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginSection(Map) + */ + public void beginSection(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginSection(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginTable(Map) + */ + public void beginTable(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginTable(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginTableCell(Map) + */ + public void beginTableCell(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginTableCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginTableHeadCell(Map) + */ + public void beginTableHeadCell(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginTableHeadCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#beginTableRow(Map) + */ + public void beginTableRow(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.beginTableRow(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endDefinitionDescription() + */ + public void endDefinitionDescription() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endDefinitionDescription(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + public void endDefinitionList(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endDefinitionList(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endDefinitionTerm() + */ + public void endDefinitionTerm() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endDefinitionTerm(); + } + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.Listener#endDocument(java.util.Map) + */ + public void endDocument(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endDocument(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endGroup(Map) + */ + public void endGroup(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endGroup(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endFormat(Format, Map) + */ + public void endFormat(Format format, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endFormat(format, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endHeader(HeaderLevel, String, Map) + */ + public void endHeader(HeaderLevel level, String id, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endHeader(level, id, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endLink(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, Map) + * @since 2.5RC1 + */ + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endLink(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endList(ListType, Map) + */ + public void endList(ListType listType, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endList(listType, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endListItem() + */ + public void endListItem() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endListItem(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endMacroMarker(String, Map, String, boolean) + */ + public void endMacroMarker(String name, Map parameters, String content, + boolean isInline) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endMacroMarker(name, parameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endParagraph(Map) + */ + public void endParagraph(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endParagraph(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endQuotation(Map) + */ + public void endQuotation(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endQuotation(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endQuotationLine() + */ + public void endQuotationLine() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endQuotationLine(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endSection(Map) + */ + public void endSection(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endSection(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endTable(Map) + */ + public void endTable(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endTable(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endTableCell(Map) + */ + public void endTableCell(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endTableCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endTableHeadCell(Map) + */ + public void endTableHeadCell(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endTableHeadCell(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#endTableRow(Map) + */ + public void endTableRow(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.endTableRow(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onEmptyLines(int) + */ + public void onEmptyLines(int count) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onEmptyLines(count); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onHorizontalLine(Map) + */ + public void onHorizontalLine(Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onHorizontalLine(parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onId(String) + */ + public void onId(String name) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onId(name); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onImage(org.xwiki.rendering.listener.reference.ResourceReference , + * boolean, java.util.Map) + * @since 2.5RC1 + */ + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onImage(reference, isFreeStandingURI, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onMacro(String, Map, String, boolean) + */ + public void onMacro(String id, Map parameters, String content, boolean isInline) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onMacro(id, parameters, content, isInline); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onNewLine() + */ + public void onNewLine() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onNewLine(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onSpace() + */ + public void onSpace() { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onSpace(); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onSpecialSymbol(char) + */ + public void onSpecialSymbol(char symbol) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onSpecialSymbol(symbol); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onVerbatim(String, boolean, Map) + */ + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onVerbatim(protectedString, isInline, parameters); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onWord(String) + */ + public void onWord(String word) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onWord(word); + } + } + + /** + * {@inheritDoc} + * + * @see ChainingListener#onRawText(String, Syntax) + */ + public void onRawText(String text, Syntax syntax) { + ChainingListener next = getListenerChain().getNextListener(getClass()); + if (next != null) { + next.onRawText(text, syntax); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/BlockStateChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/BlockStateChainingListener.java new file mode 100644 index 000000000..9332bedc5 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/BlockStateChainingListener.java @@ -0,0 +1,790 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import java.util.Map; +import java.util.Stack; + +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Indicates block element for which we are inside and previous blocks. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class BlockStateChainingListener extends AbstractChainingListener + implements StackableChainingListener { + + public enum Event { + NONE, DEFINITION_DESCRIPTION, DEFINITION_TERM, DEFINITION_LIST, DOCUMENT, FORMAT, HEADER, LINK, LIST, LIST_ITEM, MACRO_MARKER, PARAGRAPH, QUOTATION, QUOTATION_LINE, SECTION, TABLE, TABLE_CELL, TABLE_HEAD_CELL, TABLE_ROW, RAW_TEXT, EMPTY_LINES, HORIZONTAL_LINE, ID, IMAGE, NEW_LINE, SPACE, SPECIAL_SYMBOL, MACRO, VERBATIM_INLINE, VERBATIM_STANDALONE, WORD + } + + private Event previousEvent = Event.NONE; + + private int inlineDepth; + + private boolean isInParagraph; + + private boolean isInHeader; + + private int linkDepth; + + private boolean isInTable; + + private boolean isInTableCell; + + private Stack definitionListDepth = new Stack(); + + private Stack listDepth = new Stack(); + + private int quotationDepth; + + private int quotationLineDepth; + + private int quotationLineIndex = -1; + + private int macroDepth; + + private int cellRow = -1; + + private int cellCol = -1; + + public BlockStateChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + /** + * {@inheritDoc} + * + * @see StackableChainingListener#createChainingListenerInstance() + */ + public StackableChainingListener createChainingListenerInstance() { + return new BlockStateChainingListener(getListenerChain()); + } + + public Event getPreviousEvent() { + return this.previousEvent; + } + + public int getInlineDepth() { + return this.inlineDepth; + } + + public boolean isInLine() { + return getInlineDepth() > 0; + } + + public boolean isInParagraph() { + return this.isInParagraph; + } + + public boolean isInHeader() { + return this.isInHeader; + } + + public boolean isInTable() { + return this.isInTable; + } + + public boolean isInTableCell() { + return this.isInTableCell; + } + + public int getCellCol() { + return this.cellCol; + } + + public int getCellRow() { + return this.cellRow; + } + + public int getDefinitionListDepth() { + return this.definitionListDepth.size(); + } + + public boolean isInDefinitionList() { + return getDefinitionListDepth() > 0; + } + + public int getDefinitionListItemIndex() { + return isInDefinitionList() ? this.definitionListDepth.peek().definitionListItemIndex : -1; + } + + public int getListDepth() { + return this.listDepth.size(); + } + + public boolean isInList() { + return getListDepth() > 0; + } + + public int getListItemIndex() { + return isInList() ? this.listDepth.peek().listItemIndex : -1; + } + + public void pushLinkDepth() { + ++this.linkDepth; + } + + public void popLinkDepth() { + --this.linkDepth; + } + + public int getLinkDepth() { + return this.linkDepth; + } + + public boolean isInLink() { + return getLinkDepth() > 0; + } + + public int getQuotationDepth() { + return this.quotationDepth; + } + + public boolean isInQuotation() { + return getQuotationDepth() > 0; + } + + public int getQuotationLineDepth() { + return this.quotationLineDepth; + } + + public boolean isInQuotationLine() { + return getQuotationLineDepth() > 0; + } + + public int getQuotationLineIndex() { + return this.quotationLineIndex; + } + + public int getMacroDepth() { + return this.macroDepth; + } + + public boolean isInMacro() { + return getMacroDepth() > 0; + } + + // Events + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + ++this.inlineDepth; + ++this.definitionListDepth.peek().definitionListItemIndex; + + super.beginDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + this.definitionListDepth.push(new DefinitionListState()); + + super.beginDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + ++this.inlineDepth; + ++this.definitionListDepth.peek().definitionListItemIndex; + + super.beginDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + ++this.linkDepth; + + super.beginLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void beginList(ListType listType, Map parameters) { + this.listDepth.push(new ListState()); + + super.beginList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginListItem() + */ + @Override + public void beginListItem() { + ++this.inlineDepth; + ++this.listDepth.peek().listItemIndex; + + super.beginListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void beginMacroMarker(String name, Map parameters, String content, + boolean isInline) { + ++this.macroDepth; + + super.beginMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + this.isInParagraph = true; + ++this.inlineDepth; + + super.beginParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotation(java.util.Map) + */ + @Override + public void beginQuotation(Map parameters) { + ++this.quotationDepth; + + super.beginQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + ++this.quotationLineDepth; + ++this.inlineDepth; + ++this.quotationLineIndex; + + super.beginQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void beginHeader(HeaderLevel level, String id, Map parameters) { + this.isInHeader = true; + ++this.inlineDepth; + + super.beginHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + this.isInTable = true; + + super.beginTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + ++this.cellRow; + + super.beginTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + this.isInTableCell = true; + ++this.inlineDepth; + ++this.cellCol; + + super.beginTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + this.isInTableCell = true; + ++this.inlineDepth; + ++this.cellCol; + + super.beginTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + super.endDefinitionDescription(); + + --this.inlineDepth; + this.previousEvent = Event.DEFINITION_DESCRIPTION; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void endDefinitionList(Map parameters) { + super.endDefinitionList(parameters); + + this.definitionListDepth.pop(); + + this.previousEvent = Event.DEFINITION_LIST; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + super.endDefinitionTerm(); + + --this.inlineDepth; + this.previousEvent = Event.DEFINITION_TERM; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + this.previousEvent = Event.DOCUMENT; + + super.endDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void endFormat(Format format, Map parameters) { + super.endFormat(format, parameters); + + this.previousEvent = Event.FORMAT; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + super.endLink(reference, isFreeStandingURI, parameters); + + --this.linkDepth; + this.previousEvent = Event.LINK; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void endList(ListType listType, Map parameters) { + super.endList(listType, parameters); + + this.listDepth.pop(); + + this.previousEvent = Event.LIST; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endListItem() + */ + @Override + public void endListItem() { + super.endListItem(); + + --this.inlineDepth; + this.previousEvent = Event.LIST_ITEM; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void endMacroMarker(String name, Map parameters, String content, + boolean isInline) { + super.endMacroMarker(name, parameters, content, isInline); + + this.previousEvent = Event.MACRO_MARKER; + --this.macroDepth; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + super.endParagraph(parameters); + + this.isInParagraph = false; + --this.inlineDepth; + this.previousEvent = Event.PARAGRAPH; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotation(java.util.Map) + */ + @Override + public void endQuotation(Map parameters) { + super.endQuotation(parameters); + + --this.quotationDepth; + if (this.quotationDepth == 0) { + this.quotationLineIndex = -1; + } + this.previousEvent = Event.QUOTATION; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotationLine() + */ + @Override + public void endQuotationLine() { + super.endQuotationLine(); + + --this.quotationLineDepth; + --this.inlineDepth; + this.previousEvent = Event.QUOTATION_LINE; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endSection(java.util.Map) + */ + @Override + public void endSection(Map parameters) { + super.endSection(parameters); + + this.previousEvent = Event.SECTION; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + super.endHeader(level, id, parameters); + + this.isInHeader = false; + --this.inlineDepth; + this.previousEvent = Event.HEADER; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + super.endTable(parameters); + + this.isInTable = false; + this.cellRow = -1; + this.previousEvent = Event.TABLE; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + super.endTableCell(parameters); + + this.isInTableCell = false; + --this.inlineDepth; + this.previousEvent = Event.TABLE_CELL; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + super.endTableHeadCell(parameters); + + this.isInTableCell = false; + --this.inlineDepth; + this.previousEvent = Event.TABLE_HEAD_CELL; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableRow(java.util.Map) + */ + @Override + public void endTableRow(Map parameters) { + super.endTableRow(parameters); + + this.previousEvent = Event.TABLE_ROW; + this.cellCol = -1; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onRawText(String, Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + super.onRawText(text, syntax); + + this.previousEvent = Event.RAW_TEXT; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + this.previousEvent = Event.EMPTY_LINES; + + super.onEmptyLines(count); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + this.previousEvent = Event.HORIZONTAL_LINE; + + super.onHorizontalLine(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onId(java.lang.String) + */ + @Override + public void onId(String name) { + this.previousEvent = Event.ID; + + super.onId(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.previousEvent = Event.IMAGE; + + super.onImage(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onNewLine() + */ + @Override + public void onNewLine() { + this.previousEvent = Event.NEW_LINE; + + super.onNewLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpace() + */ + @Override + public void onSpace() { + this.previousEvent = Event.SPACE; + + super.onSpace(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + this.previousEvent = Event.SPECIAL_SYMBOL; + + super.onSpecialSymbol(symbol); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.previousEvent = Event.VERBATIM_STANDALONE; + + super.onVerbatim(protectedString, isInline, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onWord(java.lang.String) + */ + @Override + public void onWord(String word) { + this.previousEvent = Event.WORD; + + super.onWord(word); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onMacro(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + this.previousEvent = Event.MACRO; + + super.onMacro(id, parameters, content, isInline); + } + + private static class ListState { + + public int listItemIndex = -1; + } + + private static class DefinitionListState { + + public int definitionListItemIndex = -1; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ChainingListener.java new file mode 100644 index 000000000..e1081c6d6 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ChainingListener.java @@ -0,0 +1,38 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import org.xwiki.rendering.listener.Listener; + +/** + * A listener that can be chained with other chaining listeners using a chain. This allows creating + * listeners to filter + * some events, to aggregate state information in a decoupled manner, to perform lookaheads, etc. + * + * @version $Id$ + * @since 1.8RC1 + */ +public interface ChainingListener extends Listener { + + /** + * @return the chain this listener is part of + */ + ListenerChain getListenerChain(); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ConsecutiveNewLineStateChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ConsecutiveNewLineStateChainingListener.java new file mode 100644 index 000000000..085906294 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ConsecutiveNewLineStateChainingListener.java @@ -0,0 +1,400 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import java.util.Map; + +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Counts consecutive new lines. + * + * @version $Id; $ + * @since 1.8RC1 + */ +public class ConsecutiveNewLineStateChainingListener extends AbstractChainingListener + implements StackableChainingListener { + + /** + * Number of found new lines. + */ + private int newLineCount; + + /** + * @param listenerChain + * see {@link #getListenerChain()} + */ + public ConsecutiveNewLineStateChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + /** + * {@inheritDoc} + * + * @see StackableChainingListener#createChainingListenerInstance() + */ + public StackableChainingListener createChainingListenerInstance() { + return new ConsecutiveNewLineStateChainingListener(getListenerChain()); + } + + /** + * @return the number of found new lines. + */ + public int getNewLineCount() { + return this.newLineCount; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + this.newLineCount = 0; + super.endDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void endDefinitionList(Map parameters) { + this.newLineCount = 0; + super.endDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + this.newLineCount = 0; + super.endDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + this.newLineCount = 0; + super.endDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(Map) + */ + @Override + public void endGroup(Map parameters) { + this.newLineCount = 0; + super.endGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void endFormat(Format format, Map parameters) { + this.newLineCount = 0; + super.endFormat(format, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.newLineCount = 0; + super.endLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void endList(ListType listType, Map parameters) { + this.newLineCount = 0; + super.endList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endListItem() + */ + @Override + public void endListItem() { + this.newLineCount = 0; + super.endListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void endMacroMarker(String name, Map parameters, String content, + boolean isInline) { + this.newLineCount = 0; + super.endMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + this.newLineCount = 0; + super.endParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotation(java.util.Map) + */ + @Override + public void endQuotation(Map parameters) { + this.newLineCount = 0; + super.endQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotationLine() + */ + @Override + public void endQuotationLine() { + this.newLineCount = 0; + super.endQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + this.newLineCount = 0; + super.endHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + this.newLineCount = 0; + super.endTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + this.newLineCount = 0; + super.endTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + this.newLineCount = 0; + super.endTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableRow(java.util.Map) + */ + @Override + public void endTableRow(Map parameters) { + this.newLineCount = 0; + super.endTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onRawText(String, Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + this.newLineCount = 0; + super.onRawText(text, syntax); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + this.newLineCount = 0; + super.onEmptyLines(count); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + this.newLineCount = 0; + super.onHorizontalLine(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onId(java.lang.String) + */ + @Override + public void onId(String name) { + this.newLineCount = 0; + super.onId(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.newLineCount = 0; + super.onImage(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onNewLine() + */ + @Override + public void onNewLine() { + this.newLineCount++; + super.onNewLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpace() + */ + @Override + public void onSpace() { + this.newLineCount = 0; + super.onSpace(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + this.newLineCount = 0; + super.onSpecialSymbol(symbol); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onMacro(String, Map, + * String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + this.newLineCount = 0; + super.onMacro(id, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.newLineCount = 0; + super.onVerbatim(protectedString, isInline, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onWord(java.lang.String) + */ + @Override + public void onWord(String word) { + this.newLineCount = 0; + super.onWord(word); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListener.java new file mode 100644 index 000000000..00b85fc28 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListener.java @@ -0,0 +1,646 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.listener.HeaderLevel; + +import java.util.Map; +import java.util.Stack; + +/** + * Allow knowing if a container block (a block which can have children) has children or not. + * + * @version $Id$ + * @since 2.0M3 + */ +public class EmptyBlockChainingListener extends AbstractChainingListener { + + private Stack containerBlockStates = new Stack(); + + public EmptyBlockChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + public boolean isCurrentContainerBlockEmpty() { + return this.containerBlockStates.peek(); + } + + // Events + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDocument(java.util.Map) + */ + @Override + public void beginDocument(Map parameters) { + startContainerBlock(); + super.beginDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + markNotEmpty(); + startContainerBlock(); + super.beginDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingListener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + markNotEmpty(); + startContainerBlock(); + super.beginDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(java.util.Map) + */ + @Override + public void beginGroup(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingListener#beginFormat(org.xwiki.rendering.listener.Format, java.util.Map) + */ + @Override + public void beginFormat(Format format, Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginFormat(format, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void beginList(ListType listType, Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginListItem() + */ + @Override + public void beginListItem() { + markNotEmpty(); + startContainerBlock(); + super.beginListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void beginMacroMarker(String name, Map parameters, String content, + boolean isInline) { + markNotEmpty(); + startContainerBlock(); + super.beginMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotation(java.util.Map) + */ + @Override + public void beginQuotation(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + markNotEmpty(); + startContainerBlock(); + super.beginQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void beginHeader(HeaderLevel level, String id, Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginSection(java.util.Map) + */ + @Override + public void beginSection(Map parameters) { + markNotEmpty(); + startContainerBlock(); + super.beginSection(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + super.endDocument(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + super.endDefinitionDescription(); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingListener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void endDefinitionList(Map parameters) { + super.endDefinitionList(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + super.endDefinitionTerm(); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see AbstractChainingListener#endFormat(org.xwiki.rendering.listener.Format, java.util.Map) + */ + @Override + public void endFormat(Format format, Map parameters) { + super.endFormat(format, parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(java.util.Map) + */ + @Override + public void endGroup(Map parameters) { + super.endGroup(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + super.endLink(reference, isFreeStandingURI, parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void endList(ListType listType, Map parameters) { + super.endList(listType, parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endListItem() + */ + @Override + public void endListItem() { + super.endListItem(); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void endMacroMarker(String name, Map parameters, String content, + boolean isInline) { + super.endMacroMarker(name, parameters, content, isInline); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + super.endParagraph(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotation(java.util.Map) + */ + @Override + public void endQuotation(Map parameters) { + super.endQuotation(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotationLine() + */ + @Override + public void endQuotationLine() { + super.endQuotationLine(); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endSection(java.util.Map) + */ + @Override + public void endSection(Map parameters) { + super.endSection(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + super.endHeader(level, id, parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + super.endTable(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + super.endTableCell(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + super.endTableHeadCell(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableRow(java.util.Map) + */ + @Override + public void endTableRow(Map parameters) { + super.endTableRow(parameters); + stopContainerBlock(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onRawText(String, + * org.xwiki.rendering.syntax.Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + super.onRawText(text, syntax); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + super.onEmptyLines(count); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + super.onHorizontalLine(parameters); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onId(java.lang.String) + */ + @Override + public void onId(String name) { + super.onId(name); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + super.onImage(reference, isFreeStandingURI, parameters); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onNewLine() + */ + @Override + public void onNewLine() { + super.onNewLine(); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpace() + */ + @Override + public void onSpace() { + super.onSpace(); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + super.onSpecialSymbol(symbol); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + super.onVerbatim(protectedString, isInline, parameters); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onWord(java.lang.String) + */ + @Override + public void onWord(String word) { + super.onWord(word); + markNotEmpty(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onMacro(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + super.onMacro(id, parameters, content, isInline); + markNotEmpty(); + } + + private void startContainerBlock() { + this.containerBlockStates.push(Boolean.TRUE); + } + + private void stopContainerBlock() { + this.containerBlockStates.pop(); + } + + private void markNotEmpty() { + if (!this.containerBlockStates.isEmpty() && this.containerBlockStates.peek()) { + this.containerBlockStates.pop(); + this.containerBlockStates.push(Boolean.FALSE); + } + } + +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EventType.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EventType.java new file mode 100644 index 000000000..7af2aec3e --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/EventType.java @@ -0,0 +1,409 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import java.util.Map; + +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.listener.Listener; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Stores event types and offers a way to call a stored event. + * + * @version $Id$ + * @since 1.8RC1 + */ +public enum EventType { + + BEGIN_DOCUMENT { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginDocument((Map) eventParameters[0]); + } + }, + END_DOCUMENT { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endDocument((Map) eventParameters[0]); + } + }, + BEGIN_GROUP { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginGroup((Map) eventParameters[0]); + } + }, + END_GROUP { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endGroup((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_PARAGRAPH { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginParagraph((Map) eventParameters[0]); + } + }, + END_PARAGRAPH { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endParagraph((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_DEFINITION_LIST { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginDefinitionList((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + // This is because for nested definition lists, the event after a definition list item content + // is a new + // definition list + return true; + } + }, + END_DEFINITION_LIST { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endDefinitionList((Map) eventParameters[0]); + } + }, + BEGIN_DEFINITION_TERM { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginDefinitionTerm(); + } + }, + END_DEFINITION_TERM { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endDefinitionTerm(); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_DEFINITION_DESCRIPTION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginDefinitionDescription(); + } + }, + END_DEFINITION_DESCRIPTION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endDefinitionDescription(); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_FORMAT { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginFormat((Format) eventParameters[0], (Map) eventParameters[1]); + } + }, + END_FORMAT { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endFormat((Format) eventParameters[0], (Map) eventParameters[1]); + } + }, + BEGIN_HEADER { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginHeader((HeaderLevel) eventParameters[0], (String) eventParameters[1], + (Map) eventParameters[2]); + } + }, + END_HEADER { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endHeader((HeaderLevel) eventParameters[0], (String) eventParameters[1], + (Map) eventParameters[2]); + } + }, + BEGIN_LINK { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginLink((ResourceReference) eventParameters[0], (Boolean) eventParameters[1], + (Map) eventParameters[2]); + } + }, + END_LINK { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endLink((ResourceReference) eventParameters[0], (Boolean) eventParameters[1], + (Map) eventParameters[2]); + } + }, + BEGIN_LIST { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginList((ListType) eventParameters[0], (Map) eventParameters[1]); + } + + @Override + public boolean isInlineEnd() { + // This is because for nested lists, the event after list item content is a new list + return true; + } + }, + END_LIST { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endList((ListType) eventParameters[0], (Map) eventParameters[1]); + } + }, + BEGIN_LIST_ITEM { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginListItem(); + } + }, + END_LIST_ITEM { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endListItem(); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_MACRO_MARKER { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginMacroMarker((String) eventParameters[0], + (Map) eventParameters[1], + (String) eventParameters[2], (Boolean) eventParameters[3]); + } + }, + END_MACRO_MARKER { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endMacroMarker((String) eventParameters[0], (Map) eventParameters[1], + (String) eventParameters[2], (Boolean) eventParameters[3]); + } + }, + BEGIN_QUOTATION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginQuotation((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + // This is because for nested quotations, the event after a quotation line is a new quotation + return true; + } + }, + END_QUOTATION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endQuotation((Map) eventParameters[0]); + } + }, + BEGIN_QUOTATION_LINE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginQuotationLine(); + } + }, + END_QUOTATION_LINE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endQuotationLine(); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_SECTION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginSection((Map) eventParameters[0]); + } + }, + END_SECTION { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endSection((Map) eventParameters[0]); + } + }, + BEGIN_TABLE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginTable((Map) eventParameters[0]); + } + }, + END_TABLE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endTable((Map) eventParameters[0]); + } + }, + BEGIN_TABLE_CELL { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginTableCell((Map) eventParameters[0]); + } + }, + END_TABLE_CELL { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endTableCell((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_TABLE_HEAD_CELL { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginTableHeadCell((Map) eventParameters[0]); + } + }, + END_TABLE_HEAD_CELL { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endTableHeadCell((Map) eventParameters[0]); + } + + @Override + public boolean isInlineEnd() { + return true; + } + }, + BEGIN_TABLE_ROW { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.beginTableRow((Map) eventParameters[0]); + } + }, + END_TABLE_ROW { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.endTableRow((Map) eventParameters[0]); + } + }, + ON_RAW_TEXT { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onRawText((String) eventParameters[0], (Syntax) eventParameters[1]); + } + }, + ON_EMPTY_LINES { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onEmptyLines((Integer) eventParameters[0]); + } + }, + ON_HORIZONTAL_LINE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onHorizontalLine((Map) eventParameters[0]); + } + }, + ON_ID { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onId((String) eventParameters[0]); + } + }, + ON_IMAGE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onImage((ResourceReference) eventParameters[0], (Boolean) eventParameters[1], + (Map) eventParameters[2]); + } + }, + ON_MACRO { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onMacro((String) eventParameters[0], (Map) eventParameters[1], + (String) eventParameters[2], (Boolean) eventParameters[3]); + } + }, + ON_NEW_LINE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onNewLine(); + } + }, + ON_SPACE { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onSpace(); + } + }, + ON_SPECIAL_SYMBOL { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onSpecialSymbol((Character) eventParameters[0]); + } + }, + ON_VERBATIM { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onVerbatim((String) eventParameters[0], (Boolean) eventParameters[1], + (Map) eventParameters[2]); + } + }, + ON_WORD { + + public void fireEvent(Listener listener, Object[] eventParameters) { + listener.onWord((String) eventParameters[0]); + } + }; + + public abstract void fireEvent(Listener listener, Object[] eventParameters); + + public boolean isInlineEnd() { + return false; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/GroupStateChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/GroupStateChainingListener.java new file mode 100644 index 000000000..1d26ba5b2 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/GroupStateChainingListener.java @@ -0,0 +1,77 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import java.util.Map; + +/** + * Provides information on whether we're inside a group. Note that this listener is separated from + * the + * {@link org.xwiki.rendering.listener.chaining.BlockStateChainingListener} class because we don't + * want this listener to + * be stackable (since we need to create new instance of stackable listeners to reset states when we + * encounter a begin + * group event but we also need to know we're inside a group). + * + * @version $Id$ + * @since 1.8.3 + */ +public class GroupStateChainingListener extends AbstractChainingListener { + + private int groupDepth = 0; + + public GroupStateChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + public int getDocumentDepth() { + return this.groupDepth; + } + + public boolean isInGroup() { + return this.groupDepth > 0; + } + + // Events + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(Map) + */ + @Override + public void beginGroup(Map parameters) { + ++this.groupDepth; + + super.beginGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(Map) + */ + @Override + public void endGroup(Map parameters) { + super.endGroup(parameters); + + --this.groupDepth; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ListenerChain.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ListenerChain.java new file mode 100644 index 000000000..a99256e6f --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/ListenerChain.java @@ -0,0 +1,172 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +/** + * Stores information about the listeners in the chain and the order in which they need to be + * called. Also sports a + * feature that allows pushing and popping listeners that are stackable. This feature is useful + * since listeners can hold + * stateful information and sometimes you may need to push new versions of them to start with new + * state information. For + * example this is used in the XWiki Syntax Renderer when group event is found to start the + * rendering for that group + * using reset state information. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class ListenerChain { + + /** + * The full list of chaining listeners. For each of them we have a stack since the ones that + * implement the + * {@link StackableChainingListener} interface can be stacked. + */ + private Map, Stack> listeners = new HashMap, Stack>(); + + /** + * The ordered list of listeners. We only allow one instance per listener class name so we just + * need to store the + * class object and then the instance can be found in {@link #listeners}. + */ + private List> nextListeners = new ArrayList>(); + + /** + * @param listener + * the chaining listener to add to the chain. If an instance of that listener is already + * present then we + * stack the new instance instead. + */ + public void addListener(ChainingListener listener) { + // If there's already an entry for that listener then push it on the existing stack + // and don't add the listener as an additional listener in the list (since it's already + // in there). We need to take these steps since the push() methods below will create + // new instances of listeners which will add themselves in the chain automatically. + Stack stack = this.listeners.get(listener.getClass()); + if (stack == null) { + stack = new Stack(); + this.listeners.put(listener.getClass(), stack); + this.nextListeners.add(listener.getClass()); + } + stack.push(listener); + } + + /** + * @param listenerClass + * the listener to remove from the chain + */ + public void removeListener(Class listenerClass) { + this.listeners.remove(listenerClass); + this.nextListeners.remove(listenerClass); + } + + /** + * @param listenerClass + * the listener for which we need to find the next listener in the chain + * @return the next listener in the chain + */ + public ChainingListener getNextListener(Class listenerClass) { + ChainingListener next = null; + int pos = indexOf(listenerClass); + if (pos > -1 && this.nextListeners.size() > pos + 1) { + next = this.listeners.get(this.nextListeners.get(pos + 1)).peek(); + } + return next; + } + + /** + * @param listenerClass + * the listener class for which we want to find the listener instance + * @return the listener instance corresponding to the passed class. Note that the last instance of + * the stack is + * returned + */ + public ChainingListener getListener(Class listenerClass) { + return this.listeners.get(listenerClass).peek(); + } + + /** + * @param listenerClass + * the listener class for which to find the position in the chain + * @return the position in the chain (first position is 0) + */ + public int indexOf(Class listenerClass) { + return this.nextListeners.indexOf(listenerClass); + } + + /** + * Create a new instance of the passed chaining listener if it's stackable (ie it implements the + * {@link org.xwiki.rendering.listener.chaining.StackableChainingListener} interface. This allows + * creating a clean + * state when some sub rendering has to be done with some new state. + * + * @param listenerClass + * the listener class for which to create a new instance (if stackable) + */ + public void pushListener(Class listenerClass) { + if (StackableChainingListener.class.isAssignableFrom(listenerClass)) { + Stack stack = this.listeners.get(listenerClass); + stack.push(((StackableChainingListener) stack.peek()).createChainingListenerInstance()); + } + } + + /** + * Create new instances of all chaining listeners that are stackable (ie that implement the + * {@link org.xwiki.rendering.listener.chaining.StackableChainingListener} interface. This allows + * creating a clean + * state when some sub rendering has to be done with some new state. + */ + public void pushAllStackableListeners() { + for (Class listenerClass : this.listeners.keySet()) { + pushListener(listenerClass); + } + } + + /** + * Remove all pushed stackable listeners to go back to the previous state (see + * {@link #pushAllStackableListeners()}. + */ + public void popAllStackableListeners() { + for (Class listenerClass : this.listeners.keySet()) { + popListener(listenerClass); + } + } + + /** + * Remove the last instance corresponding to the passed listener class if it's stackable, in order + * to go back to the + * previous state. + * + * @param listenerClass + * the class of the chaining listener to pop + */ + public void popListener(Class listenerClass) { + if (StackableChainingListener.class.isAssignableFrom(listenerClass)) { + this.listeners.get(listenerClass).pop(); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListener.java new file mode 100644 index 000000000..074c04692 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListener.java @@ -0,0 +1,637 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import java.util.Map; + +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.listener.QueueListener; +import org.xwiki.rendering.listener.QueueListener.Event; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Stores events without emitting them back in order to accumulate them and to provide a lookahead + * feature. The + * lookahead depth is configurable. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class LookaheadChainingListener extends AbstractChainingListener { + + private QueueListener previousEvents = new QueueListener(); + + private int lookaheadDepth; + + public LookaheadChainingListener(ListenerChain listenerChain, int lookaheadDepth) { + setListenerChain(listenerChain); + this.lookaheadDepth = lookaheadDepth; + } + + public Event getNextEvent() { + return getNextEvent(1); + } + + public Event getNextEvent(int depth) { + return this.previousEvents.getEvent(depth); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + this.previousEvents.beginDefinitionDescription(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + this.previousEvents.beginDefinitionList(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + this.previousEvents.beginDefinitionTerm(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDocument(java.util.Map) + */ + @Override + public void beginDocument(Map parameters) { + this.previousEvents.beginDocument(parameters); + flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(Map) + */ + @Override + public void beginGroup(Map parameters) { + this.previousEvents.beginGroup(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void beginFormat(Format format, Map parameters) { + this.previousEvents.beginFormat(format, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void beginHeader(HeaderLevel level, String id, Map parameters) { + this.previousEvents.beginHeader(level, id, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.previousEvents.beginLink(reference, isFreeStandingURI, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void beginList(ListType listType, Map parameters) { + this.previousEvents.beginList(listType, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginListItem() + */ + @Override + public void beginListItem() { + this.previousEvents.beginListItem(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void beginMacroMarker(String name, Map parameters, String content, + boolean isInline) { + this.previousEvents.beginMacroMarker(name, parameters, content, isInline); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + this.previousEvents.beginParagraph(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotation(java.util.Map) + */ + @Override + public void beginQuotation(Map parameters) { + this.previousEvents.beginQuotation(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + this.previousEvents.beginQuotationLine(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginSection(java.util.Map) + */ + @Override + public void beginSection(Map parameters) { + this.previousEvents.beginSection(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + this.previousEvents.beginTable(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + this.previousEvents.beginTableCell(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + this.previousEvents.beginTableHeadCell(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + this.previousEvents.beginTableRow(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionDescription() + */ + @Override + public void endDefinitionDescription() { + this.previousEvents.endDefinitionDescription(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void endDefinitionList(Map parameters) { + this.previousEvents.endDefinitionList(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDefinitionTerm() + */ + @Override + public void endDefinitionTerm() { + this.previousEvents.endDefinitionTerm(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endDocument(java.util.Map) + */ + @Override + public void endDocument(Map parameters) { + this.previousEvents.endDocument(parameters); + flush(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endGroup(Map) + */ + public void endGroup(Map parameters) { + this.previousEvents.endGroup(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void endFormat(Format format, Map parameters) { + this.previousEvents.endFormat(format, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + this.previousEvents.endHeader(level, id, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.previousEvents.endLink(reference, isFreeStandingURI, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void endList(ListType listType, Map parameters) { + this.previousEvents.endList(listType, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endListItem() + */ + @Override + public void endListItem() { + this.previousEvents.endListItem(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void endMacroMarker(String name, Map parameters, String content, + boolean isInline) { + this.previousEvents.endMacroMarker(name, parameters, content, isInline); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + this.previousEvents.endParagraph(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotation(java.util.Map) + */ + @Override + public void endQuotation(Map parameters) { + this.previousEvents.endQuotation(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endQuotationLine() + */ + @Override + public void endQuotationLine() { + this.previousEvents.endQuotationLine(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endSection(java.util.Map) + */ + @Override + public void endSection(Map parameters) { + this.previousEvents.endSection(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + this.previousEvents.endTable(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableCell(java.util.Map) + */ + @Override + public void endTableCell(Map parameters) { + this.previousEvents.endTableCell(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableHeadCell(java.util.Map) + */ + @Override + public void endTableHeadCell(Map parameters) { + this.previousEvents.endTableHeadCell(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTableRow(java.util.Map) + */ + @Override + public void endTableRow(Map parameters) { + this.previousEvents.endTableRow(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onRawText(String, Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + this.previousEvents.onRawText(text, syntax); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onEmptyLines(int) + */ + @Override + public void onEmptyLines(int count) { + this.previousEvents.onEmptyLines(count); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + this.previousEvents.onHorizontalLine(parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onId(java.lang.String) + */ + @Override + public void onId(String name) { + this.previousEvents.onId(name); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.previousEvents.onImage(reference, isFreeStandingURI, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onMacro(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + this.previousEvents.onMacro(id, parameters, content, isInline); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onNewLine() + */ + @Override + public void onNewLine() { + this.previousEvents.onNewLine(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpace() + */ + @Override + public void onSpace() { + this.previousEvents.onSpace(); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onSpecialSymbol(char) + */ + @Override + public void onSpecialSymbol(char symbol) { + this.previousEvents.onSpecialSymbol(symbol); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.previousEvents.onVerbatim(protectedString, isInline, parameters); + firePreviousEvent(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onWord(java.lang.String) + */ + @Override + public void onWord(String word) { + this.previousEvents.onWord(word); + firePreviousEvent(); + } + + private void firePreviousEvent() { + if (this.previousEvents.size() > this.lookaheadDepth) { + Event event = this.previousEvents.remove(); + event.eventType.fireEvent(getListenerChain().getNextListener(getClass()), + event.eventParameters); + } + } + + private void flush() { + // Ensure that all remaining events are flushed + while (!this.previousEvents.isEmpty()) { + Event event = this.previousEvents.remove(); + event.eventType.fireEvent(getListenerChain().getNextListener(getClass()), + event.eventParameters); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/StackableChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/StackableChainingListener.java new file mode 100644 index 000000000..8736f9c46 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/StackableChainingListener.java @@ -0,0 +1,38 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +/** + * A chaining listener that can be stacked in the {@link ListenerChain}. This is useful when a + * listener in the chain + * wants to reset all stackable listeners to a new state (for example when handling groups in the + * XWiki Syntax + * Renderer). + * + * @version $Id$ + * @since 1.8RC1 + */ +public interface StackableChainingListener extends ChainingListener { + + /** + * @return the new instance of the listener + */ + StackableChainingListener createChainingListenerInstance(); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/TextOnNewLineStateChainingListener.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/TextOnNewLineStateChainingListener.java new file mode 100644 index 000000000..3c5feacfb --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/chaining/TextOnNewLineStateChainingListener.java @@ -0,0 +1,406 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import java.util.Map; + +import org.xwiki.rendering.listener.Format; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.ListType; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Indicate if the text being written starts a new line. By text we mean Space, Special Symbol and + * Words. This is useful + * for some Renderers which need to have this information. For example the XWiki Syntax renderer + * uses it to decide + * whether to escape "*" characters starting new lines since otherwise they would be confused for + * list items. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class TextOnNewLineStateChainingListener extends AbstractChainingListener + implements StackableChainingListener { + + private boolean isTextOnNewLine; + + public TextOnNewLineStateChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + /** + * {@inheritDoc} + * + * @see StackableChainingListener#createChainingListenerInstance() + */ + public StackableChainingListener createChainingListenerInstance() { + return new TextOnNewLineStateChainingListener(getListenerChain()); + } + + public boolean isTextOnNewLine() { + return this.isTextOnNewLine; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionDescription() + */ + @Override + public void beginDefinitionDescription() { + this.isTextOnNewLine = false; + super.beginDefinitionDescription(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionList(java.util.Map) + * @since 2.0RC1 + */ + @Override + public void beginDefinitionList(Map parameters) { + this.isTextOnNewLine = false; + super.beginDefinitionList(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDefinitionTerm() + */ + @Override + public void beginDefinitionTerm() { + this.isTextOnNewLine = false; + super.beginDefinitionTerm(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginDocument(java.util.Map) + */ + @Override + public void beginDocument(Map parameters) { + this.isTextOnNewLine = false; + super.beginDocument(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginGroup(Map) + */ + @Override + public void beginGroup(Map parameters) { + this.isTextOnNewLine = false; + super.beginGroup(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginFormat(org.xwiki.rendering.listener.Format, + * java.util.Map) + */ + @Override + public void beginFormat(Format format, Map parameters) { + // This is an exception and a bit of a hack. The reason we're calling super before + // setting that we're no longer on a new line is for cases when we have "**" (BOLD) + // at the beginning of a line and we need to escape the following character if it's + // a space as otherwise it would be confused for a list. + super.beginFormat(format, parameters); + + this.isTextOnNewLine = false; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void beginLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.isTextOnNewLine = false; + super.beginLink(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginList(org.xwiki.rendering.listener.ListType, + * java.util.Map) + */ + @Override + public void beginList(ListType listType, Map parameters) { + this.isTextOnNewLine = false; + super.beginList(listType, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginListItem() + */ + @Override + public void beginListItem() { + this.isTextOnNewLine = false; + super.beginListItem(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginMacroMarker(java.lang.String, + * java.util.Map, java.lang.String, boolean) + */ + @Override + public void beginMacroMarker(String name, Map parameters, String content, + boolean isInline) { + this.isTextOnNewLine = false; + super.beginMacroMarker(name, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginParagraph(java.util.Map) + */ + @Override + public void beginParagraph(Map parameters) { + this.isTextOnNewLine = true; + super.beginParagraph(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotation(java.util.Map) + */ + @Override + public void beginQuotation(Map parameters) { + this.isTextOnNewLine = false; + super.beginQuotation(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginQuotationLine() + */ + @Override + public void beginQuotationLine() { + this.isTextOnNewLine = false; + super.beginQuotationLine(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void beginHeader(HeaderLevel level, String id, Map parameters) { + this.isTextOnNewLine = false; + super.beginHeader(level, id, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTable(java.util.Map) + */ + @Override + public void beginTable(Map parameters) { + this.isTextOnNewLine = false; + super.beginTable(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableCell(java.util.Map) + */ + @Override + public void beginTableCell(Map parameters) { + this.isTextOnNewLine = false; + super.beginTableCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableHeadCell(java.util.Map) + */ + @Override + public void beginTableHeadCell(Map parameters) { + this.isTextOnNewLine = false; + super.beginTableHeadCell(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#beginTableRow(java.util.Map) + */ + @Override + public void beginTableRow(Map parameters) { + this.isTextOnNewLine = false; + super.beginTableRow(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onRawText(String, + * org.xwiki.rendering.syntax.Syntax) + */ + @Override + public void onRawText(String text, Syntax syntax) { + this.isTextOnNewLine = false; + super.onRawText(text, syntax); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endLink( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void endLink(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + super.endLink(reference, isFreeStandingURI, parameters); + this.isTextOnNewLine = false; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endParagraph(java.util.Map) + */ + @Override + public void endParagraph(Map parameters) { + super.endParagraph(parameters); + this.isTextOnNewLine = true; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endHeader(org.xwiki.rendering.listener.HeaderLevel, + * java.lang.String, java.util.Map) + */ + @Override + public void endHeader(HeaderLevel level, String id, Map parameters) { + super.endHeader(level, id, parameters); + this.isTextOnNewLine = false; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#endTable(java.util.Map) + */ + @Override + public void endTable(Map parameters) { + super.endTable(parameters); + this.isTextOnNewLine = false; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onHorizontalLine(java.util.Map) + */ + @Override + public void onHorizontalLine(Map parameters) { + this.isTextOnNewLine = false; + super.onHorizontalLine(parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onId(java.lang.String) + */ + @Override + public void onId(String name) { + this.isTextOnNewLine = false; + super.onId(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onImage( + * org.xwiki.rendering.listener.reference.ResourceReference , boolean, java.util.Map) + * @since 2.5RC1 + */ + @Override + public void onImage(ResourceReference reference, boolean isFreeStandingURI, + Map parameters) { + this.isTextOnNewLine = false; + super.onImage(reference, isFreeStandingURI, parameters); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onNewLine() + */ + @Override + public void onNewLine() { + super.onNewLine(); + this.isTextOnNewLine = true; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onMacro(java.lang.String, + * java.util.Map, + * java.lang.String, boolean) + */ + @Override + public void onMacro(String id, Map parameters, String content, boolean isInline) { + this.isTextOnNewLine = false; + super.onMacro(id, parameters, content, isInline); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.listener.chaining.AbstractChainingListener#onVerbatim(String, boolean, + * Map) + */ + @Override + public void onVerbatim(String protectedString, boolean isInline, Map parameters) { + this.isTextOnNewLine = false; + super.onVerbatim(protectedString, isInline, parameters); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/AttachmentResourceReference.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/AttachmentResourceReference.java new file mode 100644 index 000000000..28e594476 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/AttachmentResourceReference.java @@ -0,0 +1,63 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.reference; + +import org.apache.commons.lang.StringUtils; + +/** + * Represents a reference to an Attachment. + * + * @version $Id$ + * @since 2.5RC1 + */ +public class AttachmentResourceReference extends ResourceReference { + + /** + * The name of the parameter representing the Query String. + */ + public static final String QUERY_STRING = "queryString"; + + /** + * @param reference + * see {@link #getReference()} + */ + public AttachmentResourceReference(String reference) { + super(reference, ResourceType.ATTACHMENT); + } + + /** + * @return the query string for specifying parameters that will be used in the rendered URL or + * null if no query + * string has been specified. Example: "mydata1=5&mydata2=Hello" + */ + public String getQueryString() { + return getParameter(QUERY_STRING); + } + + /** + * @param queryString + * see {@link #getQueryString()} + */ + public void setQueryString(String queryString) { + if (!StringUtils.isEmpty(queryString)) { + setParameter(QUERY_STRING, queryString); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/DocumentResourceReference.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/DocumentResourceReference.java new file mode 100644 index 000000000..e6e9c6279 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/DocumentResourceReference.java @@ -0,0 +1,89 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.reference; + +import org.apache.commons.lang.StringUtils; + +/** + * Represents a reference to a Document. + * + * @version $Id$ + * @since 2.5RC1 + */ +public class DocumentResourceReference extends ResourceReference { + + /** + * The name of the parameter representing the Query String. + */ + public static final String QUERY_STRING = "queryString"; + + /** + * The name of the parameter representing the Anchor. + */ + public static final String ANCHOR = "anchor"; + + /** + * @param reference + * see {@link #getReference()} + */ + public DocumentResourceReference(String reference) { + super(reference, ResourceType.DOCUMENT); + } + + /** + * @return the query string for specifying parameters that will be used in the rendered URL or + * null if no query + * string has been specified. Example: "mydata1=5&mydata2=Hello" + */ + public String getQueryString() { + return getParameter(QUERY_STRING); + } + + /** + * @param queryString + * see {@link #getQueryString()} + */ + public void setQueryString(String queryString) { + if (!StringUtils.isEmpty(queryString)) { + setParameter(QUERY_STRING, queryString); + } + } + + /** + * @return the anchor name pointing to an anchor defined in the referenced document or null if no + * anchor has been + * specified (in which case the reference points to the top of the document). Note that in + * XWiki anchors are + * automatically created for titles. Example: "TableOfContentAnchor" + */ + public String getAnchor() { + return getParameter(ANCHOR); + } + + /** + * @param anchor + * see {@link #getAnchor()} + */ + public void setAnchor(String anchor) { + if (!StringUtils.isEmpty(anchor)) { + setParameter(ANCHOR, anchor); + } + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/InterWikiResourceReference.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/InterWikiResourceReference.java new file mode 100644 index 000000000..0253bcf31 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/InterWikiResourceReference.java @@ -0,0 +1,70 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.reference; + +/** + * Represents a reference to an external wiki(Inter + * Wiki). An + * InterWiki reference is a shorthand notation to reference a set of external URL, all having a + * common prefix (eg + * http://server/some/common/prefix/a1, http://server/some/common/prefix/a2). An InterWiki reference + * is made of an + * InterWiki Alias which is a name corresponding to the common URL and an InterWiki Path which is + * the suffix to append + * to the common URL part to make the full URL. + * + * @version $Id$ + * @since 2.5RC1 + */ +public class InterWikiResourceReference extends ResourceReference { + + /** + * The name of the parameter representing the InterWiki Alias. + */ + public static final String INTERWIKI_ALIAS = "interWikiAlias"; + + /** + * @param reference + * see {@link #getReference()} + */ + public InterWikiResourceReference(String reference) { + super(reference, ResourceType.INTERWIKI); + setTyped(true); + } + + /** + * @param interWikiAlias + * see {@link #getInterWikiAlias()} + */ + public void setInterWikiAlias(String interWikiAlias) { + setParameter(INTERWIKI_ALIAS, interWikiAlias); + } + + /** + * @return the Inter Wiki alias to which the + * resource is + * pointing to or null if not defined. Mappings between Inter Wiki aliases and actual + * locations are defined + * in the Inter Wiki Map. Example: "wikipedia" + */ + public String getInterWikiAlias() { + return getParameter(INTERWIKI_ALIAS); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceReference.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceReference.java new file mode 100644 index 000000000..3f445ccce --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceReference.java @@ -0,0 +1,269 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.reference; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Represents a reference to a Resource (document, image, attachment, mail, etc). Note that this + * representation is + * independent of any wiki syntax. + * + * @version $Id$ + * @since 2.5RC1 + */ +public class ResourceReference implements Cloneable { + + /** + * @see #isTyped() + */ + private boolean isTyped = true; + + /** + * @see #getReference() Note that the reason we store the reference as a String and not as an + * Entity Reference is + * because we want the Rendering module independent of the XWiki Model so that it can be used + * independently of + * XWiki. + */ + private String reference; + + /** + * @see #getType() + */ + private ResourceType type; + + /** + * @see #getParameter(String) + */ + private Map parameters = new HashMap(); + + /** + * @param reference + * see {@link #getReference()} + * @param type + * see {@link #getType()} + */ + public ResourceReference(String reference, ResourceType type) { + setReference(reference); + setType(type); + } + + /** + * @param isTyped + * see {@link #isTyped()} + */ + public void setTyped(boolean isTyped) { + this.isTyped = isTyped; + } + + /** + * @return true if the resource type has been explicitly provided (eg in XWiki Syntax 2.1 if the + * reference is + * prefixed with the resource type followed by ":" and then the rest of the reference) + */ + public boolean isTyped() { + return this.isTyped; + } + + /** + * @param reference + * see {@link #getReference()} + */ + public void setReference(String reference) { + this.reference = reference; + } + + /** + * @return the reference pointed to by this resource. For example a reference can be a document's + * name (which + * depends on the wiki, for example for XWiki the format is "wiki:space.page"), a URI (for + * example: + * mailto:john@doe.com), a URL, an Inter + * Wiki + * reference, etc + * @see #getType() + */ + public String getReference() { + return this.reference; + } + + /** + * @return the type of the resource + * @see ResourceType + */ + public ResourceType getType() { + return this.type; + } + + /** + * @param type + * the type of the resource + * @see ResourceType + */ + public void setType(ResourceType type) { + this.type = type; + } + + /** + * @param name + * see {@link #getParameter(String)} + * @param value + * see {@link #getParameter(String)} + */ + public void setParameter(String name, String value) { + this.parameters.put(name, value); + } + + /** + * @param parameters + * see {@link #getParameters()} + */ + public void setParameters(Map parameters) { + this.parameters.putAll(parameters); + } + + /** + * @param name + * see {@link #getParameter(String)} + */ + public void removeParameter(String name) { + this.parameters.remove(name); + } + + /** + * In order for Resource references to be extensible we allow for extra parameters in addition to + * the Resource + * reference. For example this is used in Document Resource References for storing the query + * string and anchor + * information, and in InterWiki Resource References to store the InterWiki Alias. Note that + * supported parameters + * depend on the Renderer that will be used (i.e. it depends on the target Syntax). For example + * the XWiki Syntax 2.1 + * only supports "queryString" and "anchor". + * + * @param name + * the name of the parameter to get + * @return the parameter value or null if no such parameter exist + */ + public String getParameter(String name) { + return this.parameters.get(name); + } + + /** + * @return the collections of parameters, see {@link #getParameter(String)} + */ + public Map getParameters() { + return Collections.unmodifiableMap(this.parameters); + } + + /** + * {@inheritDoc} + *

+ * The output is syntax independent since this class is used for all syntaxes. Specific syntaxes + * should extend this + * class and override this method to perform syntax-dependent formatting. + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("Typed = [").append(isTyped()).append("]"); + sb.append(" "); + sb.append("Type = [").append(getType().getScheme()).append("]"); + if (getReference() != null) { + sb.append(" "); + sb.append("Reference = [").append(getReference()).append("]"); + } + Map params = getParameters(); + if (!params.isEmpty()) { + sb.append(" "); + sb.append("Parameters = ["); + Iterator> it = params.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + sb.append("[").append(entry.getKey()).append("] = [").append(entry.getValue()).append("]"); + if (it.hasNext()) { + sb.append(", "); + } + } + sb.append("]"); + } + + return sb.toString(); + } + + /** + * {@inheritDoc} + * + * @see Object#clone() + */ + @Override + public ResourceReference clone() { + ResourceReference clone; + try { + clone = (ResourceReference) super.clone(); + } catch (CloneNotSupportedException e) { + // Should never happen + throw new RuntimeException("Failed to clone object", e); + } + return clone; + } + + /** + * {@inheritDoc} + * + * @see Object#hashCode() + */ + @Override + public int hashCode() { + return new HashCodeBuilder(1, 9).append(getType()).append(isTyped()).append(getReference()) + .append(getParameters()).toHashCode(); + } + + /** + * {@inheritDoc} + * + * @see Object#equals(Object) + */ + @Override + public boolean equals(Object object) { + if (object == null) { + return false; + } + if (object == this) { + return true; + } + if (object.getClass() != getClass()) { + return false; + } + ResourceReference rhs = (ResourceReference) object; + return new EqualsBuilder().append(getType(), rhs.getType()).append(isTyped(), rhs.isTyped()) + .append(getReference(), rhs.getReference()).append(getParameters(), rhs.getParameters()) + .isEquals(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceType.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceType.java new file mode 100644 index 000000000..eefdf8329 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/listener/reference/ResourceType.java @@ -0,0 +1,152 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.reference; + +/** + * The Resource type. It can be one of: + *

    + *
  • document ("doc")
  • + *
  • URL ("url")
  • + *
  • document in another wiki (interwiki) ("interwiki")
  • + *
  • relative URL ("path")
  • + *
  • mail ("mailto")
  • + *
  • attachment ("attach")
  • + *
  • UNC path ("unc")
  • + *
+ * + * @version $Id$ + * @since 2.5RC1 + */ +public class ResourceType { + + /** + * Special type to be used when the type of the resource is not known. + */ + public static final ResourceType UNKNOWN = new ResourceType("unknown"); + + /** + * Represents a Document. + */ + public static final ResourceType DOCUMENT = new ResourceType("doc"); + + /** + * Represents an URL. + */ + public static final ResourceType URL = new ResourceType("url"); + + /** + * Represents a document in another wiki. + */ + public static final ResourceType INTERWIKI = new ResourceType("interwiki"); + + /** + * Represents a relative URL in the current wiki. + */ + public static final ResourceType PATH = new ResourceType("path"); + + /** + * Represents a mail. + */ + public static final ResourceType MAILTO = new ResourceType("mailto"); + + /** + * Represents an attachment. + */ + public static final ResourceType ATTACHMENT = new ResourceType("attach"); + + /** + * Represents an icon. + */ + public static final ResourceType ICON = new ResourceType("icon"); + + /** + * Represents a UNC (Universal Naming Convention) (eg "\\myserver\myshare\mydoc.txt"). + * + * @since 2.7M1 + */ + public static final ResourceType UNC = new ResourceType("unc"); + + /** + * @see #getScheme() + */ + private String scheme; + + /** + * @param scheme + * see {@link #getScheme()} + */ + public ResourceType(String scheme) { + setScheme(scheme); + } + + /** + * @return the type of the link (eg "doc" for links to documents, etc) + */ + public String getScheme() { + return this.scheme; + } + + /** + * @param scheme + * see {@link #getScheme()} + */ + public void setScheme(String scheme) { + this.scheme = scheme; + } + + /** + * {@inheritDoc} + * + * @see Object#hashCode() + */ + @Override + public int hashCode() { + // Random number. See http://www.technofundo.com/tech/java/equalhash.html for the detail of this + // algorithm. + int hash = 8; + hash = 31 * hash + (null == getScheme() ? 0 : getScheme().hashCode()); + return hash; + } + + /** + * {@inheritDoc} + * + * @see Object#equals(Object) + */ + @Override + public boolean equals(Object object) { + boolean result; + + // See http://www.technofundo.com/tech/java/equalhash.html for the detail of this algorithm. + if (this == object) { + result = true; + } else { + if ((object == null) || (object.getClass() != this.getClass())) { + result = false; + } else { + // object must be ResourceType at this point + ResourceType type = (ResourceType) object; + result = (getScheme() == type.getScheme() + || (getScheme() != null && getScheme().equals(type.getScheme()))); + } + } + return result; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ParseException.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ParseException.java new file mode 100644 index 000000000..11ba5e565 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ParseException.java @@ -0,0 +1,59 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.parser; + +/** + * Encapsulate a parsing error. + * + * @version $Id$ + */ +public class ParseException extends Exception { + + /** + * Class ID for serialization. + */ + private static final long serialVersionUID = 442523704445037944L; + + /** + * Construct a new ParseException with the specified detail message. + * + * @param message + * The detailed message. This can later be retrieved by the Throwable.getMessage() + * method. + */ + public ParseException(String message) { + super(message); + } + + /** + * Construct a new ParseException with the specified detail message and cause. + * + * @param message + * The detailed message. This can later be retrieved by the Throwable.getMessage() + * method. + * @param throwable + * the cause. This can be retrieved later by the Throwable.getCause() method. (A null + * value is permitted, + * and indicates that the cause is nonexistent or unknown) + */ + public ParseException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/Parser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/Parser.java new file mode 100644 index 000000000..6b2b40518 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/Parser.java @@ -0,0 +1,52 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.parser; + +import java.io.Reader; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Parse content into a XDOM (a tree of {@link org.xwiki.rendering.block.Block}s). + * + * @version $Id$ + * @since 1.5M2 + */ +@ComponentRole +public interface Parser { + + /** + * @return the wiki syntax the parser is implementing + */ + Syntax getSyntax(); + + /** + * @param source + * the content to parse + * @return the tree representation of the content as {@link org.xwiki.rendering.block.Block}s + * @throws ParseException + * if the source cannot be read or an unexpected error happens during the parsing. + * Parsers should be + * written to not generate any error as much as possible. + */ + XDOM parse(Reader source) throws ParseException; +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceParser.java new file mode 100644 index 000000000..cfe1b9e79 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceParser.java @@ -0,0 +1,47 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.parser; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Interface for parsing resource references (references to links, images, attachments, etc) for + * various wiki syntaxes. + * + * @version $Id$ + * @since 2.5RC1 + */ +@ComponentRole +public interface ResourceReferenceParser { + + /** + * Parses a resource reference represented (reference to a link, image, attachment, etc) as a + * String into a + * {@link org.xwiki.rendering.listener.reference.ResourceReference} object. + * + * @param rawReference + * the string representation of the resource reference to parse (the supported syntax + * depends on the + * parser implementation used) + * @return the parsed resource reference + */ + ResourceReference parse(String rawReference); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceTypeParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceTypeParser.java new file mode 100644 index 000000000..f7ac2fb02 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/ResourceReferenceTypeParser.java @@ -0,0 +1,49 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.parser; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; + +/** + * Parses a raw Resource Reference by determining if it has the right type and return a non-null + * {@link org.xwiki.rendering.listener.reference.ResourceReference} object if it has. + * + * @version $Id$ + * @since 2.5RC1 + */ +@ComponentRole +public interface ResourceReferenceTypeParser { + + /** + * @return the resource type (document, url, attachment, etc). + */ + ResourceType getType(); + + /** + * @param reference + * the raw resource reference to parse + * @return the parsed resource information if the passed reference can be parsed by this type + * parser or null if the + * passed reference isn't valid + */ + ResourceReference parse(String reference); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/StreamParser.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/StreamParser.java new file mode 100644 index 000000000..e36422e6d --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/parser/StreamParser.java @@ -0,0 +1,53 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.parser; + +import java.io.Reader; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.listener.Listener; +import org.xwiki.rendering.syntax.Syntax; + +/** + * Streaming based parser. Instead of returning a resulting XDOM it send events during the parsing. + * + * @version $Id$ + * @since 2.1M1 + */ +@ComponentRole +public interface StreamParser { + + /** + * @return the wiki syntax the parser is implementing + */ + Syntax getSyntax(); + + /** + * @param source + * the content to parse + * @param listener + * receive event for each element + * @throws ParseException + * if the source cannot be read or an unexpected error happens during the parsing. + * Parsers should be + * written to not generate any error as much as possible. + */ + void parse(Reader source, Listener listener) throws ParseException; +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/AbstractChainingPrintRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/AbstractChainingPrintRenderer.java new file mode 100644 index 000000000..718f4ac52 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/AbstractChainingPrintRenderer.java @@ -0,0 +1,95 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer; + +import java.util.Stack; + +import org.xwiki.rendering.listener.chaining.AbstractChainingListener; +import org.xwiki.rendering.listener.chaining.ChainingListener; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * @version $Id$ + * @since 1.8RC1 + */ +public abstract class AbstractChainingPrintRenderer extends AbstractChainingListener + implements PrintRenderer { + + /** + * The printer stack. Can be used to print in a specific printer and then easily return to the + * previous one. + */ + private Stack printers = new Stack(); + + /** + * @return the main printer. + */ + public WikiPrinter getMainPrinter() { + return this.printers.firstElement(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.PrintRenderer#getPrinter() + */ + public WikiPrinter getPrinter() { + return this.printers.peek(); + } + + /** + * {@inheritDoc} + * + * @see PrintRenderer#setPrinter(org.xwiki.rendering.renderer.printer.WikiPrinter) + * @since 2.0M3 + */ + public void setPrinter(WikiPrinter printer) { + pushPrinter(printer); + } + + /** + * Change the current {@link WikiPrinter} with the provided one. + * + * @param wikiPrinter + * the new {@link WikiPrinter} to use + */ + protected void pushPrinter(WikiPrinter wikiPrinter) { + this.printers.push(wikiPrinter); + + // Since we're setting a new printer to use, make sure that all print renderers in the chain + // have the new + // printer set. Only do this if we're on the top level Print Renderer. + if (getListenerChain().indexOf(getClass()) == 0) { + ChainingListener nextListener = this; + while ((nextListener = getListenerChain().getNextListener(nextListener.getClass())) != null) { + if (PrintRenderer.class.isAssignableFrom(nextListener.getClass())) { + ((PrintRenderer) nextListener).setPrinter(wikiPrinter); + } + } + } + } + + /** + * Removes the current {@link WikiPrinter} and instead sets the previous printer as active. + */ + protected void popPrinter() { + this.printers.pop(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/BlockRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/BlockRenderer.java new file mode 100644 index 000000000..581fa947c --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/BlockRenderer.java @@ -0,0 +1,52 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer; + +import java.util.Collection; +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.renderer.printer.WikiPrinter; +import org.xwiki.rendering.block.Block; + +/** + * Renders a {@link Block} in some target syntax. + * + * @version $Id$ + * @since 2.0M3 + */ +@ComponentRole +public interface BlockRenderer { + + /** + * @param block + * the block to render in the target syntax + * @param printer + * the object where to output the result of the rendering + */ + void render(Block block, WikiPrinter printer); + + /** + * @param blocks + * the list of blocks to render in the target syntax + * @param printer + * the object where to output the result of the rendering + * @todo remove this API once we introduce the notion of BlockCollection + */ + void render(Collection blocks, WikiPrinter printer); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRenderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRenderer.java new file mode 100644 index 000000000..041379d27 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRenderer.java @@ -0,0 +1,48 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * A Print Renderer is a {@link Renderer} that outputs its results to a {@link WikiPrinter}. + * + * @version $Id$ + * @since 1.6M1 + */ +@ComponentRole +public interface PrintRenderer extends Renderer { + + /** + * @return the printer to which events generate results in. For example the XHTML print renderer + * outputs XHTML to a + * {@link WikiPrinter} and the resulting XHTML can be retrieved by calling + * {@link org.xwiki.rendering.renderer.printer.WikiPrinter#toString()} + */ + WikiPrinter getPrinter(); + + /** + * @param printer + * the wiki printer to use when the Renderer needs to output rendered content + * @since 2.0M3 + */ + void setPrinter(WikiPrinter printer); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRendererFactory.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRendererFactory.java new file mode 100644 index 000000000..f69353464 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/PrintRendererFactory.java @@ -0,0 +1,54 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer; + +import org.xwiki.component.annotation.ComponentRole; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * Allows creating {@link Renderer}s of a given type (one factory implementation per Renderer type). + * We need a factory + * since we need to pass a {@link WikiPrinter} object to the created Renderer. In addition this + * factory allows us to be + * able to return the {@link org.xwiki.rendering.syntax.Syntax} supported by the Renderer without + * needing to create an + * instance of it. + * + * @version $Id$ + * @since 1.6M2 + */ +@ComponentRole +public interface PrintRendererFactory { + + /** + * @return the Syntax supported by the Renderer type + * @since 2.0M3 + */ + Syntax getSyntax(); + + /** + * @param printer + * the printer to use to output renderer data + * @return a new Renderer instance (stateful) + * @since 2.0M3 + */ + PrintRenderer createRenderer(WikiPrinter printer); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/Renderer.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/Renderer.java new file mode 100644 index 000000000..646e64312 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/Renderer.java @@ -0,0 +1,31 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer; + +import org.xwiki.rendering.listener.Listener; + +/** + * A special type of Listener which writes data somewhere. For example, a PDFRenderer, an + * XHTMLRenderer, etc. + * + * @version $Id$ + * @since 1.5M2 + */ +public interface Renderer extends Listener {} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/DefaultWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/DefaultWikiPrinter.java new file mode 100644 index 000000000..ae67e50e4 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/DefaultWikiPrinter.java @@ -0,0 +1,100 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer.printer; + +/** + * Printer using a {@link StringBuffer} as the underlying output target. + * + * @version $Id$ + * @since 1.6M1 + */ +public class DefaultWikiPrinter implements WikiPrinter { + + /** + * The buffer where to put the provided {@link String}s. + */ + private StringBuffer buffer; + + /** + * The default constructor. It initialize a new empty {@link StringBuffer}. + */ + public DefaultWikiPrinter() { + this(new StringBuffer()); + } + + /** + * @param buffer + * the {@link StringBuffer} to where to put the provided {@link String}s. + */ + public DefaultWikiPrinter(StringBuffer buffer) { + this.buffer = buffer; + } + + /** + * @return the buffer containing the printed {@link String}s. + */ + public StringBuffer getBuffer() { + return this.buffer; + } + + /** + * This method is protected to allow classes extending this one to override what a new line is. + * + * @return a new line symbols + */ + protected String getEOL() { + return "\n"; + } + + /** + * {@inheritDoc} + * + * @see WikiPrinter#print(String) + */ + public void print(String text) { + getBuffer().append(text); + } + + /** + * {@inheritDoc} + * + * @see WikiPrinter#println(String) + */ + public void println(String text) { + getBuffer().append(text).append(getEOL()); + } + + /** + * {@inheritDoc} + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getBuffer().toString(); + } + + /** + * Removes the buffer's content which allows the printer to be reused. + */ + public void clear() { + getBuffer().setLength(0); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/LookaheadWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/LookaheadWikiPrinter.java new file mode 100644 index 000000000..e30df5107 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/LookaheadWikiPrinter.java @@ -0,0 +1,87 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer.printer; + +/** + * Wiki printer that allows deferring printing text and that instead can save it in some internal + * buffer. This allows + * accumulating some content before it's flushed. This feature is used for example in the XWiki + * Syntax Renderer to + * accumulate text so that it be reviewed and escaped before printed (indeed some text has some + * characters that need to + * be escaped or they'd have a wiki meaning otherwise). + * + * @version $Id$ + * @since 1.7 + */ +public class LookaheadWikiPrinter extends WrappingWikiPrinter { + + private StringBuffer buffer = new StringBuffer(); + + public LookaheadWikiPrinter(WikiPrinter printer) { + super(printer); + } + + protected void printInternal(String text) { + super.print(text); + } + + protected void printlnInternal(String text) { + super.println(text); + } + + public void print(String text) { + flush(); + printInternal(text); + } + + public void println(String text) { + flush(); + printlnInternal(text); + } + + public void printDelayed(String text) { + getBuffer().append(text); + } + + public void printlnDelayed(String text) { + getBuffer().append(text).append(getEOL()); + } + + public StringBuffer getBuffer() { + return this.buffer; + } + + public void flush() { + if (getBuffer().length() > 0) { + printInternal(getBuffer().toString()); + getBuffer().setLength(0); + } + } + + /** + * This method is protected to allow classes extending this one to define what a new line is. + * + * @return a new line symbols + */ + protected String getEOL() { + return "\n"; + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/VoidWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/VoidWikiPrinter.java new file mode 100644 index 000000000..7a5d953aa --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/VoidWikiPrinter.java @@ -0,0 +1,56 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer.printer; + +/** + * A WikiPrinter implementation which does not do anything. + * + * @version $Id$ + */ +public class VoidWikiPrinter implements WikiPrinter { + + /** + * Unique instance of {@link VoidWikiPrinter}. + */ + public static final VoidWikiPrinter VOIDWIKIPRINTER = new VoidWikiPrinter(); + + /** + * Use {@link #VOIDWIKIPRINTER}. + */ + private VoidWikiPrinter() {} + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.WikiPrinter#print(java.lang.String) + */ + public void print(String text) { + // Don't do anything + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.WikiPrinter#println(java.lang.String) + */ + public void println(String text) { + // Don't do anything + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WikiPrinter.java new file mode 100644 index 000000000..5482a0998 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WikiPrinter.java @@ -0,0 +1,41 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer.printer; + +/** + * Printer for {@link org.xwiki.rendering.renderer.PrintRenderer}s. + * + * @version $Id$ + * @since 1.6M1 + */ +public interface WikiPrinter { + + /** + * @param text + * print the provided {@link String}. + */ + void print(String text); + + /** + * @param text + * print the provided {@link String} and add a new line. + */ + void println(String text); +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WrappingWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WrappingWikiPrinter.java new file mode 100644 index 000000000..e87a58f4f --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/WrappingWikiPrinter.java @@ -0,0 +1,52 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer.printer; + +/** + * Wraps a wiki printer. + * + * @version $Id$ + * @since 1.7 + */ +public class WrappingWikiPrinter implements WikiPrinter { + + private WikiPrinter printer; + + public WrappingWikiPrinter(WikiPrinter printer) { + this.printer = printer; + } + + public void print(String text) { + getWrappedPrinter().print(text); + } + + public void println(String text) { + getWrappedPrinter().println(text); + } + + public WikiPrinter getWrappedPrinter() { + return this.printer; + } + + @Override + public String toString() { + return getWrappedPrinter().toString(); + } +} diff --git a/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java new file mode 100644 index 000000000..eb5428ab5 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java @@ -0,0 +1,269 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.renderer.printer; + +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.xml.sax.Attributes; + +/** + * Base toolkit class for all XHTML-based renderers. This printer handles whitespaces so that it + * prints " " when + * needed (i.e. when the spaces are at the beginning or at the end of an element's content or when + * there are more than 1 + * contiguous spaces, except for CDATA sections and inside PRE elements. It also knows how to handle + * XHTML comments). + * + * @version $Id$ + * @since 1.7M1 + */ +public class XHTMLWikiPrinter extends XMLWikiPrinter { + + private int spaceCount = 0; + + private boolean isInCData; + + private boolean isInPreserveElement; + + private boolean elementEnded; + + private boolean hasTextBeenPrinted; + + /** + * @param printer + * the object to which to write the XHTML output to + */ + public XHTMLWikiPrinter(WikiPrinter printer) { + super(printer); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXML(java.lang.String) + */ + @Override + public void printXML(String str) { + handleSpaceWhenInText(); + super.printXML(str); + this.hasTextBeenPrinted = true; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLElement(java.lang.String) + */ + @Override + public void printXMLElement(String name) { + handleSpaceWhenStartElement(); + super.printXMLElement(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLElement(java.lang.String, + * java.lang.String[][]) + */ + @Override + public void printXMLElement(String name, String[][] attributes) { + handleSpaceWhenStartElement(); + super.printXMLElement(name, attributes); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLElement(java.lang.String, + * java.util.Map) + */ + @Override + public void printXMLElement(String name, Map attributes) { + handleSpaceWhenStartElement(); + super.printXMLElement(name, attributes); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLStartElement(java.lang.String) + */ + @Override + public void printXMLStartElement(String name) { + handleSpaceWhenStartElement(); + super.printXMLStartElement(name); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLStartElement(java.lang.String, + * java.lang.String[][]) + */ + @Override + public void printXMLStartElement(String name, String[][] attributes) { + handleSpaceWhenStartElement(); + super.printXMLStartElement(name, attributes); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLStartElement(java.lang.String, + * java.util.Map) + */ + @Override + public void printXMLStartElement(String name, Map attributes) { + handleSpaceWhenStartElement(); + super.printXMLStartElement(name, attributes); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLStartElement(java.lang.String, + * org.xml.sax.Attributes) + */ + @Override + public void printXMLStartElement(String name, Attributes attributes) { + handleSpaceWhenStartElement(); + super.printXMLStartElement(name, attributes); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLEndElement(java.lang.String) + */ + @Override + public void printXMLEndElement(String name) { + handleSpaceWhenEndlement(); + super.printXMLEndElement(name); + this.elementEnded = true; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLComment(java.lang.String) + */ + @Override + public void printXMLComment(String content) { + printXMLComment(content, false); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLComment(java.lang.String, + * boolean) + */ + @Override + public void printXMLComment(String content, boolean escape) { + handleSpaceWhenStartElement(); + super.printXMLComment(content, escape); + this.elementEnded = true; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLStartCData() + */ + @Override + public void printXMLStartCData() { + handleSpaceWhenStartElement(); + super.printXMLStartCData(); + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printXMLEndCData() + */ + @Override + public void printXMLEndCData() { + handleSpaceWhenEndlement(); + super.printXMLEndCData(); + } + + /** + * This method should be used to print a space rather than calling printXML(" "). + */ + public void printSpace() { + this.spaceCount++; + } + + /** + * {@inheritDoc} + * + * @see org.xwiki.rendering.renderer.printer.XMLWikiPrinter#printRaw(java.lang.String) + */ + @Override + public void printRaw(String raw) { + handleSpaceWhenStartElement(); + super.printRaw(raw); + this.elementEnded = true; + } + + private void handleSpaceWhenInText() { + if (this.elementEnded || this.hasTextBeenPrinted) { + handleSpaceWhenStartElement(); + } else { + handleSpaceWhenEndlement(); + } + } + + private void handleSpaceWhenStartElement() { + // Use case: something ... + // Use case: something + + +

Represents content elements (Paragraph, Header, List, Styles, + etc) as Blocks and a full document content is represented by a XDOM + object.

+ +

Related Documentation

+

For overviews, tutorials, examples, guides, and tool + documentation, please see:

+ + \ No newline at end of file diff --git a/celements-xwiki-rendering-api/src/main/resources/META-INF/components.txt b/celements-xwiki-rendering-api/src/main/resources/META-INF/components.txt new file mode 100644 index 000000000..b964f6c00 --- /dev/null +++ b/celements-xwiki-rendering-api/src/main/resources/META-INF/components.txt @@ -0,0 +1,15 @@ +org.xwiki.rendering.internal.parser.PlainTextBlockParser +org.xwiki.rendering.internal.parser.PlainTextStreamParser +org.xwiki.rendering.internal.renderer.DefaultLinkLabelGenerator +org.xwiki.rendering.internal.renderer.DefaultAttachmentURILabelGenerator +org.xwiki.rendering.internal.renderer.MailtoURILabelGenerator +org.xwiki.rendering.internal.renderer.event.EventRendererFactory +org.xwiki.rendering.internal.renderer.event.EventRenderer +org.xwiki.rendering.internal.renderer.event.EventBlockRenderer +org.xwiki.rendering.internal.renderer.plain.PlainTextRendererFactory +org.xwiki.rendering.internal.renderer.plain.PlainTextRenderer +org.xwiki.rendering.internal.renderer.plain.PlainTextBlockRenderer +org.xwiki.rendering.internal.converter.DefaultConverter +org.xwiki.rendering.internal.transformation.DefaultTransformationManager +org.xwiki.rendering.internal.configuration.DefaultRenderingConfiguration +org.xwiki.rendering.internal.syntax.DefaultSyntaxFactory diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/block/BlockTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/block/BlockTest.java new file mode 100644 index 000000000..c4b4bd33b --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/block/BlockTest.java @@ -0,0 +1,222 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.block; + +import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.xwiki.rendering.listener.HeaderLevel; +import org.xwiki.rendering.listener.reference.DocumentResourceReference; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; + +/** + * Unit tests for Block manipulation, testing {@link AbstractBlock}. + * + * @version $Id$ + * @since 1.5M2 + */ +public class BlockTest { + + @Test + public void testGetBlocksByType() { + ParagraphBlock pb1 = new ParagraphBlock(Arrays + .asList( + new HeaderBlock(Arrays.asList(new WordBlock("title1")), HeaderLevel.LEVEL1))); + ParagraphBlock pb2 = new ParagraphBlock(Arrays + .asList( + new HeaderBlock(Arrays.asList(new WordBlock("title2")), HeaderLevel.LEVEL2))); + ParagraphBlock pb3 = new ParagraphBlock(Arrays.asList(pb1, pb2)); + + List results = pb1.getChildrenByType(HeaderBlock.class, true); + Assert.assertEquals(1, results.size()); + + results = pb3.getChildrenByType(HeaderBlock.class, true); + Assert.assertEquals(2, results.size()); + } + + @Test + public void testInsertChildAfter() { + Block wb1 = new WordBlock("block1"); + Block wb2 = new WordBlock("block2"); + ParagraphBlock pb = new ParagraphBlock(Arrays.asList(wb1, wb2)); + + Block wb = new WordBlock("block"); + + pb.insertChildAfter(wb, wb1); + Assert.assertSame(wb, pb.getChildren().get(1)); + Assert.assertSame(wb1, wb.getPreviousSibling()); + Assert.assertSame(wb2, wb.getNextSibling()); + Assert.assertSame(wb, wb1.getNextSibling()); + Assert.assertSame(wb, wb2.getPreviousSibling()); + + pb.insertChildAfter(wb, wb2); + Assert.assertSame(wb, pb.getChildren().get(3)); + Assert.assertSame(wb2, wb.getPreviousSibling()); + Assert.assertSame(wb, wb2.getNextSibling()); + Assert.assertNull(wb.getNextSibling()); + } + + @Test + public void testInsertChildBefore() { + Block wb1 = new WordBlock("block1"); + Block wb2 = new WordBlock("block2"); + + List children = new ArrayList<>(); + children.add(wb1); + children.add(wb2); + + ParagraphBlock pb = new ParagraphBlock(children); + + Block wb = new WordBlock("block"); + + pb.insertChildBefore(wb, wb1); + Assert.assertSame(wb, pb.getChildren().get(0)); + + pb.insertChildBefore(wb, wb2); + Assert.assertSame(wb, pb.getChildren().get(2)); + } + + @Test + public void testReplaceBlock() { + // It's important all blocks have same content to make sure replacement api don't find the + // position of the + // old block using Object#equals + Block word1 = new WordBlock("block1"); + Block word2 = new WordBlock("block2"); + Block word3 = new WordBlock("block3"); + + Block parentBlock = new ParagraphBlock(Arrays.asList(word1, word2)); + + // replace by one + parentBlock.replaceChild(word3, word1); + + Assert.assertEquals(2, parentBlock.getChildren().size()); + Assert.assertSame(word3, parentBlock.getChildren().get(0)); + Assert.assertSame(word2, parentBlock.getChildren().get(1)); + Assert.assertSame(word2, word3.getNextSibling()); + Assert.assertSame(word3, word2.getPreviousSibling()); + + // replace by nothing + parentBlock.replaceChild(Collections.emptyList(), word2); + + Assert.assertEquals(1, parentBlock.getChildren().size()); + Assert.assertSame(word3, parentBlock.getChildren().get(0)); + Assert.assertNull(word3.getNextSibling()); + Assert.assertNull(word3.getPreviousSibling()); + + // replace by several + parentBlock.replaceChild(Arrays.asList(word1, word2), word3); + + Assert.assertEquals(2, parentBlock.getChildren().size()); + Assert.assertSame(word1, parentBlock.getChildren().get(0)); + Assert.assertSame(word2, parentBlock.getChildren().get(1)); + Assert.assertSame(word2, word1.getNextSibling()); + Assert.assertSame(word1, word2.getPreviousSibling()); + + // provide not existing block to replace + try { + parentBlock.replaceChild(word3, new WordBlock("not existing")); + Assert.fail("Should have thrown an InvalidParameterException exception"); + } catch (InvalidParameterException expected) { + // expected + } + } + + @Test + public void testClone() { + WordBlock wb = new WordBlock("block"); + ImageBlock ib = new ImageBlock( + new ResourceReference("document@attachment", ResourceType.ATTACHMENT), true); + DocumentResourceReference linkReference = new DocumentResourceReference("reference"); + LinkBlock lb = new LinkBlock(Arrays.asList((Block) new WordBlock("label")), linkReference, + false); + Block rootBlock = new ParagraphBlock(Arrays.asList(wb, ib, lb)); + + Block newRootBlock = rootBlock.clone(); + + Assert.assertNotSame(rootBlock, newRootBlock); + Assert.assertNotSame(wb, newRootBlock.getChildren().get(0)); + Assert.assertNotSame(ib, newRootBlock.getChildren().get(1)); + Assert.assertNotSame(lb, newRootBlock.getChildren().get(2)); + + Assert.assertEquals(wb.getWord(), ((WordBlock) newRootBlock.getChildren().get(0)).getWord()); + Assert.assertNotSame(ib.getReference(), + ((ImageBlock) newRootBlock.getChildren().get(1)).getReference()); + Assert.assertNotSame(lb.getReference(), + ((LinkBlock) newRootBlock.getChildren().get(2)).getReference()); + } + + @Test + public void testGetPreviousBlockByType() { + WordBlock lw = new WordBlock("linkword"); + SpecialSymbolBlock ls = new SpecialSymbolBlock('$'); + + DocumentResourceReference linkReference = new DocumentResourceReference("reference"); + LinkBlock pl = new LinkBlock(Arrays.asList(lw, ls), linkReference, false); + + ImageBlock pi = new ImageBlock( + new ResourceReference("document@attachment", ResourceType.ATTACHMENT), true); + + ParagraphBlock rootBlock = new ParagraphBlock(Arrays.asList(pi, pl)); + + Assert.assertSame(lw, ls.getPreviousBlockByType(WordBlock.class, false)); + Assert.assertNull(ls.getPreviousBlockByType(ImageBlock.class, false)); + Assert.assertSame(pl, ls.getPreviousBlockByType(LinkBlock.class, true)); + Assert.assertSame(pi, ls.getPreviousBlockByType(ImageBlock.class, true)); + Assert.assertSame(rootBlock, ls.getPreviousBlockByType(ParagraphBlock.class, true)); + } + + @Test + public void testGetNextSibling() { + WordBlock b1 = new WordBlock("b1"); + WordBlock b2 = new WordBlock("b2"); + ParagraphBlock p = new ParagraphBlock(Arrays.asList(b1, b2)); + + Assert.assertSame(b2, b1.getNextSibling()); + Assert.assertNull(b2.getNextSibling()); + Assert.assertNull(p.getNextSibling()); + Assert.assertNull(new ParagraphBlock(Collections.emptyList()).getNextSibling()); + } + + @Test + public void testRemoveBlock() { + WordBlock b1 = new WordBlock("b1"); + WordBlock b2 = new WordBlock("b2"); + ParagraphBlock p1 = new ParagraphBlock(Arrays.asList(b1, b2)); + + p1.removeBlock(b1); + Assert.assertEquals(1, p1.getChildren().size()); + Assert.assertSame(b2, p1.getChildren().get(0)); + Assert.assertNull(b1.getPreviousSibling()); + Assert.assertNull(b1.getNextSibling()); + Assert.assertNull(b2.getPreviousSibling()); + + p1.removeBlock(b2); + Assert.assertEquals(0, p1.getChildren().size()); + Assert.assertNull(b2.getPreviousSibling()); + Assert.assertNull(b2.getNextSibling()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/block/ProtectedBlockFilterTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/block/ProtectedBlockFilterTest.java new file mode 100644 index 000000000..6d94ed020 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/block/ProtectedBlockFilterTest.java @@ -0,0 +1,50 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.block; + +import java.util.Arrays; +import java.util.Collections; + +import org.junit.Assert; +import org.junit.Test; +import org.xwiki.rendering.block.Block; +import org.xwiki.rendering.block.MacroMarkerBlock; +import org.xwiki.rendering.block.ParagraphBlock; +import org.xwiki.rendering.block.XDOM; + +/** + * Unit tests for {@link org.xwiki.rendering.internal.block.ProtectedBlockFilter}. + * + * @version $Id$ + * @since 2.6 + */ +public class ProtectedBlockFilterTest { + + @Test + public void testGetNextSibling() { + ProtectedBlockFilter pbf = new ProtectedBlockFilter(); + Block b1 = new ParagraphBlock(Collections.emptyList()); + Block b2 = new MacroMarkerBlock("code", Collections.emptyMap(), + Collections.emptyList(), false); + Block b3 = new ParagraphBlock(Collections.emptyList()); + XDOM xdom = new XDOM(Arrays.asList(b1, b2, b3)); + Assert.assertEquals(b3, pbf.getNextSibling(b1)); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManagerTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManagerTest.java new file mode 100644 index 000000000..013aacd05 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/internal/transformation/DefaultTransformationManagerTest.java @@ -0,0 +1,43 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.transformation; + +import org.junit.Test; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.transformation.TransformationContext; +import org.xwiki.rendering.transformation.TransformationManager; + +import com.celements.common.test.AbstractBaseComponentTest; + +/** + * Unit tests for {@link DefaultTransformationManager}. + * + * @version $Id$ + */ +public class DefaultTransformationManagerTest extends AbstractBaseComponentTest { + + @Test + public void testTransformations() throws Exception { + TransformationManager manager = getComponentManager().lookup(TransformationManager.class); + manager.performTransformations(XDOM.EMPTY, + new TransformationContext(XDOM.EMPTY, Syntax.XWIKI_2_0)); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListenerTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListenerTest.java new file mode 100644 index 000000000..05de52114 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/EmptyBlockChainingListenerTest.java @@ -0,0 +1,96 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import java.util.Collections; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Unit tests for {@link LookaheadChainingListener}. + * + * @version $Id$ + * @since 2.0M3 + */ +public class EmptyBlockChainingListenerTest { + + private ListenerChain chain; + + private EmptyBlockChainingListener listener; + + @Before + public void setUp() { + chain = new ListenerChain(); + listener = new EmptyBlockChainingListener(chain); + chain.addListener(listener); + } + + /** + * Verify that isCurrentContainerBlockEmpty return true if there's no children inside a paragraph + * container block. + */ + @Test + public void testEmptyParagraphContainer() { + chain.addListener(new AbstractChainingListener() { + + { + setListenerChain(chain); + } + + @Override + public void endParagraph(Map parameters) { + EmptyBlockChainingListener blockState = (EmptyBlockChainingListener) getListenerChain() + .getListener(EmptyBlockChainingListener.class); + Assert.assertTrue(blockState.isCurrentContainerBlockEmpty()); + } + }); + + listener.beginParagraph(Collections.emptyMap()); + listener.endParagraph(Collections.emptyMap()); + } + + /** + * Verify that isCurrentContainerBlockEmpty return false if there are children inside a paragraph + * container block. + */ + @Test + public void testNonEmptyParagraphContainer() { + chain.addListener(new AbstractChainingListener() { + + { + setListenerChain(chain); + } + + @Override + public void endParagraph(Map parameters) { + EmptyBlockChainingListener blockState = (EmptyBlockChainingListener) getListenerChain() + .getListener(EmptyBlockChainingListener.class); + Assert.assertFalse(blockState.isCurrentContainerBlockEmpty()); + } + }); + + listener.beginParagraph(Collections.emptyMap()); + listener.onWord("word"); + listener.endParagraph(Collections.emptyMap()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListenerTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListenerTest.java new file mode 100644 index 000000000..ec76b163b --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/listener/chaining/LookaheadChainingListenerTest.java @@ -0,0 +1,102 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.listener.chaining; + +import java.util.Collections; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Unit tests for {@link LookaheadChainingListener}. + * + * @version $Id$ + * @since 1.8RC1 + */ +public class LookaheadChainingListenerTest { + + public class TestChainingListener extends AbstractChainingListener { + + public int calls = 0; + + public TestChainingListener(ListenerChain listenerChain) { + setListenerChain(listenerChain); + } + + @Override + public void beginDocument(Map parameters) { + this.calls++; + } + + @Override + public void beginParagraph(Map parameters) { + this.calls++; + } + + @Override + public void endDocument(Map parameters) { + this.calls++; + } + + @Override + public void endParagraph(Map parameters) { + this.calls++; + } + } + + @Test + public void testLookahead() { + ListenerChain chain = new ListenerChain(); + LookaheadChainingListener listener = new LookaheadChainingListener(chain, 2); + chain.addListener(listener); + TestChainingListener testListener = new TestChainingListener(chain); + chain.addListener(testListener); + + // The begin document flushes + listener.beginDocument(Collections.emptyMap()); + Assert.assertEquals(1, testListener.calls); + + // 1st lookahead, nothing is sent to the test listener + listener.beginParagraph(Collections.emptyMap()); + Assert.assertEquals(1, testListener.calls); + Assert.assertEquals(EventType.BEGIN_PARAGRAPH, listener.getNextEvent().eventType); + Assert.assertNull(listener.getNextEvent(2)); + + // 2nd lookahead, nothing is sent to the test listener + listener.beginParagraph(Collections.emptyMap()); + Assert.assertEquals(1, testListener.calls); + Assert.assertEquals(EventType.BEGIN_PARAGRAPH, listener.getNextEvent().eventType); + Assert.assertEquals(EventType.BEGIN_PARAGRAPH, listener.getNextEvent(2).eventType); + Assert.assertNull(listener.getNextEvent(3)); + + // 3rd events, the first begin paragraph is sent + listener.endParagraph(Collections.emptyMap()); + Assert.assertEquals(2, testListener.calls); + Assert.assertEquals(EventType.BEGIN_PARAGRAPH, listener.getNextEvent().eventType); + Assert.assertEquals(EventType.END_PARAGRAPH, listener.getNextEvent(2).eventType); + Assert.assertNull(listener.getNextEvent(3)); + + // The end document flushes + listener.endDocument(Collections.emptyMap()); + Assert.assertEquals(5, testListener.calls); + Assert.assertNull(listener.getNextEvent()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/parser/SyntaxTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/parser/SyntaxTest.java new file mode 100644 index 000000000..ccb54dca8 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/parser/SyntaxTest.java @@ -0,0 +1,62 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.parser; + +import org.xwiki.rendering.syntax.Syntax; +import org.xwiki.rendering.syntax.SyntaxType; + +import junit.framework.TestCase; + +/** + * Unit tests for {@link org.xwiki.rendering.syntax.Syntax}. + * + * @version $Id$ + * @since 1.5M2 + */ +public class SyntaxTest extends TestCase { + + public void testEquality() { + Syntax syntax1 = new Syntax(new SyntaxType("mytype", "My Type"), "1.0"); + Syntax syntax2 = new Syntax(new SyntaxType("mytype", "My Type"), "1.0"); + Syntax syntax3 = new Syntax(new SyntaxType("mytype", "Still same type"), "1.0"); + + assertEquals("mytype", syntax1.getType().getId()); + assertEquals("My Type", syntax1.getType().getName()); + + assertEquals(syntax2, syntax1); + // The syntax type name is not part of the equality test. + assertEquals(syntax3, syntax1); + } + + public void testNonEquality() { + Syntax syntax1 = new Syntax(SyntaxType.XWIKI, "1.0"); + Syntax syntax2 = new Syntax(SyntaxType.XWIKI, "2.0"); + Syntax syntax3 = new Syntax(SyntaxType.CONFLUENCE, "1.0"); + + assertFalse(syntax2.equals(syntax1)); + assertFalse(syntax3.equals(syntax1)); + } + + public void testToString() { + Syntax syntax = new Syntax(SyntaxType.XWIKI, "1.0"); + assertEquals("XWiki 1.0", syntax.toString()); + assertEquals("xwiki/1.0", syntax.toIdString()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/scaffolding/BlockAssert.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/scaffolding/BlockAssert.java new file mode 100644 index 000000000..e1eadd393 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/scaffolding/BlockAssert.java @@ -0,0 +1,59 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.scaffolding; + +import java.util.List; + +import org.xwiki.rendering.block.Block; +import org.xwiki.rendering.block.XDOM; +import org.xwiki.rendering.renderer.PrintRenderer; +import org.xwiki.rendering.renderer.PrintRendererFactory; +import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter; +import org.xwiki.rendering.renderer.printer.WikiPrinter; + +/** + * Class to be imported in unit tests as a static import and which contains helper methods to assert + * Rendering Blocks. + * + * @version $Id$ + * @since 2.4M2 + */ +public class BlockAssert { + + /** + * Protect constructor since it is a static only class + */ + protected BlockAssert() { + // Nothing to do + } + + public static void assertBlocks(String expected, List blocks, PrintRendererFactory factory) + throws Exception { + // Assert the result by parsing it through the EventsRenderer to generate easily + // assertable events. + XDOM dom = new XDOM(blocks); + WikiPrinter printer = new DefaultWikiPrinter(); + + PrintRenderer eventRenderer = factory.createRenderer(printer); + + dom.traverse(eventRenderer); + junit.framework.Assert.assertEquals(expected, printer.toString()); + } +} diff --git a/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/util/IdGeneratorTest.java b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/util/IdGeneratorTest.java new file mode 100644 index 000000000..1e59d2b37 --- /dev/null +++ b/celements-xwiki-rendering-api/src/test/java/org/xwiki/rendering/util/IdGeneratorTest.java @@ -0,0 +1,83 @@ +package org.xwiki.rendering.util; + +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +import junit.framework.TestCase; + +/** + * Validate {@link IdGenerator}. + * + * @version $Id$ + */ +public class IdGeneratorTest extends TestCase { + + private IdGenerator idGenerator; + + /** + * {@inheritDoc} + * + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + + this.idGenerator = new IdGenerator(); + } + + public void testGenerateUniqueId() { + assertEquals("Itext", this.idGenerator.generateUniqueId("text")); + assertEquals("Itext-1", this.idGenerator.generateUniqueId("te xt")); + } + + public void testGenerateUniqueIdWithPrefix() { + assertEquals("prefixtext", this.idGenerator.generateUniqueId("prefix", "text")); + assertEquals("prefixtext-1", this.idGenerator.generateUniqueId("prefix", "te xt")); + } + + public void testGenerateUniqueIdFromNonAlphaNum() { + assertEquals("I:_.-", this.idGenerator.generateUniqueId(":_.-")); + assertEquals("Iwithspace", this.idGenerator.generateUniqueId("with space")); + assertEquals("Iwithtab", this.idGenerator.generateUniqueId("with\ttab")); + assertEquals("I5BC67801", this.idGenerator.generateUniqueId("\u5BC6\u7801")); + assertEquals("I3D", this.idGenerator.generateUniqueId("=")); + } + + public void testGenerateUniqueIdWhenInvalidEmptyPrefix() { + try { + this.idGenerator.generateUniqueId("", "whatever"); + fail("Should have thrown an exception"); + } catch (IllegalArgumentException expected) { + assertEquals("The prefix [] should only contain alphanumerical characters and not be empty.", + expected.getMessage()); + } + } + + public void testGenerateUniqueIdWhenInvalidNonAlphaPrefix() { + try { + this.idGenerator.generateUniqueId("a-b", "whatever"); + fail("Should have thrown an exception"); + } catch (IllegalArgumentException expected) { + assertEquals( + "The prefix [a-b] should only contain alphanumerical characters and not be empty.", + expected.getMessage()); + } + } +} diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityConfiguration.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityConfiguration.java index a84a1c393..150660932 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityConfiguration.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityConfiguration.java @@ -26,25 +26,27 @@ /** * Configuration properties for the Velocity module. *

- * You can override the default values for each of the configuration properties below by defining them in XWiki's global + * You can override the default values for each of the configuration properties below by defining + * them in XWiki's global * configuration file using a prefix of "velocity" followed by the property name. For example: * velocity.tools = listtool = org.apache.velocity.tools.generic.ListTool * * @version $Id$ - * * @since 2.0M1 */ @ComponentRole public interface VelocityConfiguration { - /** - * @return the Velocity properties as defined at - * http://velocity.apache.org/engine/devel/developer-guide.html#Velocity_Configuration_Keys_and_Values - */ - Properties getProperties(); - /** - * @return the list of configured Velocity Tools (the key is the name under which the tool will be available in the - * Velocity Context and the value is the tool's class name) - */ - Properties getTools(); + /** + * @return the Velocity properties as defined at + * http://velocity.apache.org/engine/devel/developer-guide.html#Velocity_Configuration_Keys_and_Values + */ + Properties getProperties(); + + /** + * @return the list of configured Velocity Tools (the key is the name under which the tool will be + * available in the + * Velocity Context and the value is the tool's class name) + */ + Properties getTools(); } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityContextFactory.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityContextFactory.java index a18286677..d0e308244 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityContextFactory.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityContextFactory.java @@ -24,9 +24,12 @@ import org.xwiki.component.annotation.ComponentRole; /** - * Creates Velocity Context instances, pre-populated with the Velocity Tools enabled in the component's configuration, - * and by all the enabled {@link VelocityContextInitializer} components. The returned context is supposed to be used - * only once, as otherwise data may leak between different requests, and the parsing/rendering process would be affected + * Creates Velocity Context instances, pre-populated with the Velocity Tools enabled in the + * component's configuration, + * and by all the enabled {@link VelocityContextInitializer} components. The returned context is + * supposed to be used + * only once, as otherwise data may leak between different requests, and the parsing/rendering + * process would be affected * by previous data. * * @version $Id$ @@ -34,13 +37,13 @@ @ComponentRole public interface VelocityContextFactory { - /** - * Creates and initializes a new Velocity Context. - * - * @return a new Velocity Context, populated with Tools and data pushed by {@link VelocityContextInitializer}s - * - * @throws XWikiVelocityException - * if the context failed to be created or initialized properly - */ - VelocityContext createContext() throws XWikiVelocityException; + /** + * Creates and initializes a new Velocity Context. + * + * @return a new Velocity Context, populated with Tools and data pushed by + * {@link VelocityContextInitializer}s + * @throws XWikiVelocityException + * if the context failed to be created or initialized properly + */ + VelocityContext createContext() throws XWikiVelocityException; } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityContextInitializer.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityContextInitializer.java index 84e456689..1fb7125c5 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityContextInitializer.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityContextInitializer.java @@ -27,16 +27,16 @@ * Populates new Velocity contexts with custom entries. * * @version $Id$ - * * @since 1.5M1 */ @ComponentRole public interface VelocityContextInitializer { - /** - * Allow initializing the Velocity Context by putting objects into it. - * - * @param context - * the Velocity context to initialize - */ - void initialize(VelocityContext context); + + /** + * Allow initializing the Velocity Context by putting objects into it. + * + * @param context + * the Velocity context to initialize + */ + void initialize(VelocityContext context); } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityEngine.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityEngine.java index 360ae9b35..edd3cdc92 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityEngine.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityEngine.java @@ -34,83 +34,81 @@ */ @ComponentRole public interface VelocityEngine { - /** - * Initializes the Velocity engine by setting its configuration both from the component's configuration and from the - * passed properties. This method must be called before any other method from this class can be executed. - * - * @param properties - * the properties that will override the static properties defined in the component's configuration - * - * @throws XWikiVelocityException - * in case of error - */ - void initialize(Properties properties) throws XWikiVelocityException; - /** - * Renders the input string using the context into the output writer. - * - * @param context - * the Velocity context to use in rendering the input string - * @param out - * the writer in which to render the output - * @param templateName - * the string to be used as the template name for log messages in case of error - * @param source - * the input string containing the VTL to be rendered - * - * @return true if successful, false otherwise. If false, see the Velocity runtime log - * - * @throws XWikiVelocityException - * in case of error - */ - boolean evaluate(Context context, Writer out, String templateName, String source) throws XWikiVelocityException; + /** + * Initializes the Velocity engine by setting its configuration both from the component's + * configuration and from the + * passed properties. This method must be called before any other method from this class can be + * executed. + * + * @param properties + * the properties that will override the static properties defined in the component's + * configuration + * @throws XWikiVelocityException + * in case of error + */ + void initialize(Properties properties) throws XWikiVelocityException; - /** - * Renders the input string using the context into the output writer. - * - * @param context - * the Velocity context to use in rendering the input string - * @param out - * the writer in which to render the output - * @param templateName - * the string to be used as the template name for log messages in case of error - * @param source - * the input containing the VTL to be rendered, as a Reader - * - * @return true if successful, false otherwise. If false, see the Velocity runtime log - * - * @throws XWikiVelocityException - * in case of error - */ - boolean evaluate(Context context, Writer out, String templateName, Reader source) throws XWikiVelocityException; + /** + * Renders the input string using the context into the output writer. + * + * @param context + * the Velocity context to use in rendering the input string + * @param out + * the writer in which to render the output + * @param templateName + * the string to be used as the template name for log messages in case of error + * @param source + * the input string containing the VTL to be rendered + * @return true if successful, false otherwise. If false, see the Velocity runtime log + * @throws XWikiVelocityException + * in case of error + */ + boolean evaluate(Context context, Writer out, String templateName, String source) + throws XWikiVelocityException; - /** - * Clear the internal Velocity Macro cache for the passed namespace. - * - * @param templateName - * the namespace for which to remove all cached Velocity macros - * - * @since 2.4M2 - */ - void clearMacroNamespace(String templateName); + /** + * Renders the input string using the context into the output writer. + * + * @param context + * the Velocity context to use in rendering the input string + * @param out + * the writer in which to render the output + * @param templateName + * the string to be used as the template name for log messages in case of error + * @param source + * the input containing the VTL to be rendered, as a Reader + * @return true if successful, false otherwise. If false, see the Velocity runtime log + * @throws XWikiVelocityException + * in case of error + */ + boolean evaluate(Context context, Writer out, String templateName, Reader source) + throws XWikiVelocityException; - /** - * Notify that a rendering action is starting in the given namespace. - * - * @param namespace - * the namespace being used - * - * @since 2.4RC1 - */ - void startedUsingMacroNamespace(String namespace); + /** + * Clear the internal Velocity Macro cache for the passed namespace. + * + * @param templateName + * the namespace for which to remove all cached Velocity macros + * @since 2.4M2 + */ + void clearMacroNamespace(String templateName); - /** - * Notify that a rendering action in the given namespace just finished. - * - * @param namespace - * the namespace which was used - * - * @since 2.4RC1 - */ - void stoppedUsingMacroNamespace(String namespace); + /** + * Notify that a rendering action is starting in the given namespace. + * + * @param namespace + * the namespace being used + * @since 2.4RC1 + */ + void startedUsingMacroNamespace(String namespace); + + /** + * Notify that a rendering action in the given namespace just finished. + * + * @param namespace + * the namespace which was used + * @since 2.4RC1 + */ + void stoppedUsingMacroNamespace(String namespace); } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityFactory.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityFactory.java index e4a301229..8bee74761 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityFactory.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityFactory.java @@ -25,61 +25,75 @@ import org.xwiki.component.annotation.ComponentRole; /** - * Allows creating different Velocity engine instances. This is useful when you need to have different Velocity engines - * running in the same JVM but with different configurations. Since global templates in Velocity are part of the - * configuration the only solution to use different global templates is to use different Velocity engines. As an example + * Allows creating different Velocity engine instances. This is useful when you need to have + * different Velocity engines + * running in the same JVM but with different configurations. Since global templates in Velocity are + * part of the + * configuration the only solution to use different global templates is to use different Velocity + * engines. As an example * we need this in XWiki since we want to allow each Skin to provide its own global macros. * * @version $Id$ */ @ComponentRole public interface VelocityFactory { - /** - * Check if an engine was already created for a certain key. - * - * @param key - * the key under which the Velocity engine has been saved in cache. This is the key used when the - * Velocity engine was created using {@link #createVelocityEngine(String, java.util.Properties)} - * - * @return true if there is a cached Velocity Engine matching the passed key, false - * otherwise. - */ - boolean hasVelocityEngine(String key); - /** - * Retrieves from the cache the Velocity engine corresponding to a specific key, if such an engine was already - * created. - * - * @param key - * the key under which the Velocity engine has been saved in cache. This is the key used when the - * Velocity engine was created using {@link #createVelocityEngine(String, java.util.Properties)} - * - * @return the cached Velocity engine instance corresponding to the passed key or null if not found - */ - VelocityEngine getVelocityEngine(String key); + /** + * Check if an engine was already created for a certain key. + * + * @param key + * the key under which the Velocity engine has been saved in cache. This is the key used + * when the + * Velocity engine was created using + * {@link #createVelocityEngine(String, java.util.Properties)} + * @return true if there is a cached Velocity Engine matching the passed key, + * false + * otherwise. + */ + boolean hasVelocityEngine(String key); - /** - * Creates a new Velocity engine instance, which will be cached using a specific key for later reuse. The key allows - * having different Velocity Engines, so that each one can have its own special configuration. This is especially - * handy for having different sets of global Velocity libraries (such as for different XWiki Skins for example). If - * another engine was previously created for the same key, then that instance is returned instead, without creating - * any other instance. - * - * @param key - * the key used to cache the Velocity engine instance to return - * @param properties - * the list of properties that will override the default properties when creating the engine. For example - * it's possible to define a list of global velocimacros by passing the - * RuntimeConstants.VM_LIBRARY property key. - * - * @return the newly created Velocity Engine, or an existing one, if an engine was previously created for the same - * key. - * - * @throws XWikiVelocityException - * if the Velocity Engine cannot be initialized for some reason - * - * @todo How to create a new engine instance when parameters have changed? Shouldn't this discard the old instance - * and create a new one, instead? - */ - VelocityEngine createVelocityEngine(String key, Properties properties) throws XWikiVelocityException; + /** + * Retrieves from the cache the Velocity engine corresponding to a specific key, if such an engine + * was already + * created. + * + * @param key + * the key under which the Velocity engine has been saved in cache. This is the key used + * when the + * Velocity engine was created using + * {@link #createVelocityEngine(String, java.util.Properties)} + * @return the cached Velocity engine instance corresponding to the passed key or + * null if not found + */ + VelocityEngine getVelocityEngine(String key); + + /** + * Creates a new Velocity engine instance, which will be cached using a specific key for later + * reuse. The key allows + * having different Velocity Engines, so that each one can have its own special configuration. + * This is especially + * handy for having different sets of global Velocity libraries (such as for different XWiki Skins + * for example). If + * another engine was previously created for the same key, then that instance is returned instead, + * without creating + * any other instance. + * + * @param key + * the key used to cache the Velocity engine instance to return + * @param properties + * the list of properties that will override the default properties when creating the + * engine. For example + * it's possible to define a list of global velocimacros by passing the + * RuntimeConstants.VM_LIBRARY property key. + * @return the newly created Velocity Engine, or an existing one, if an engine was previously + * created for the same + * key. + * @throws XWikiVelocityException + * if the Velocity Engine cannot be initialized for some reason + * @todo How to create a new engine instance when parameters have changed? Shouldn't this discard + * the old instance + * and create a new one, instead? + */ + VelocityEngine createVelocityEngine(String key, Properties properties) + throws XWikiVelocityException; } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityManager.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityManager.java index 7975b094b..c9fd97bd1 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityManager.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/VelocityManager.java @@ -27,26 +27,25 @@ * Provides access to the main XWiki Velocity objects. * * @since 1.5M2 - * * @version $Id$ */ @ComponentRole public interface VelocityManager { - /** - * @return the current Velocity Context retrieved from the Execution Context - */ - VelocityContext getVelocityContext(); - /** - * Get the current Velocity Engine or create one if none has been created. - * - * @return the current Velocity Engine retrieved from the Execution Context - * - * @throws XWikiVelocityException - * if the Velocity Engine cannot be created - * - * @todo Move the engine creation to some initialization method instead and remove the need for throwing an - * exception - */ - VelocityEngine getVelocityEngine() throws XWikiVelocityException; + /** + * @return the current Velocity Context retrieved from the Execution Context + */ + VelocityContext getVelocityContext(); + + /** + * Get the current Velocity Engine or create one if none has been created. + * + * @return the current Velocity Engine retrieved from the Execution Context + * @throws XWikiVelocityException + * if the Velocity Engine cannot be created + * @todo Move the engine creation to some initialization method instead and remove the need for + * throwing an + * exception + */ + VelocityEngine getVelocityEngine() throws XWikiVelocityException; } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/XWikiVelocityException.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/XWikiVelocityException.java index 69be61c27..94f45d579 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/XWikiVelocityException.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/XWikiVelocityException.java @@ -26,34 +26,33 @@ * @version $Id$ */ public class XWikiVelocityException extends Exception { - /** - * Provides an id for serialization. - */ - private static final long serialVersionUID = 2035182137507870523L; - /** - * Constructs a new exception with the specified detail message. - * - * @param message - * the exception message - * - * @see Exception#Exception(String) - */ - public XWikiVelocityException(String message) { - super(message); - } + /** + * Provides an id for serialization. + */ + private static final long serialVersionUID = 2035182137507870523L; - /** - * Constructs a new exception with the specified detail message and cause. - * - * @param message - * the exception message - * @param throwable - * the original exception to wrap - * - * @see Exception#Exception(String, Throwable) - */ - public XWikiVelocityException(String message, Throwable throwable) { - super(message, throwable); - } + /** + * Constructs a new exception with the specified detail message. + * + * @param message + * the exception message + * @see Exception#Exception(String) + */ + public XWikiVelocityException(String message) { + super(message); + } + + /** + * Constructs a new exception with the specified detail message and cause. + * + * @param message + * the exception message + * @param throwable + * the original exception to wrap + * @see Exception#Exception(String, Throwable) + */ + public XWikiVelocityException(String message, Throwable throwable) { + super(message, throwable); + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityConfiguration.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityConfiguration.java index 5580c2293..eec7b6632 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityConfiguration.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityConfiguration.java @@ -43,83 +43,87 @@ * All configuration options for the Velocity subsystem. * * @version $Id$ - * * @since 2.0M1 */ @Component public class DefaultVelocityConfiguration implements Initializable, VelocityConfiguration { - /** - * Prefix for configuration keys for the Velocity module. - */ - private static final String PREFIX = "velocity."; - /** - * Defines from where to read the rendering configuration data. - */ - @Requirement - private ConfigurationSource configuration; + /** + * Prefix for configuration keys for the Velocity module. + */ + private static final String PREFIX = "velocity."; + + /** + * Defines from where to read the rendering configuration data. + */ + @Requirement + private ConfigurationSource configuration; - /** - * Default Tools. - */ - private Properties defaultTools = new Properties(); + /** + * Default Tools. + */ + private Properties defaultTools = new Properties(); - /** - * Default properties. - */ - private Properties defaultProperties = new Properties(); + /** + * Default properties. + */ + private Properties defaultProperties = new Properties(); - /** - * {@inheritDoc} - * - * @see org.xwiki.component.phase.Initializable#initialize() - */ - public void initialize() throws InitializationException { - // Default Velocity tools. - this.defaultTools.setProperty("listtool", ListTool.class.getName()); - this.defaultTools.setProperty("numbertool", NumberTool.class.getName()); - this.defaultTools.setProperty("datetool", ComparisonDateTool.class.getName()); - this.defaultTools.setProperty("mathtool", MathTool.class.getName()); - this.defaultTools.setProperty("sorttool", SortTool.class.getName()); - this.defaultTools.setProperty("escapetool", EscapeTool.class.getName()); - this.defaultTools.setProperty("regextool", RegexTool.class.getName()); + /** + * {@inheritDoc} + * + * @see org.xwiki.component.phase.Initializable#initialize() + */ + public void initialize() throws InitializationException { + // Default Velocity tools. + this.defaultTools.setProperty("listtool", ListTool.class.getName()); + this.defaultTools.setProperty("numbertool", NumberTool.class.getName()); + this.defaultTools.setProperty("datetool", ComparisonDateTool.class.getName()); + this.defaultTools.setProperty("mathtool", MathTool.class.getName()); + this.defaultTools.setProperty("sorttool", SortTool.class.getName()); + this.defaultTools.setProperty("escapetool", EscapeTool.class.getName()); + this.defaultTools.setProperty("regextool", RegexTool.class.getName()); - // Default Velocity properties - this.defaultProperties.setProperty("resource.loader", "webapp"); - this.defaultProperties.setProperty("directive.set.null.allowed", Boolean.TRUE.toString()); - this.defaultProperties.setProperty("webapp.resource.loader.class", WebappLoader.class.getName()); - this.defaultProperties.setProperty("velocimacro.messages.on", Boolean.FALSE.toString()); - this.defaultProperties.setProperty("resource.manager.logwhenfound", Boolean.FALSE.toString()); - this.defaultProperties.setProperty("velocimacro.permissions.allow.inline.local.scope", Boolean.TRUE.toString()); - // Prevents users from writing dangerous Velocity code like using Class.forName or Java threading APIs. - this.defaultProperties.setProperty("runtime.introspector.uberspect", ChainingUberspector.class.getName()); - this.defaultProperties.setProperty("runtime.introspector.uberspect.chainClasses", - SecureUberspector.class.getName() + "," + DeprecatedCheckUberspector.class.getName()); - } + // Default Velocity properties + this.defaultProperties.setProperty("resource.loader", "webapp"); + this.defaultProperties.setProperty("directive.set.null.allowed", Boolean.TRUE.toString()); + this.defaultProperties.setProperty("webapp.resource.loader.class", + WebappLoader.class.getName()); + this.defaultProperties.setProperty("velocimacro.messages.on", Boolean.FALSE.toString()); + this.defaultProperties.setProperty("resource.manager.logwhenfound", Boolean.FALSE.toString()); + this.defaultProperties.setProperty("velocimacro.permissions.allow.inline.local.scope", + Boolean.TRUE.toString()); + // Prevents users from writing dangerous Velocity code like using Class.forName or Java + // threading APIs. + this.defaultProperties.setProperty("runtime.introspector.uberspect", + ChainingUberspector.class.getName()); + this.defaultProperties.setProperty("runtime.introspector.uberspect.chainClasses", + SecureUberspector.class.getName() + "," + DeprecatedCheckUberspector.class.getName()); + } - /** - * {@inheritDoc} - * - * @see VelocityConfiguration#getProperties() - */ - public Properties getProperties() { - // Merge default properties and properties defined in the configuration - Properties props = new Properties(); - props.putAll(this.defaultProperties); - props.putAll(this.configuration.getProperty(PREFIX + "properties", Properties.class)); - return props; - } + /** + * {@inheritDoc} + * + * @see VelocityConfiguration#getProperties() + */ + public Properties getProperties() { + // Merge default properties and properties defined in the configuration + Properties props = new Properties(); + props.putAll(this.defaultProperties); + props.putAll(this.configuration.getProperty(PREFIX + "properties", Properties.class)); + return props; + } - /** - * {@inheritDoc} - * - * @see VelocityConfiguration#getTools() - */ - public Properties getTools() { - // Merge default tools and tools defined in the configuration - Properties props = new Properties(); - props.putAll(this.defaultTools); - props.putAll(this.configuration.getProperty(PREFIX + "tools", Properties.class)); - return props; - } + /** + * {@inheritDoc} + * + * @see VelocityConfiguration#getTools() + */ + public Properties getTools() { + // Merge default tools and tools defined in the configuration + Properties props = new Properties(); + props.putAll(this.defaultTools); + props.putAll(this.configuration.getProperty(PREFIX + "tools", Properties.class)); + return props; + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityContextFactory.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityContextFactory.java index b9bba91ed..9b2ec759e 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityContextFactory.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityContextFactory.java @@ -43,70 +43,74 @@ * @version $Id$ */ @Component -public class DefaultVelocityContextFactory extends AbstractLogEnabled implements VelocityContextFactory, Initializable { - /** - * The component manager we used to find all components implementing the - * {@link org.xwiki.velocity.VelocityContextInitializer} role. - */ - @Requirement - private ComponentManager componentManager; +public class DefaultVelocityContextFactory extends AbstractLogEnabled + implements VelocityContextFactory, Initializable { - /** - * Velocity configuration to get the list of configured Velocity tools. - */ - @Requirement - private VelocityConfiguration velocityConfiguration; + /** + * The component manager we used to find all components implementing the + * {@link org.xwiki.velocity.VelocityContextInitializer} role. + */ + @Requirement + private ComponentManager componentManager; - /** - * An internal read-only Velocity Context containing the Tools defined in the component's configuration. We reuse - * them across Contexts for better performance. - */ - private Context toolsContext; + /** + * Velocity configuration to get the list of configured Velocity tools. + */ + @Requirement + private VelocityConfiguration velocityConfiguration; - /** - * {@inheritDoc} - * - * @see Initializable#initialize() - */ - public void initialize() throws InitializationException { - this.toolsContext = new VelocityContext(); + /** + * An internal read-only Velocity Context containing the Tools defined in the component's + * configuration. We reuse + * them across Contexts for better performance. + */ + private Context toolsContext; - // Instantiate Velocity tools - Properties properties = this.velocityConfiguration.getTools(); - if (properties != null) { - for (Enumeration props = properties.propertyNames(); props.hasMoreElements();) { - String key = props.nextElement().toString(); - String value = properties.getProperty(key); - Object toolInstance; - try { - toolInstance = Class.forName(value).newInstance(); - } catch (Exception e) { - throw new InitializationException("Failed to initialize tool [" + value + "]", e); - } - this.toolsContext.put(key, toolInstance); - getLogger().debug("Setting tool [" + key + "] = [" + value + "]"); - } - } - } - - /** - * {@inheritDoc} - * - * @see VelocityContextFactory#createContext() - */ - public VelocityContext createContext() throws XWikiVelocityException { - // Note: This constructor uses the passed context as an internal read-only context. - VelocityContext context = new VelocityContext(this.toolsContext); + /** + * {@inheritDoc} + * + * @see Initializable#initialize() + */ + public void initialize() throws InitializationException { + this.toolsContext = new VelocityContext(); - // Call all components implementing the VelocityContextInitializer's role. + // Instantiate Velocity tools + Properties properties = this.velocityConfiguration.getTools(); + if (properties != null) { + for (Enumeration props = properties.propertyNames(); props.hasMoreElements();) { + String key = props.nextElement().toString(); + String value = properties.getProperty(key); + Object toolInstance; try { - for (Object interceptor : this.componentManager.lookupList(VelocityContextInitializer.class)) { - ((VelocityContextInitializer) interceptor).initialize(context); - } - } catch (ComponentLookupException e) { - throw new XWikiVelocityException("Failed to locate some Velocity Context initializers", e); + toolInstance = Class.forName(value).newInstance(); + } catch (Exception e) { + throw new InitializationException("Failed to initialize tool [" + value + "]", e); } + this.toolsContext.put(key, toolInstance); + getLogger().debug("Setting tool [" + key + "] = [" + value + "]"); + } + } + } + + /** + * {@inheritDoc} + * + * @see VelocityContextFactory#createContext() + */ + public VelocityContext createContext() throws XWikiVelocityException { + // Note: This constructor uses the passed context as an internal read-only context. + VelocityContext context = new VelocityContext(this.toolsContext); - return context; + // Call all components implementing the VelocityContextInitializer's role. + try { + for (Object interceptor : this.componentManager + .lookupList(VelocityContextInitializer.class)) { + ((VelocityContextInitializer) interceptor).initialize(context); + } + } catch (ComponentLookupException e) { + throw new XWikiVelocityException("Failed to locate some Velocity Context initializers", e); } + + return context; + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityEngine.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityEngine.java index 1c11b879a..96d897cd3 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityEngine.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityEngine.java @@ -48,8 +48,10 @@ import org.xwiki.velocity.XWikiVelocityException; /** - * Default implementation of the Velocity service which initializes the Velocity system using configuration values - * defined in the component's configuration. Note that the {@link #initialize} method has to be executed before any + * Default implementation of the Velocity service which initializes the Velocity system using + * configuration values + * defined in the component's configuration. Note that the {@link #initialize} method has to be + * executed before any * other method can be called. * * @version $Id$ @@ -58,324 +60,325 @@ @InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) public class DefaultVelocityEngine implements VelocityEngine, LogChute { - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultVelocityEngine.class); - - /** - * The name of the Velocity configuration property that specifies the ResourceLoader that Velocity should use when - * locating velocimacros. - */ - private static final String RESOURCE_LOADER = "resource.loader"; - - /** - * The Velocity engine we're wrapping. - */ - private org.apache.velocity.app.VelocityEngine engine; - - /** - * Velocity configuration to get the list of configured Velocity properties. - */ - @Requirement - private VelocityConfiguration velocityConfiguration; - - /** - * The Container component. We need it in order to store the ServletContext as a property in the Application Context - * so that the Velocity Tools WebappLoader can find it. - */ - @Requirement - private Container container; - - /** - * See the comment in {@link #init(org.apache.velocity.runtime.RuntimeServices)}. - */ - private RuntimeServices rsvc; - - /** Counter for the number of active rendering processes using each namespace. */ - private final Map namespaceUsageCount = new HashMap<>(); - - /** - * {@inheritDoc} - * - * @see VelocityEngine#initialize(Properties) - */ - @Override - public void initialize(Properties properties) throws XWikiVelocityException { - this.engine = new org.apache.velocity.app.VelocityEngine(); - - Properties velocityProperties = this.velocityConfiguration.getProperties(); - - // If the Velocity configuration uses the - // org.apache.velocity.tools.view.servlet.WebappLoader Velocity Tools class - // then we need to set the ServletContext object as a Velocity Application Attribute as - // it's used to load resources from the webapp directory in WebapLoader. - String resourceLoader = properties.getProperty(RESOURCE_LOADER, - velocityProperties.getProperty(RESOURCE_LOADER)); - if ((resourceLoader != null) && resourceLoader.equals("webapp")) { - ApplicationContext context = this.container.getApplicationContext(); - if (context instanceof ServletApplicationContext) { - getEngine().setApplicationAttribute("javax.servlet.ServletContext", - ((ServletApplicationContext) context).getServletContext()); - } - } - - // Avoid "unable to find resource 'VM_global_library.vm' in any resource loader." if no - // Velocimacro library is defined. This value is overriden below. - getEngine().setProperty("velocimacro.library", ""); - - getEngine().setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, this); - - // Configure Velocity by passing the properties defined in this component's configuration - if (velocityProperties != null) { - for (Enumeration e = velocityProperties.propertyNames(); e.hasMoreElements();) { - String key = e.nextElement().toString(); - // Only set a property if it's not overridden by one of the passed properties - if (!properties.containsKey(key)) { - String value = velocityProperties.getProperty(key); - getEngine().setProperty(key, value); - LOGGER.debug("Setting property [{}] = [{}]", key, value); - } - } - } - - // Override the component's static properties with the ones passed in parameter - if (properties != null) { - for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) { - String key = e.nextElement().toString(); - String value = properties.getProperty(key); - getEngine().setProperty(key, value); - LOGGER.debug("Overriding property [{}] = [{}]", key, value); - } - } + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultVelocityEngine.class); + + /** + * The name of the Velocity configuration property that specifies the ResourceLoader that Velocity + * should use when + * locating velocimacros. + */ + private static final String RESOURCE_LOADER = "resource.loader"; + + /** + * The Velocity engine we're wrapping. + */ + private org.apache.velocity.app.VelocityEngine engine; + + /** + * Velocity configuration to get the list of configured Velocity properties. + */ + @Requirement + private VelocityConfiguration velocityConfiguration; + + /** + * The Container component. We need it in order to store the ServletContext as a property in the + * Application Context + * so that the Velocity Tools WebappLoader can find it. + */ + @Requirement + private Container container; + + /** + * See the comment in {@link #init(org.apache.velocity.runtime.RuntimeServices)}. + */ + private RuntimeServices rsvc; + + /** Counter for the number of active rendering processes using each namespace. */ + private final Map namespaceUsageCount = new HashMap<>(); + + /** + * {@inheritDoc} + * + * @see VelocityEngine#initialize(Properties) + */ + @Override + public void initialize(Properties properties) throws XWikiVelocityException { + this.engine = new org.apache.velocity.app.VelocityEngine(); + + Properties velocityProperties = this.velocityConfiguration.getProperties(); + + // If the Velocity configuration uses the + // org.apache.velocity.tools.view.servlet.WebappLoader Velocity Tools class + // then we need to set the ServletContext object as a Velocity Application Attribute as + // it's used to load resources from the webapp directory in WebapLoader. + String resourceLoader = properties.getProperty(RESOURCE_LOADER, + velocityProperties.getProperty(RESOURCE_LOADER)); + if ((resourceLoader != null) && resourceLoader.equals("webapp")) { + ApplicationContext context = this.container.getApplicationContext(); + if (context instanceof ServletApplicationContext) { + getEngine().setApplicationAttribute("javax.servlet.ServletContext", + ((ServletApplicationContext) context).getServletContext()); + } + } - try { - getEngine().init(); - } catch (Exception e) { - throw new XWikiVelocityException("Cannot start the Velocity engine", e); + // Avoid "unable to find resource 'VM_global_library.vm' in any resource loader." if no + // Velocimacro library is defined. This value is overriden below. + getEngine().setProperty("velocimacro.library", ""); + + getEngine().setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, this); + + // Configure Velocity by passing the properties defined in this component's configuration + if (velocityProperties != null) { + for (Enumeration e = velocityProperties.propertyNames(); e.hasMoreElements();) { + String key = e.nextElement().toString(); + // Only set a property if it's not overridden by one of the passed properties + if (!properties.containsKey(key)) { + String value = velocityProperties.getProperty(key); + getEngine().setProperty(key, value); + LOGGER.debug("Setting property [{}] = [{}]", key, value); } + } } - /** - * {@inheritDoc} - * - * @see VelocityEngine#evaluate(Context, java.io.Writer, String, String) - */ - @Override - public boolean evaluate(Context context, Writer out, String templateName, String source) - throws XWikiVelocityException { - return evaluate(context, out, templateName, new StringReader(source)); + // Override the component's static properties with the ones passed in parameter + if (properties != null) { + for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) { + String key = e.nextElement().toString(); + String value = properties.getProperty(key); + getEngine().setProperty(key, value); + LOGGER.debug("Overriding property [{}] = [{}]", key, value); + } } - /** - * {@inheritDoc} - * - * @see VelocityEngine#evaluate(Context, java.io.Writer, String, String) - * @see #init(RuntimeServices) - */ - @Override - public boolean evaluate(Context context, Writer out, String templateName, Reader source) - throws XWikiVelocityException { - // Ensure that initialization has been called - if (this.engine == null) { - throw new XWikiVelocityException("This Velocity Engine has not yet been initialized. " - + " You must call its initialize() method before you can use it."); - } - - // We override the default implementation here. See #init(RuntimeServices) - // for explanations. - try { - SimpleNode nodeTree = null; - - // The trick is done here: We use the signature that allows - // passing a boolean and we pass false, thus preventing Velocity - // from cleaning the context of its velocimacros even though the - // config property velocimacro.permissions.allow.inline.local.scope - // is set to true. - nodeTree = this.rsvc.parse(source, templateName, false); - - if (nodeTree != null) { - InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context); - ica.pushCurrentTemplateName(templateName); - try { - nodeTree.init(ica, this.rsvc); - nodeTree.render(ica, out); - } finally { - ica.popCurrentTemplateName(); - } - return true; - } - - return false; - } catch (Exception e) { - throw new XWikiVelocityException("Failed to evaluate content with id [" + templateName + "]", e); - } + try { + getEngine().init(); + } catch (Exception e) { + throw new XWikiVelocityException("Cannot start the Velocity engine", e); } - - /** - * {@inheritDoc} - * - * @see VelocityEngine#clearMacroNamespace(String) - * - * @since 2.4M2 - */ - @Override - public void clearMacroNamespace(String templateName) { - this.rsvc.dumpVMNamespace(templateName); + } + + /** + * {@inheritDoc} + * + * @see VelocityEngine#evaluate(Context, java.io.Writer, String, String) + */ + @Override + public boolean evaluate(Context context, Writer out, String templateName, String source) + throws XWikiVelocityException { + return evaluate(context, out, templateName, new StringReader(source)); + } + + /** + * {@inheritDoc} + * + * @see VelocityEngine#evaluate(Context, java.io.Writer, String, String) + * @see #init(RuntimeServices) + */ + @Override + public boolean evaluate(Context context, Writer out, String templateName, Reader source) + throws XWikiVelocityException { + // Ensure that initialization has been called + if (this.engine == null) { + throw new XWikiVelocityException("This Velocity Engine has not yet been initialized. " + + " You must call its initialize() method before you can use it."); } - /** - * {@inheritDoc} - * - * @see VelocityEngine#startedUsingMacroNamespace(String) - * - * @since 2.4RC1 - */ - @Override - public void startedUsingMacroNamespace(String namespace) { - synchronized (this.namespaceUsageCount) { - Integer count = this.namespaceUsageCount.get(namespace); - if (count == null) { - count = 0; - } - count = count + 1; - this.namespaceUsageCount.put(namespace, count); + // We override the default implementation here. See #init(RuntimeServices) + // for explanations. + try { + SimpleNode nodeTree = null; + + // The trick is done here: We use the signature that allows + // passing a boolean and we pass false, thus preventing Velocity + // from cleaning the context of its velocimacros even though the + // config property velocimacro.permissions.allow.inline.local.scope + // is set to true. + nodeTree = this.rsvc.parse(source, templateName, false); + + if (nodeTree != null) { + InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context); + ica.pushCurrentTemplateName(templateName); + try { + nodeTree.init(ica, this.rsvc); + nodeTree.render(ica, out); + } finally { + ica.popCurrentTemplateName(); } - } + return true; + } - /** - * {@inheritDoc} - * - * @see VelocityEngine#stoppedUsingMacroNamespace(String) - * - * @since 2.4RC1 - */ - @Override - public void stoppedUsingMacroNamespace(String namespace) { - synchronized (this.namespaceUsageCount) { - Integer count = this.namespaceUsageCount.get(namespace); - if (count == null) { - // This shouldn't happen - this.log(LogChute.WARN_ID, "Wrong usage count for namespace [" + namespace + "]"); - return; - } - count = count - 1; - if (count <= 0) { - this.namespaceUsageCount.remove(namespace); - this.clearMacroNamespace(namespace); - } else { - this.namespaceUsageCount.put(namespace, count); - } - } + return false; + } catch (Exception e) { + throw new XWikiVelocityException("Failed to evaluate content with id [" + templateName + "]", + e); } - - /** - * Provides access to the {@link org.apache.velocity.app.VelocityEngine Velocity Engine}, which can be used to call - * all Velocity services. - * - * @return the initialized Velocity engine - */ - private org.apache.velocity.app.VelocityEngine getEngine() { - return this.engine; + } + + /** + * {@inheritDoc} + * + * @see VelocityEngine#clearMacroNamespace(String) + * @since 2.4M2 + */ + @Override + public void clearMacroNamespace(String templateName) { + this.rsvc.dumpVMNamespace(templateName); + } + + /** + * {@inheritDoc} + * + * @see VelocityEngine#startedUsingMacroNamespace(String) + * @since 2.4RC1 + */ + @Override + public void startedUsingMacroNamespace(String namespace) { + synchronized (this.namespaceUsageCount) { + Integer count = this.namespaceUsageCount.get(namespace); + if (count == null) { + count = 0; + } + count = count + 1; + this.namespaceUsageCount.put(namespace, count); } - - /** - * {@inheritDoc} - * - * @see LogChute#init(org.apache.velocity.runtime.RuntimeServices) - */ - @Override - public void init(RuntimeServices runtimeServices) { - // We save the RuntimeServices instance in order to be able to override the - // VelocityEngine.evaluate() method. We need to do this so that it's possible - // to make macros included with #includeMacros() work even though we're using - // the Velocity setting: - // velocimacro.permissions.allow.inline.local.scope = true - // TODO: Fix this when by rewriting the XWiki.include() implementation so that - // included Velocity templates are added to the current document before - // evaluation instead of doing 2 separate executions. - this.rsvc = runtimeServices; + } + + /** + * {@inheritDoc} + * + * @see VelocityEngine#stoppedUsingMacroNamespace(String) + * @since 2.4RC1 + */ + @Override + public void stoppedUsingMacroNamespace(String namespace) { + synchronized (this.namespaceUsageCount) { + Integer count = this.namespaceUsageCount.get(namespace); + if (count == null) { + // This shouldn't happen + this.log(LogChute.WARN_ID, "Wrong usage count for namespace [" + namespace + "]"); + return; + } + count = count - 1; + if (count <= 0) { + this.namespaceUsageCount.remove(namespace); + this.clearMacroNamespace(namespace); + } else { + this.namespaceUsageCount.put(namespace, count); + } } - - /** - * {@inheritDoc} - * - * @see LogChute#log(int, String) - */ - @Override - public void log(int level, String message) { - switch (level) { - case LogChute.WARN_ID: - LOGGER.warn(message); - break; - case LogChute.INFO_ID: - // Velocity info messages are too verbose, just consider them as debug messages... - LOGGER.debug(message); - break; - case LogChute.DEBUG_ID: - LOGGER.debug(message); - break; - case LogChute.ERROR_ID: - LOGGER.error(message); - break; - default: - LOGGER.debug(message); - break; - } + } + + /** + * Provides access to the {@link org.apache.velocity.app.VelocityEngine Velocity Engine}, which + * can be used to call + * all Velocity services. + * + * @return the initialized Velocity engine + */ + private org.apache.velocity.app.VelocityEngine getEngine() { + return this.engine; + } + + /** + * {@inheritDoc} + * + * @see LogChute#init(org.apache.velocity.runtime.RuntimeServices) + */ + @Override + public void init(RuntimeServices runtimeServices) { + // We save the RuntimeServices instance in order to be able to override the + // VelocityEngine.evaluate() method. We need to do this so that it's possible + // to make macros included with #includeMacros() work even though we're using + // the Velocity setting: + // velocimacro.permissions.allow.inline.local.scope = true + // TODO: Fix this when by rewriting the XWiki.include() implementation so that + // included Velocity templates are added to the current document before + // evaluation instead of doing 2 separate executions. + this.rsvc = runtimeServices; + } + + /** + * {@inheritDoc} + * + * @see LogChute#log(int, String) + */ + @Override + public void log(int level, String message) { + switch (level) { + case LogChute.WARN_ID: + LOGGER.warn(message); + break; + case LogChute.INFO_ID: + // Velocity info messages are too verbose, just consider them as debug messages... + LOGGER.debug(message); + break; + case LogChute.DEBUG_ID: + LOGGER.debug(message); + break; + case LogChute.ERROR_ID: + LOGGER.error(message); + break; + default: + LOGGER.debug(message); + break; } - - /** - * {@inheritDoc} - * - * @see LogChute#log(int, String, Throwable) - */ - @Override - public void log(int level, String message, Throwable throwable) { - switch (level) { - case LogChute.WARN_ID: - LOGGER.warn(message, throwable); - break; - case LogChute.INFO_ID: - // Velocity info messages are too verbose, just consider them as debug messages... - LOGGER.debug(message, throwable); - break; - case LogChute.DEBUG_ID: - LOGGER.debug(message, throwable); - break; - case LogChute.ERROR_ID: - LOGGER.error(message, throwable); - break; - default: - LOGGER.debug(message, throwable); - break; - } + } + + /** + * {@inheritDoc} + * + * @see LogChute#log(int, String, Throwable) + */ + @Override + public void log(int level, String message, Throwable throwable) { + switch (level) { + case LogChute.WARN_ID: + LOGGER.warn(message, throwable); + break; + case LogChute.INFO_ID: + // Velocity info messages are too verbose, just consider them as debug messages... + LOGGER.debug(message, throwable); + break; + case LogChute.DEBUG_ID: + LOGGER.debug(message, throwable); + break; + case LogChute.ERROR_ID: + LOGGER.error(message, throwable); + break; + default: + LOGGER.debug(message, throwable); + break; } - - /** - * {@inheritDoc} - * - * @see LogChute#isLevelEnabled(int) - */ - @Override - public boolean isLevelEnabled(int level) { - boolean isEnabled; - - switch (level) { - case LogChute.WARN_ID: - isEnabled = LOGGER.isWarnEnabled(); - break; - case LogChute.INFO_ID: - // Velocity info messages are too verbose, just consider them as debug messages... - isEnabled = LOGGER.isDebugEnabled(); - break; - case LogChute.DEBUG_ID: - isEnabled = LOGGER.isDebugEnabled(); - break; - case LogChute.ERROR_ID: - isEnabled = LOGGER.isErrorEnabled(); - break; - default: - isEnabled = LOGGER.isDebugEnabled(); - break; - } - - return isEnabled; + } + + /** + * {@inheritDoc} + * + * @see LogChute#isLevelEnabled(int) + */ + @Override + public boolean isLevelEnabled(int level) { + boolean isEnabled; + + switch (level) { + case LogChute.WARN_ID: + isEnabled = LOGGER.isWarnEnabled(); + break; + case LogChute.INFO_ID: + // Velocity info messages are too verbose, just consider them as debug messages... + isEnabled = LOGGER.isDebugEnabled(); + break; + case LogChute.DEBUG_ID: + isEnabled = LOGGER.isDebugEnabled(); + break; + case LogChute.ERROR_ID: + isEnabled = LOGGER.isErrorEnabled(); + break; + default: + isEnabled = LOGGER.isDebugEnabled(); + break; } + + return isEnabled; + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityFactory.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityFactory.java index 6ed113749..5fc153515 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityFactory.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/DefaultVelocityFactory.java @@ -40,68 +40,71 @@ * Default implementation for {@link VelocityFactory}. * * @see VelocityFactory - * * @version $Id$ */ @Component public class DefaultVelocityFactory extends AbstractLogEnabled implements VelocityFactory { - /** - * The Component manager we use to lookup (and thus create since it's a singleton) the VelocityEngine component. - */ - @Requirement - private ComponentManager componentManager; - - /** - * In order to register the Velocity MBean for management. - */ - @Requirement - private JMXBeanRegistration jmxRegistration; - /** - * A cache of Velocity Engines. See {@link org.xwiki.velocity.VelocityFactory} for more details as to why we need - * this cache. - */ - private Map velocityEngines = new HashMap(); + /** + * The Component manager we use to lookup (and thus create since it's a singleton) the + * VelocityEngine component. + */ + @Requirement + private ComponentManager componentManager; - /** - * {@inheritDoc} - * - * @see VelocityFactory#hasVelocityEngine(String) - */ - public synchronized boolean hasVelocityEngine(String key) { - return this.velocityEngines.containsKey(key); - } + /** + * In order to register the Velocity MBean for management. + */ + @Requirement + private JMXBeanRegistration jmxRegistration; - /** - * {@inheritDoc} - * - * @see VelocityFactory#getVelocityEngine(String) - */ - public synchronized VelocityEngine getVelocityEngine(String key) { - return this.velocityEngines.get(key); - } + /** + * A cache of Velocity Engines. See {@link org.xwiki.velocity.VelocityFactory} for more details as + * to why we need + * this cache. + */ + private Map velocityEngines = new HashMap(); - /** - * {@inheritDoc} - * - * @see VelocityFactory#createVelocityEngine(String, Properties) - */ - public synchronized VelocityEngine createVelocityEngine(String key, Properties properties) - throws XWikiVelocityException { - VelocityEngine engine; - try { - engine = this.componentManager.lookup(VelocityEngine.class); - } catch (ComponentLookupException e) { - throw new XWikiVelocityException("Failed to create Velocity Engine", e); - } - engine.initialize(properties); - this.velocityEngines.put(key, engine); + /** + * {@inheritDoc} + * + * @see VelocityFactory#hasVelocityEngine(String) + */ + public synchronized boolean hasVelocityEngine(String key) { + return this.velocityEngines.containsKey(key); + } - // Register a JMX MBean for providing information about the created Velocity Engine (template namespaces, - // macros, etc). - JMXVelocityEngineMBean mbean = new JMXVelocityEngine(engine); - this.jmxRegistration.registerMBean(mbean, "type=Velocity,domain=Engines,name=" + key); + /** + * {@inheritDoc} + * + * @see VelocityFactory#getVelocityEngine(String) + */ + public synchronized VelocityEngine getVelocityEngine(String key) { + return this.velocityEngines.get(key); + } - return engine; + /** + * {@inheritDoc} + * + * @see VelocityFactory#createVelocityEngine(String, Properties) + */ + public synchronized VelocityEngine createVelocityEngine(String key, Properties properties) + throws XWikiVelocityException { + VelocityEngine engine; + try { + engine = this.componentManager.lookup(VelocityEngine.class); + } catch (ComponentLookupException e) { + throw new XWikiVelocityException("Failed to create Velocity Engine", e); } + engine.initialize(properties); + this.velocityEngines.put(key, engine); + + // Register a JMX MBean for providing information about the created Velocity Engine (template + // namespaces, + // macros, etc). + JMXVelocityEngineMBean mbean = new JMXVelocityEngine(engine); + this.jmxRegistration.registerMBean(mbean, "type=Velocity,domain=Engines,name=" + key); + + return engine; + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/ServicesVelocityContextInitializer.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/ServicesVelocityContextInitializer.java index dd1841af3..44beee90a 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/ServicesVelocityContextInitializer.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/ServicesVelocityContextInitializer.java @@ -26,27 +26,29 @@ import org.xwiki.velocity.VelocityContextInitializer; /** - * Registers the Script Service Manager in the Velocity Context so that it's available from Velocity. + * Registers the Script Service Manager in the Velocity Context so that it's available from + * Velocity. * * @version $Id$ - * * @since 2.3M1 */ -// TODO: In the future Velocity will be implemented using the JSR 223 API and this class won't be required anymore. +// TODO: In the future Velocity will be implemented using the JSR 223 API and this class won't be +// required anymore. @Component("scriptservices") public class ServicesVelocityContextInitializer implements VelocityContextInitializer { - /** - * The Script Service Manager to bind in the Script Context. - */ - @Requirement - private ScriptServiceManager scriptServiceManager; - /** - * {@inheritDoc} - * - * @see org.xwiki.velocity.VelocityContextInitializer#initialize(org.apache.velocity.VelocityContext) - */ - public void initialize(VelocityContext context) { - context.put("services", this.scriptServiceManager); - } + /** + * The Script Service Manager to bind in the Script Context. + */ + @Requirement + private ScriptServiceManager scriptServiceManager; + + /** + * {@inheritDoc} + * + * @see org.xwiki.velocity.VelocityContextInitializer#initialize(org.apache.velocity.VelocityContext) + */ + public void initialize(VelocityContext context) { + context.put("services", this.scriptServiceManager); + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/VelocityExecutionContextInitializer.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/VelocityExecutionContextInitializer.java index c6695d47d..0eb674b50 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/VelocityExecutionContextInitializer.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/VelocityExecutionContextInitializer.java @@ -30,40 +30,42 @@ import org.xwiki.velocity.XWikiVelocityException; /** - * Allow registering the Velocity Context in the Execution Context object since it's shared during the whole execution + * Allow registering the Velocity Context in the Execution Context object since it's shared during + * the whole execution * of the current request. * * @see org.xwiki.context.ExecutionContextInitializer - * * @since 1.5M1 - * * @version $Id$ */ @Component("velocity") public class VelocityExecutionContextInitializer implements ExecutionContextInitializer { - /** - * The id under which the Velocity Context is stored in the Execution Context. - */ - public static final String VELOCITY_CONTEXT_ID = "velocityContext"; - /** - * The Velocity context factory component used for creating the Velocity Context (injected automatically by the - * Component subsystem). - */ - @Requirement - private VelocityContextFactory velocityContextFactory; + /** + * The id under which the Velocity Context is stored in the Execution Context. + */ + public static final String VELOCITY_CONTEXT_ID = "velocityContext"; + + /** + * The Velocity context factory component used for creating the Velocity Context (injected + * automatically by the + * Component subsystem). + */ + @Requirement + private VelocityContextFactory velocityContextFactory; - /** - * {@inheritDoc} - * - * @see org.xwiki.context.ExecutionContextInitializer#initialize(org.xwiki.context.ExecutionContext) - */ - public void initialize(ExecutionContext executionContext) throws ExecutionContextException { - try { - VelocityContext context = this.velocityContextFactory.createContext(); - executionContext.setProperty(VelocityExecutionContextInitializer.VELOCITY_CONTEXT_ID, context); - } catch (XWikiVelocityException e) { - throw new ExecutionContextException("Failed to initialize Velocity Context", e); - } + /** + * {@inheritDoc} + * + * @see org.xwiki.context.ExecutionContextInitializer#initialize(org.xwiki.context.ExecutionContext) + */ + public void initialize(ExecutionContext executionContext) throws ExecutionContextException { + try { + VelocityContext context = this.velocityContextFactory.createContext(); + executionContext.setProperty(VelocityExecutionContextInitializer.VELOCITY_CONTEXT_ID, + context); + } catch (XWikiVelocityException e) { + throw new ExecutionContextException("Failed to initialize Velocity Context", e); } + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngine.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngine.java index d3d4fd398..3c8c24d0d 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngine.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngine.java @@ -35,134 +35,139 @@ import java.util.Map; /** - * Uses non-stable (ie might need to be modified when we upgrade the Velocity JAR) introspection to access private - * fields of Velocity. This is needed since Velocity doesn't offer a way to access information about the template + * Uses non-stable (ie might need to be modified when we upgrade the Velocity JAR) introspection to + * access private + * fields of Velocity. This is needed since Velocity doesn't offer a way to access information about + * the template * namespaces and the macros within them. * * @version $Id$ - * * @since 2.4M2 */ public class JMXVelocityEngine implements JMXVelocityEngineMBean { - /** - * The Velocity Engine for which to return management data. - */ - private VelocityEngine engine; - - /** - * @param engine - * the Velocity Engine for which to return management data - */ - public JMXVelocityEngine(VelocityEngine engine) { - this.engine = engine; - } - - /** - * {@inheritDoc} - * - * @see JMXVelocityEngineMBean#getTemplates() - */ - public TabularData getTemplates() { - TabularData data; - - try { - Map result = getInternalTemplates(); - - // Note: JDK 1.6 has the notion of MXBean which support returning a Map type but since we must use - // JDK 1.5 for now we have to output a TabularData value. - - // Represents the list of macro names - ArrayType macroNameType = new ArrayType(1, SimpleType.STRING); - - // Represents one row (template name, macro names) in the returned table data - String[] columnNames = new String[] { "templateName", "macroNames" }; - String[] descriptions = new String[] { "The Template Name (namespace)", "The names of registered Macros" }; - CompositeType rowType = new CompositeType("template", - "Template management data (namespaces, macros) for a row", columnNames, descriptions, - new OpenType[] { SimpleType.STRING, macroNameType }); - TabularType type = new TabularType("templates", "Template management data (namespaces, macros)", rowType, - columnNames); - data = new TabularDataSupport(type); - - for (Map.Entry entry : result.entrySet()) { - - String templateName = entry.getKey(); - String[] macroNames = entry.getValue(); - - CompositeData rowData = new CompositeDataSupport(rowType, columnNames, - new Object[] { templateName, macroNames }); - data.put(rowData); - } - - } catch (Exception e) { - throw new RuntimeException("Failed to gather information on Velocity Templates/Macros", e); - } - - return data; + /** + * The Velocity Engine for which to return management data. + */ + private VelocityEngine engine; + + /** + * @param engine + * the Velocity Engine for which to return management data + */ + public JMXVelocityEngine(VelocityEngine engine) { + this.engine = engine; + } + + /** + * {@inheritDoc} + * + * @see JMXVelocityEngineMBean#getTemplates() + */ + public TabularData getTemplates() { + TabularData data; + + try { + Map result = getInternalTemplates(); + + // Note: JDK 1.6 has the notion of MXBean which support returning a Map type but since we must + // use + // JDK 1.5 for now we have to output a TabularData value. + + // Represents the list of macro names + ArrayType macroNameType = new ArrayType(1, SimpleType.STRING); + + // Represents one row (template name, macro names) in the returned table data + String[] columnNames = new String[] { "templateName", "macroNames" }; + String[] descriptions = new String[] { "The Template Name (namespace)", + "The names of registered Macros" }; + CompositeType rowType = new CompositeType("template", + "Template management data (namespaces, macros) for a row", columnNames, descriptions, + new OpenType[] { SimpleType.STRING, macroNameType }); + + TabularType type = new TabularType("templates", + "Template management data (namespaces, macros)", rowType, + columnNames); + data = new TabularDataSupport(type); + + for (Map.Entry entry : result.entrySet()) { + + String templateName = entry.getKey(); + String[] macroNames = entry.getValue(); + + CompositeData rowData = new CompositeDataSupport(rowType, columnNames, + new Object[] { templateName, macroNames }); + data.put(rowData); + } + + } catch (Exception e) { + throw new RuntimeException("Failed to gather information on Velocity Templates/Macros", e); } - /** - * @return the data using standard Java classes, {@link #getTemplates()} wraps it in generic Open types to make the - * returned data portable and accessible remotely from a JMX management console - * - * @throws NoSuchFieldException - * in case of an exception in getting the data - * @throws IllegalAccessException - * in case of an exception in getting the data - * - * @see #getTemplates() - */ - private Map getInternalTemplates() throws NoSuchFieldException, IllegalAccessException { - // Get the internal Velocity Engine (not the XWiki wrapping one) - Object velocityEngine = getField(this.engine, "engine"); - - Object runtimeInstance = getField(velocityEngine, "ri"); - Object vmFactory = getField(runtimeInstance, "vmFactory"); - Object vmManager = getField(vmFactory, "vmManager"); - - Map> namespaceHash = (Map>) getField(vmManager, "namespaceHash"); - - Map globalNamespace = (Map) getField(vmManager, "globalNamespace"); - - Map result = new HashMap(); - - for (String name : namespaceHash.keySet()) { - String nameSpaceName = name; - if (globalNamespace.equals(namespaceHash.get(name))) { - nameSpaceName = ""; - } - String[] macroNames = new String[namespaceHash.get(name).size()]; - int i = 0; - for (String macroName : namespaceHash.get(name).keySet()) { - macroNames[i] = macroName; - i++; - } - - result.put(nameSpaceName, macroNames); - } - - return result; + return data; + } + + /** + * @return the data using standard Java classes, {@link #getTemplates()} wraps it in generic Open + * types to make the + * returned data portable and accessible remotely from a JMX management console + * @throws NoSuchFieldException + * in case of an exception in getting the data + * @throws IllegalAccessException + * in case of an exception in getting the data + * @see #getTemplates() + */ + private Map getInternalTemplates() + throws NoSuchFieldException, IllegalAccessException { + // Get the internal Velocity Engine (not the XWiki wrapping one) + Object velocityEngine = getField(this.engine, "engine"); + + Object runtimeInstance = getField(velocityEngine, "ri"); + Object vmFactory = getField(runtimeInstance, "vmFactory"); + Object vmManager = getField(vmFactory, "vmManager"); + + Map> namespaceHash = (Map>) getField(vmManager, + "namespaceHash"); + + Map globalNamespace = (Map) getField(vmManager, "globalNamespace"); + + Map result = new HashMap(); + + for (String name : namespaceHash.keySet()) { + String nameSpaceName = name; + if (globalNamespace.equals(namespaceHash.get(name))) { + nameSpaceName = ""; + } + String[] macroNames = new String[namespaceHash.get(name).size()]; + int i = 0; + for (String macroName : namespaceHash.get(name).keySet()) { + macroNames[i] = macroName; + i++; + } + + result.put(nameSpaceName, macroNames); } - /** - * Helper method to access a private field. - * - * @param instance - * the instance containing the field to access - * @param fieldName - * the name of the field to access - * - * @return the field object - * - * @throws NoSuchFieldException - * in case of an error when accessing the private field - * @throws IllegalAccessException - * in case of an error when accessing the private field - */ - private Object getField(Object instance, String fieldName) throws NoSuchFieldException, IllegalAccessException { - Field field = instance.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - return field.get(instance); - } + return result; + } + + /** + * Helper method to access a private field. + * + * @param instance + * the instance containing the field to access + * @param fieldName + * the name of the field to access + * @return the field object + * @throws NoSuchFieldException + * in case of an error when accessing the private field + * @throws IllegalAccessException + * in case of an error when accessing the private field + */ + private Object getField(Object instance, String fieldName) + throws NoSuchFieldException, IllegalAccessException { + Field field = instance.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(instance); + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngineMBean.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngineMBean.java index ceddd230c..968c73c0e 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngineMBean.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngineMBean.java @@ -24,16 +24,18 @@ /** * MBean API related to Velocity Engines. Supports the following features: *

    - *
  • Retrieve list of template namespaces along with the name of macros registered in each template namespace
  • + *
  • Retrieve list of template namespaces along with the name of macros registered in each + * template namespace
  • *
* * @version $Id$ - * * @since 2.4M2 */ public interface JMXVelocityEngineMBean { - /** - * @return the list of template namespaces along with the name of macros registered in each template namespace - */ - TabularData getTemplates(); + + /** + * @return the list of template namespaces along with the name of macros registered in each + * template namespace + */ + TabularData getTemplates(); } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityBlock.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityBlock.java index d6ca26dc4..29b211c9d 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityBlock.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityBlock.java @@ -25,81 +25,82 @@ * @version $Id$ */ public class VelocityBlock { - /** - * The type of found Velocity element. - * - * @version $Id$ - */ - public enum VelocityType { - /** - * A simple or multilines comment. - */ - COMMENT, - - /** - * A Velocity directive (except macros). - */ - DIRECTIVE, - - /** - * A Velocity macro. - */ - MACRO, - - /** - * Anything starting with a $. - */ - VAR - } + /** + * The type of found Velocity element. + * + * @version $Id$ + */ + public enum VelocityType { /** - * The name of the Velocity element (if, macro, ...). + * A simple or multilines comment. */ - private String name; + COMMENT, /** - * The of the Velocity element. + * A Velocity directive (except macros). */ - private VelocityType type; + DIRECTIVE, /** - * @param name - * the name of the Velocity element (if, macro, ...). - * @param type - * the type of the Velocity element. + * A Velocity macro. */ - public VelocityBlock(String name, VelocityType type) { - this.name = name; - this.type = type; - } + MACRO, /** - * @return the name of the Velocity element (if, macro, ...). + * Anything starting with a $. */ - public String getName() { - return name; - } + VAR + } - /** - * @param name - * the name of the Velocity element (if, macro, ...). - */ - public void setName(String name) { - this.name = name; - } + /** + * The name of the Velocity element (if, macro, ...). + */ + private String name; - /** - * @return the type of the Velocity element. - */ - public VelocityType getType() { - return type; - } + /** + * The of the Velocity element. + */ + private VelocityType type; - /** - * @param type - * the type of the Velocity element. - */ - public void setType(VelocityType type) { - this.type = type; - } + /** + * @param name + * the name of the Velocity element (if, macro, ...). + * @param type + * the type of the Velocity element. + */ + public VelocityBlock(String name, VelocityType type) { + this.name = name; + this.type = type; + } + + /** + * @return the name of the Velocity element (if, macro, ...). + */ + public String getName() { + return name; + } + + /** + * @param name + * the name of the Velocity element (if, macro, ...). + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the type of the Velocity element. + */ + public VelocityType getType() { + return type; + } + + /** + * @param type + * the type of the Velocity element. + */ + public void setType(VelocityType type) { + this.type = type; + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityParser.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityParser.java index 69f8a5e55..eb348fb4b 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityParser.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityParser.java @@ -31,805 +31,790 @@ * @version $Id$ */ public class VelocityParser extends AbstractLogEnabled { - /** - * The directives which start a new level which will have to be close by a #end. - */ - public static final Set VELOCITYDIRECTIVE_BEGIN = new HashSet(); - - /** - * Close an opened level. - */ - public static final Set VELOCITYDIRECTIVE_END = new HashSet(); - - /** - * Reserved directive containing parameter(s) like #if. - */ - public static final Set VELOCITYDIRECTIVE_PARAM = new HashSet(); - - /** - * Reserved directives without parameters like #else. - */ - public static final Set VELOCITYDIRECTIVE_NOPARAM = new HashSet(); - - /** - * All the velocity reserved directives. - */ - public static final Set VELOCITYDIRECTIVE_ALL = new HashSet(); - - static { - VELOCITYDIRECTIVE_BEGIN.add("if"); - VELOCITYDIRECTIVE_BEGIN.add("foreach"); - VELOCITYDIRECTIVE_BEGIN.add("literal"); - VELOCITYDIRECTIVE_BEGIN.add("macro"); - VELOCITYDIRECTIVE_BEGIN.add("define"); - - VELOCITYDIRECTIVE_END.add("end"); - - VELOCITYDIRECTIVE_PARAM.addAll(VELOCITYDIRECTIVE_BEGIN); - VELOCITYDIRECTIVE_PARAM.add("set"); - VELOCITYDIRECTIVE_PARAM.add("elseif"); - VELOCITYDIRECTIVE_PARAM.add("evaluate"); - VELOCITYDIRECTIVE_PARAM.add("include"); - - VELOCITYDIRECTIVE_NOPARAM.addAll(VELOCITYDIRECTIVE_END); - VELOCITYDIRECTIVE_NOPARAM.add("else"); - VELOCITYDIRECTIVE_NOPARAM.add("break"); - VELOCITYDIRECTIVE_NOPARAM.add("stop"); - - VELOCITYDIRECTIVE_ALL.addAll(VELOCITYDIRECTIVE_PARAM); - VELOCITYDIRECTIVE_ALL.addAll(VELOCITYDIRECTIVE_NOPARAM); - } - - /** - * @param logger - * the logger to use - */ - public VelocityParser(Logger logger) { - enableLogging(logger); - } - - /** - * Get any valid Velocity block starting with a sharp character (#if, #somemaccro(), ##comment etc.). - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - * - * @throws InvalidVelocityException - * not a valid velocity block - */ - public int getKeyWord(char[] array, int currentIndex, StringBuffer velocityBlock, VelocityParserContext context) - throws InvalidVelocityException { - int i = currentIndex; - - if (i + 1 >= array.length) { - throw new InvalidVelocityException(); - } - - if (array[i + 1] == '#') { - // A simple line comment - i = getSimpleComment(array, currentIndex, velocityBlock, context); - } else if (array[i + 1] == '*') { - // A multi lines comment - i = getMultilinesComment(array, currentIndex, velocityBlock, context); - } else if (array[i + 1] == '{' || Character.isLetter(array[i + 1])) { - // A directive - i = getDirective(array, currentIndex, velocityBlock, context); - } else { - throw new InvalidVelocityException(); - } - return i; - } - - /** - * Get any valid Velocity block starting with a sharp character except comments. - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - * - * @throws InvalidVelocityException - * not a valid velocity block - */ - public int getDirective(char[] array, int currentIndex, StringBuffer velocityBlock, VelocityParserContext context) - throws InvalidVelocityException { - int i = currentIndex + 1; - - // Get macro name - StringBuffer directiveNameBuffer = new StringBuffer(); - i = getDirectiveName(array, i, directiveNameBuffer, null, context); - - String directiveName = directiveNameBuffer.toString(); - - if (!VELOCITYDIRECTIVE_NOPARAM.contains(directiveName)) { - // Skip spaces - while (i < array.length && array[i] == ' ') { - ++i; - } - - if (i < array.length && array[i] == '(') { - // Skip condition - i = getMethodParameters(array, i, null, context); - } else { - throw new InvalidVelocityException(); - } - } + /** + * The directives which start a new level which will have to be close by a #end. + */ + public static final Set VELOCITYDIRECTIVE_BEGIN = new HashSet(); + + /** + * Close an opened level. + */ + public static final Set VELOCITYDIRECTIVE_END = new HashSet(); + + /** + * Reserved directive containing parameter(s) like #if. + */ + public static final Set VELOCITYDIRECTIVE_PARAM = new HashSet(); + + /** + * Reserved directives without parameters like #else. + */ + public static final Set VELOCITYDIRECTIVE_NOPARAM = new HashSet(); + + /** + * All the velocity reserved directives. + */ + public static final Set VELOCITYDIRECTIVE_ALL = new HashSet(); + + static { + VELOCITYDIRECTIVE_BEGIN.add("if"); + VELOCITYDIRECTIVE_BEGIN.add("foreach"); + VELOCITYDIRECTIVE_BEGIN.add("literal"); + VELOCITYDIRECTIVE_BEGIN.add("macro"); + VELOCITYDIRECTIVE_BEGIN.add("define"); + + VELOCITYDIRECTIVE_END.add("end"); + + VELOCITYDIRECTIVE_PARAM.addAll(VELOCITYDIRECTIVE_BEGIN); + VELOCITYDIRECTIVE_PARAM.add("set"); + VELOCITYDIRECTIVE_PARAM.add("elseif"); + VELOCITYDIRECTIVE_PARAM.add("evaluate"); + VELOCITYDIRECTIVE_PARAM.add("include"); + + VELOCITYDIRECTIVE_NOPARAM.addAll(VELOCITYDIRECTIVE_END); + VELOCITYDIRECTIVE_NOPARAM.add("else"); + VELOCITYDIRECTIVE_NOPARAM.add("break"); + VELOCITYDIRECTIVE_NOPARAM.add("stop"); + + VELOCITYDIRECTIVE_ALL.addAll(VELOCITYDIRECTIVE_PARAM); + VELOCITYDIRECTIVE_ALL.addAll(VELOCITYDIRECTIVE_NOPARAM); + } + + /** + * @param logger + * the logger to use + */ + public VelocityParser(Logger logger) { + enableLogging(logger); + } + + /** + * Get any valid Velocity block starting with a sharp character (#if, #somemaccro(), ##comment + * etc.). + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + * @throws InvalidVelocityException + * not a valid velocity block + */ + public int getKeyWord(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) + throws InvalidVelocityException { + int i = currentIndex; + + if (i + 1 >= array.length) { + throw new InvalidVelocityException(); + } - if (VELOCITYDIRECTIVE_ALL.contains(directiveName)) { - if (VELOCITYDIRECTIVE_BEGIN.contains(directiveName)) { - context.pushVelocityElement(new VelocityBlock(directiveName, VelocityBlock.VelocityType.DIRECTIVE)); - } else if (VELOCITYDIRECTIVE_END.contains(directiveName)) { - context.popVelocityElement(); - } + if (array[i + 1] == '#') { + // A simple line comment + i = getSimpleComment(array, currentIndex, velocityBlock, context); + } else if (array[i + 1] == '*') { + // A multi lines comment + i = getMultilinesComment(array, currentIndex, velocityBlock, context); + } else if (array[i + 1] == '{' || Character.isLetter(array[i + 1])) { + // A directive + i = getDirective(array, currentIndex, velocityBlock, context); + } else { + throw new InvalidVelocityException(); + } - // consume the end of the line - i = getDirectiveEndOfLine(array, i, null, context); + return i; + } + + /** + * Get any valid Velocity block starting with a sharp character except comments. + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + * @throws InvalidVelocityException + * not a valid velocity block + */ + public int getDirective(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) + throws InvalidVelocityException { + int i = currentIndex + 1; + + // Get macro name + StringBuffer directiveNameBuffer = new StringBuffer(); + i = getDirectiveName(array, i, directiveNameBuffer, null, context); + + String directiveName = directiveNameBuffer.toString(); + + if (!VELOCITYDIRECTIVE_NOPARAM.contains(directiveName)) { + // Skip spaces + while (i < array.length && array[i] == ' ') { + ++i; + } + + if (i < array.length && array[i] == '(') { + // Skip condition + i = getMethodParameters(array, i, null, context); + } else { + throw new InvalidVelocityException(); + } + } - context.setType(VelocityBlock.VelocityType.DIRECTIVE); - } else { - context.setType(VelocityBlock.VelocityType.MACRO); - } + if (VELOCITYDIRECTIVE_ALL.contains(directiveName)) { + if (VELOCITYDIRECTIVE_BEGIN.contains(directiveName)) { + context.pushVelocityElement( + new VelocityBlock(directiveName, VelocityBlock.VelocityType.DIRECTIVE)); + } else if (VELOCITYDIRECTIVE_END.contains(directiveName)) { + context.popVelocityElement(); + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + // consume the end of the line + i = getDirectiveEndOfLine(array, i, null, context); - return i; - } - - /** - * Get a valid Velocity identifier used for variable of macro. - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - * - * @throws InvalidVelocityException - * not a valid velocity block - */ - public int getVelocityIdentifier(char[] array, int currentIndex, StringBuffer velocityBlock, - VelocityParserContext context) throws InvalidVelocityException { - // The first character of an identifier must be a [a-zA-Z] - if (!Character.isLetter(array[currentIndex])) { - throw new InvalidVelocityException(); - } + context.setType(VelocityBlock.VelocityType.DIRECTIVE); + } else { + context.setType(VelocityBlock.VelocityType.MACRO); + } - int i = currentIndex + 1; + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - while (i < array.length && array[i] != '}' && isValidVelocityIdentifierChar(array[i])) { - ++i; - } + return i; + } + + /** + * Get a valid Velocity identifier used for variable of macro. + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + * @throws InvalidVelocityException + * not a valid velocity block + */ + public int getVelocityIdentifier(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) throws InvalidVelocityException { + // The first character of an identifier must be a [a-zA-Z] + if (!Character.isLetter(array[currentIndex])) { + throw new InvalidVelocityException(); + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + int i = currentIndex + 1; - return i; - } - - /** - * Indicate if the provided character is valid in a velocity identifier. - * - * @param c - * the character - * - * @return true if the character is valid - */ - public boolean isValidVelocityIdentifierChar(char c) { - return Character.isLetterOrDigit(c) || c == '_' || c == '-'; - } - - /** - * Get a Velocity directive name block. It's different from - * {@link #getVelocityIdentifier(char[], int, StringBuffer, VelocityParserContext)} because is include the optional - * { and }. - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param directiveName - * the buffer where to append the name of the directive - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - * - * @throws InvalidVelocityException - * not a valid velocity block - */ - public int getDirectiveName(char[] array, int currentIndex, StringBuffer directiveName, StringBuffer velocityBlock, - VelocityParserContext context) throws InvalidVelocityException { - int i = currentIndex; - - if (i == array.length) { - throw new InvalidVelocityException(); - } + while (i < array.length && array[i] != '}' && isValidVelocityIdentifierChar(array[i])) { + ++i; + } - if (array[i] == '{') { - ++i; - } + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - i = getVelocityIdentifier(array, i, directiveName, context); + return i; + } + + /** + * Indicate if the provided character is valid in a velocity identifier. + * + * @param c + * the character + * @return true if the character is valid + */ + public boolean isValidVelocityIdentifierChar(char c) { + return Character.isLetterOrDigit(c) || c == '_' || c == '-'; + } + + /** + * Get a Velocity directive name block. It's different from + * {@link #getVelocityIdentifier(char[], int, StringBuffer, VelocityParserContext)} because is + * include the optional + * { and }. + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param directiveName + * the buffer where to append the name of the directive + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + * @throws InvalidVelocityException + * not a valid velocity block + */ + public int getDirectiveName(char[] array, int currentIndex, StringBuffer directiveName, + StringBuffer velocityBlock, + VelocityParserContext context) throws InvalidVelocityException { + int i = currentIndex; + + if (i == array.length) { + throw new InvalidVelocityException(); + } - if (i < array.length && array[i] == '}') { - ++i; - } + if (array[i] == '{') { + ++i; + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + i = getVelocityIdentifier(array, i, directiveName, context); - return i; - } - - /** - * Get the newline consumed by Velocity directive other than macros. - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getDirectiveEndOfLine(char[] array, int currentIndex, StringBuffer velocityBlock, - VelocityParserContext context) { - int i = currentIndex; - - for (; i < array.length; ++i) { - if (array[i] == '\n') { - ++i; - break; - } else if (!Character.isWhitespace(array[i])) { - return currentIndex; - } - } + if (i < array.length && array[i] == '}') { + ++i; + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - return i; - } - - /** - * Get comment single line comment (starting with ##). - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getSimpleComment(char[] array, int currentIndex, StringBuffer velocityBlock, - VelocityParserContext context) { - int i = currentIndex + 2; - - while (i < array.length && array[i - 1] != '\n') { - ++i; - } + return i; + } + + /** + * Get the newline consumed by Velocity directive other than macros. + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getDirectiveEndOfLine(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) { + int i = currentIndex; + + for (; i < array.length; ++i) { + if (array[i] == '\n') { + ++i; + break; + } else if (!Character.isWhitespace(array[i])) { + return currentIndex; + } + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - context.setType(VelocityBlock.VelocityType.COMMENT); - - return i; - } - - /** - * Get multilines comment (between #* and *#). - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getMultilinesComment(char[] array, int currentIndex, StringBuffer velocityBlock, - VelocityParserContext context) { - int i = currentIndex + 2; - - while (i < array.length && (array[i - 1] != '#' || array[i - 2] != '*')) { - ++i; - } + return i; + } + + /** + * Get comment single line comment (starting with ##). + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getSimpleComment(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) { + int i = currentIndex + 2; + + while (i < array.length && array[i - 1] != '\n') { + ++i; + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - context.setType(VelocityBlock.VelocityType.COMMENT); - - return i; - } - - /** - * Get any valid Velocity starting with a $. - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - * - * @throws InvalidVelocityException - * not a valid velocity block - */ - public int getVar(char[] array, int currentIndex, StringBuffer velocityBlock, VelocityParserContext context) - throws InvalidVelocityException { - return getVar(array, currentIndex, null, velocityBlock, context); - } - - /** - * Get any valid Velocity starting with a $. - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param varName - * the buffer where to append the name of the variable - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - * - * @throws InvalidVelocityException - * not a valid velocity block - */ - public int getVar(char[] array, int currentIndex, StringBuffer varName, StringBuffer velocityBlock, - VelocityParserContext context) throws InvalidVelocityException { - if (isVarEscaped(array, currentIndex)) { - throw new InvalidVelocityException(); - } + context.setType(VelocityBlock.VelocityType.COMMENT); + + return i; + } + + /** + * Get multilines comment (between #* and *#). + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getMultilinesComment(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) { + int i = currentIndex + 2; + + while (i < array.length && (array[i - 1] != '#' || array[i - 2] != '*')) { + ++i; + } - int i = currentIndex + 1; + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - if (i == array.length) { - throw new InvalidVelocityException(); - } + context.setType(VelocityBlock.VelocityType.COMMENT); + + return i; + } + + /** + * Get any valid Velocity starting with a $. + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + * @throws InvalidVelocityException + * not a valid velocity block + */ + public int getVar(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) + throws InvalidVelocityException { + return getVar(array, currentIndex, null, velocityBlock, context); + } + + /** + * Get any valid Velocity starting with a $. + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param varName + * the buffer where to append the name of the variable + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + * @throws InvalidVelocityException + * not a valid velocity block + */ + public int getVar(char[] array, int currentIndex, StringBuffer varName, + StringBuffer velocityBlock, + VelocityParserContext context) throws InvalidVelocityException { + if (isVarEscaped(array, currentIndex)) { + throw new InvalidVelocityException(); + } - if (array[i] == '!') { - ++i; - } + int i = currentIndex + 1; - if (i == array.length) { - throw new InvalidVelocityException(); - } + if (i == array.length) { + throw new InvalidVelocityException(); + } - boolean fullSyntax = false; - if (array[i] == '{') { - ++i; - fullSyntax = true; - } + if (array[i] == '!') { + ++i; + } - if (i == array.length) { - throw new InvalidVelocityException(); - } + if (i == array.length) { + throw new InvalidVelocityException(); + } - // get the variable name - i = getVelocityIdentifier(array, i, varName, context); + boolean fullSyntax = false; + if (array[i] == '{') { + ++i; + fullSyntax = true; + } - // get the method(s) - i = followVar(array, i, fullSyntax, context); + if (i == array.length) { + throw new InvalidVelocityException(); + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + // get the variable name + i = getVelocityIdentifier(array, i, varName, context); - context.setType(VelocityBlock.VelocityType.VAR); + // get the method(s) + i = followVar(array, i, fullSyntax, context); - return i; + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); } - /** - * Look in previous characters of the array to find if the current var is escaped (like \$var). - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * - * @return the parser context to put some informations - */ - private boolean isVarEscaped(char[] array, int currentIndex) { - int i = currentIndex - 1; - - while (i >= 0 && array[i] == '\\') { - --i; - } - - return (currentIndex - i) % 2 == 0; - } - - /** - * Get the right part of a Velocity variable (the methods and properties starting from the dot). - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param fullSyntax - * indicate if it's between { and } - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - private int followVar(char[] array, int currentIndex, boolean fullSyntax, VelocityParserContext context) { - int i = currentIndex; - - while (i < array.length) { - if (fullSyntax && array[i] == '}') { - ++i; - break; - } else if (array[i] == '.') { - try { - i = getMethodOrProperty(array, i, null, context); - } catch (InvalidVelocityException e) { - getLogger().debug("Not a valid method at char [" + i + "]", e); - break; - } - } else if (array[i] == '[') { - i = getTableElement(array, i, null, context); - break; - } else { - break; - } - } + context.setType(VelocityBlock.VelocityType.VAR); + + return i; + } + + /** + * Look in previous characters of the array to find if the current var is escaped (like \$var). + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @return the parser context to put some informations + */ + private boolean isVarEscaped(char[] array, int currentIndex) { + int i = currentIndex - 1; + + while (i >= 0 && array[i] == '\\') { + --i; + } - return i; - } - - /** - * Get a velocity method call or a property starting with a .. - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - * - * @throws InvalidVelocityException - * not a valid velocity block - */ - public int getMethodOrProperty(char[] array, int currentIndex, StringBuffer velocityBlock, - VelocityParserContext context) throws InvalidVelocityException { - int i = currentIndex + 1; - - // A Velocity method starts with [a-zA-Z] - if (Character.isLetter(array[i])) { - for (; i < array.length; ++i) { - if (array[i] == '(') { - i = getMethodParameters(array, i, null, context); - break; - } else if (!Character.isLetterOrDigit(array[i])) { - break; - } - } - } else { - throw new InvalidVelocityException(); - } + return (currentIndex - i) % 2 == 0; + } + + /** + * Get the right part of a Velocity variable (the methods and properties starting from the dot). + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param fullSyntax + * indicate if it's between { and } + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + private int followVar(char[] array, int currentIndex, boolean fullSyntax, + VelocityParserContext context) { + int i = currentIndex; + + while (i < array.length) { + if (fullSyntax && array[i] == '}') { + ++i; + break; + } else if (array[i] == '.') { + try { + i = getMethodOrProperty(array, i, null, context); + } catch (InvalidVelocityException e) { + getLogger().debug("Not a valid method at char [" + i + "]", e); + break; + } + } else if (array[i] == '[') { + i = getTableElement(array, i, null, context); + break; + } else { + break; + } + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + return i; + } + + /** + * Get a velocity method call or a property starting with a .. + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + * @throws InvalidVelocityException + * not a valid velocity block + */ + public int getMethodOrProperty(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) throws InvalidVelocityException { + int i = currentIndex + 1; + + // A Velocity method starts with [a-zA-Z] + if (Character.isLetter(array[i])) { + for (; i < array.length; ++i) { + if (array[i] == '(') { + i = getMethodParameters(array, i, null, context); + break; + } else if (!Character.isLetterOrDigit(array[i])) { + break; + } + } + } else { + throw new InvalidVelocityException(); + } - return i; - } - - /** - * Get a Velocity table. - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getTableElement(char[] array, int currentIndex, StringBuffer velocityBlock, - VelocityParserContext context) { - return getParameters(array, currentIndex, velocityBlock, ']', context); - } - - /** - * Get the Velocity method parameters (including ( and )). - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getMethodParameters(char[] array, int currentIndex, StringBuffer velocityBlock, - VelocityParserContext context) { - return getParameters(array, currentIndex, velocityBlock, ')', context); - } - - /** - * Get a group of parameters between two characters. Generic version of - * {@link #getTableElement(char[], int, StringBuffer, VelocityParserContext)} and - * {@link #getMethodParameters(char[], int, StringBuffer, VelocityParserContext)}. - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param endingChar - * the char to end to - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getParameters(char[] array, int currentIndex, StringBuffer velocityBlock, char endingChar, - VelocityParserContext context) { - char beginChar = array[currentIndex]; - - int i = currentIndex + 1; - - int depth = 1; - - while (i < array.length) { - if (array[i] == endingChar) { - --depth; - if (depth == 0) { - ++i; - break; - } - } else if (array[i] == beginChar) { - ++depth; - } else if (array[i] == '"' || array[i] == '\'') { - i = getEscape(array, i, null, context); - continue; - } - - ++i; - } + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + return i; + } + + /** + * Get a Velocity table. + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getTableElement(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) { + return getParameters(array, currentIndex, velocityBlock, ']', context); + } + + /** + * Get the Velocity method parameters (including ( and )). + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getMethodParameters(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) { + return getParameters(array, currentIndex, velocityBlock, ')', context); + } + + /** + * Get a group of parameters between two characters. Generic version of + * {@link #getTableElement(char[], int, StringBuffer, VelocityParserContext)} and + * {@link #getMethodParameters(char[], int, StringBuffer, VelocityParserContext)}. + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param endingChar + * the char to end to + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getParameters(char[] array, int currentIndex, StringBuffer velocityBlock, + char endingChar, + VelocityParserContext context) { + char beginChar = array[currentIndex]; + + int i = currentIndex + 1; + + int depth = 1; + + while (i < array.length) { + if (array[i] == endingChar) { + --depth; + if (depth == 0) { + ++i; + break; + } + } else if (array[i] == beginChar) { + ++depth; + } else if (array[i] == '"' || array[i] == '\'') { + i = getEscape(array, i, null, context); + continue; + } + + ++i; + } - return i; - } - - /** - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getEscape(char[] array, int currentIndex, StringBuffer velocityBlock, VelocityParserContext context) { - char escapeChar = array[currentIndex]; - - int i = currentIndex + 1; - - boolean escaped = false; - - for (; i < array.length;) { - if (!escaped) { - if (array[i] == '\\') { - escaped = true; - } else if (array[i] == '$') { - try { - i = getVar(array, i, null, context); - continue; - } catch (InvalidVelocityException e) { - getLogger().debug("Not a valid variable at char [" + i + "]", e); - } - } else if (array[i] == escapeChar) { - ++i; - break; - } - } else { - escaped = false; - } - - ++i; - } + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + return i; + } + + /** + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getEscape(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) { + char escapeChar = array[currentIndex]; + + int i = currentIndex + 1; + + boolean escaped = false; + + for (; i < array.length;) { + if (!escaped) { + if (array[i] == '\\') { + escaped = true; + } else if (array[i] == '$') { + try { + i = getVar(array, i, null, context); + continue; + } catch (InvalidVelocityException e) { + getLogger().debug("Not a valid variable at char [" + i + "]", e); + } + } else if (array[i] == escapeChar) { + ++i; + break; + } + } else { + escaped = false; + } + + ++i; + } - return i; - } - - /** - * Match a group of {@link Character#isWhitespace(char)}. - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getWhiteSpaces(char[] array, int currentIndex, StringBuffer velocityBlock, - VelocityParserContext context) { - int i = currentIndex; - - while (i < array.length && Character.isWhitespace(array[i])) { - ++i; - } + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + return i; + } + + /** + * Match a group of {@link Character#isWhitespace(char)}. + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getWhiteSpaces(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) { + int i = currentIndex; + + while (i < array.length && Character.isWhitespace(array[i])) { + ++i; + } - return i; - } - - /** - * Match a group of space characters (ASCII 32). - * - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getSpaces(char[] array, int currentIndex, StringBuffer velocityBlock, VelocityParserContext context) { - int i = currentIndex; - - while (i < array.length && Character.isWhitespace(array[i])) { - ++i; - } + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + return i; + } + + /** + * Match a group of space characters (ASCII 32). + * + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getSpaces(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) { + int i = currentIndex; + + while (i < array.length && Character.isWhitespace(array[i])) { + ++i; + } - return i; - } - - /** - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getMacroParametersSeparator(char[] array, int currentIndex, StringBuffer velocityBlock, - VelocityParserContext context) { - int i = currentIndex; - - i = getWhiteSpaces(array, i, null, context); - if (array[i] == ',') { - i++; - } - i = getWhiteSpaces(array, i, null, context); + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + return i; + } + + /** + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getMacroParametersSeparator(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) { + int i = currentIndex; + + i = getWhiteSpaces(array, i, null, context); + if (array[i] == ',') { + i++; + } + i = getWhiteSpaces(array, i, null, context); - return i; - } - - /** - * @param array - * the source to parse - * @param currentIndex - * the current index in the array - * @param velocityBlock - * the buffer where to append matched velocity block - * @param context - * the parser context to put some informations - * - * @return the index in the array after the matched block - */ - public int getMacroParameter(char[] array, int currentIndex, StringBuffer velocityBlock, - VelocityParserContext context) { - int i = currentIndex; - - for (; i < array.length; ++i) { - if (array[i] == '$') { - try { - i = getVar(array, i, null, context); - break; - } catch (InvalidVelocityException e) { - getLogger().debug("Not a valid velocity variable at char [" + i + "]", e); - } - } else if (array[i] == '"' || array[i] == '\'') { - i = getEscape(array, i, null, context); - break; - } else if (Character.isWhitespace(array[i]) || array[i] == ',') { - break; - } else if (array[i] == ')') { - break; - } - } + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); + } - if (velocityBlock != null) { - velocityBlock.append(array, currentIndex, i - currentIndex); - } + return i; + } + + /** + * @param array + * the source to parse + * @param currentIndex + * the current index in the array + * @param velocityBlock + * the buffer where to append matched velocity block + * @param context + * the parser context to put some informations + * @return the index in the array after the matched block + */ + public int getMacroParameter(char[] array, int currentIndex, StringBuffer velocityBlock, + VelocityParserContext context) { + int i = currentIndex; + + for (; i < array.length; ++i) { + if (array[i] == '$') { + try { + i = getVar(array, i, null, context); + break; + } catch (InvalidVelocityException e) { + getLogger().debug("Not a valid velocity variable at char [" + i + "]", e); + } + } else if (array[i] == '"' || array[i] == '\'') { + i = getEscape(array, i, null, context); + break; + } else if (Character.isWhitespace(array[i]) || array[i] == ',') { + break; + } else if (array[i] == ')') { + break; + } + } - return i; + if (velocityBlock != null) { + velocityBlock.append(array, currentIndex, i - currentIndex); } + + return i; + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityParserContext.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityParserContext.java index 2ec52d629..9a090a112 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityParserContext.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/internal/util/VelocityParserContext.java @@ -29,63 +29,63 @@ * @version $Id$ */ public class VelocityParserContext { - /** - * The type of found velocity block. - */ - private VelocityType type; - /** - * The current blocks. - */ - private Stack blocks = new Stack(); + /** + * The type of found velocity block. + */ + private VelocityType type; - /** - * @param type - * the type of found velocity block. - */ - public void setType(VelocityType type) { - this.type = type; - } + /** + * The current blocks. + */ + private Stack blocks = new Stack(); - /** - * @return The type of found velocity block. - */ - public VelocityType getType() { - return this.type; - } + /** + * @param type + * the type of found velocity block. + */ + public void setType(VelocityType type) { + this.type = type; + } - /** - * @return the Velocity block in which the process is. - */ - public VelocityBlock getCurrentElement() { - return this.blocks.peek(); - } + /** + * @return The type of found velocity block. + */ + public VelocityType getType() { + return this.type; + } - /** - * Enter a Velocity block. - * - * @param block - * the Velocity block in which the process is. - * - * @return the Velocity block in which the process is. - */ - public VelocityBlock pushVelocityElement(VelocityBlock block) { - return this.blocks.push(block); - } + /** + * @return the Velocity block in which the process is. + */ + public VelocityBlock getCurrentElement() { + return this.blocks.peek(); + } - /** - * Go out of a Velocity block. - * - * @return the previous Velocity block in which the process was. - */ - public VelocityBlock popVelocityElement() { - return this.blocks.pop(); - } + /** + * Enter a Velocity block. + * + * @param block + * the Velocity block in which the process is. + * @return the Velocity block in which the process is. + */ + public VelocityBlock pushVelocityElement(VelocityBlock block) { + return this.blocks.push(block); + } - /** - * @return indicate if the current process is inside a Velocity block. - */ - public boolean isInVelocityBlock() { - return !this.blocks.isEmpty(); - } + /** + * Go out of a Velocity block. + * + * @return the previous Velocity block in which the process was. + */ + public VelocityBlock popVelocityElement() { + return this.blocks.pop(); + } + + /** + * @return indicate if the current process is inside a Velocity block. + */ + public boolean isInVelocityBlock() { + return !this.blocks.isEmpty(); + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/AbstractChainableUberspector.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/AbstractChainableUberspector.java index 7bc15e7ca..4cf1c00ba 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/AbstractChainableUberspector.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/AbstractChainableUberspector.java @@ -30,87 +30,94 @@ import org.apache.velocity.util.introspection.VelPropertySet; /** - * Default implementation of a {@link ChainableUberspector chainable uberspector} that forwards all calls to the wrapped - * uberspector (when that is possible). It should be used as the base class for all chainable uberspectors. + * Default implementation of a {@link ChainableUberspector chainable uberspector} that forwards all + * calls to the wrapped + * uberspector (when that is possible). It should be used as the base class for all chainable + * uberspectors. * * @version $Id$ - * * @since 1.5M1 - * * @see ChainableUberspector */ -public abstract class AbstractChainableUberspector extends UberspectImpl implements ChainableUberspector { - /** The wrapped (decorated) uberspector. */ - protected Uberspect inner; +public abstract class AbstractChainableUberspector extends UberspectImpl + implements ChainableUberspector { - /** - * {@inheritDoc} - * - * @see ChainableUberspector#wrap(org.apache.velocity.util.introspection.Uberspect) - * @see #inner - */ - public void wrap(Uberspect inner) { - this.inner = inner; - } + /** The wrapped (decorated) uberspector. */ + protected Uberspect inner; - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.introspection.Uberspect#init() - */ - @Override - public void init() { - if (this.inner != null) { - try { - this.inner.init(); - } catch (Exception e) { - this.log.error(e.getMessage(), e); - } - } - } + /** + * {@inheritDoc} + * + * @see ChainableUberspector#wrap(org.apache.velocity.util.introspection.Uberspect) + * @see #inner + */ + public void wrap(Uberspect inner) { + this.inner = inner; + } - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.introspection.Uberspect#getIterator(java.lang.Object, - * org.apache.velocity.util.introspection.Info) - */ - @SuppressWarnings("unchecked") - @Override - public Iterator getIterator(Object obj, Info i) throws Exception { - return (this.inner != null) ? this.inner.getIterator(obj, i) : null; + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.introspection.Uberspect#init() + */ + @Override + public void init() { + if (this.inner != null) { + try { + this.inner.init(); + } catch (Exception e) { + this.log.error(e.getMessage(), e); + } } + } - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.introspection.Uberspect#getMethod(java.lang.Object, java.lang.String, - * java.lang.Object[], org.apache.velocity.util.introspection.Info) - */ - @Override - public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) throws Exception { - return (this.inner != null) ? this.inner.getMethod(obj, methodName, args, i) : null; - } + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.introspection.Uberspect#getIterator(java.lang.Object, + * org.apache.velocity.util.introspection.Info) + */ + @SuppressWarnings("unchecked") + @Override + public Iterator getIterator(Object obj, Info i) throws Exception { + return (this.inner != null) ? this.inner.getIterator(obj, i) : null; + } - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.introspection.Uberspect#getPropertyGet(java.lang.Object, java.lang.String, - * org.apache.velocity.util.introspection.Info) - */ - @Override - public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception { - return (this.inner != null) ? this.inner.getPropertyGet(obj, identifier, i) : null; - } + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.introspection.Uberspect#getMethod(java.lang.Object, + * java.lang.String, + * java.lang.Object[], org.apache.velocity.util.introspection.Info) + */ + @Override + public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) + throws Exception { + return (this.inner != null) ? this.inner.getMethod(obj, methodName, args, i) : null; + } - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.introspection.Uberspect#getPropertySet(java.lang.Object, java.lang.String, - * java.lang.Object, org.apache.velocity.util.introspection.Info) - */ - @Override - public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info i) throws Exception { - return (this.inner != null) ? this.inner.getPropertySet(obj, identifier, arg, i) : null; - } + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.introspection.Uberspect#getPropertyGet(java.lang.Object, + * java.lang.String, + * org.apache.velocity.util.introspection.Info) + */ + @Override + public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception { + return (this.inner != null) ? this.inner.getPropertyGet(obj, identifier, i) : null; + } + + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.introspection.Uberspect#getPropertySet(java.lang.Object, + * java.lang.String, + * java.lang.Object, org.apache.velocity.util.introspection.Info) + */ + @Override + public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info i) + throws Exception { + return (this.inner != null) ? this.inner.getPropertySet(obj, identifier, arg, i) : null; + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/ChainableUberspector.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/ChainableUberspector.java index d7f573700..c3982ea06 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/ChainableUberspector.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/ChainableUberspector.java @@ -23,27 +23,31 @@ import org.apache.velocity.util.introspection.Uberspect; /** - * Interface that marks uberspectors as chainable, meaning that multiple uberspectors can be combined in a chain (using + * Interface that marks uberspectors as chainable, meaning that multiple uberspectors can be + * combined in a chain (using * the Decorator pattern). * * @version $Id$ - * * @since 1.5M1 */ public interface ChainableUberspector extends Uberspect { - /** - * Since uberspectors are dynamically enabled using a configuration string, we cannot simply call the constructors - * to pass the inner uberspector. We can either instantiate uberspectors using reflection and passing the wrapped - * object to the constructor, or explicitely "wrap" the inner uberspector. The second method has several advantages, - * so it was chosen here: - *
    - *
  • Doesn't require adding an extra constructor
  • - *
  • Keeps the initialization process a bit more simple
  • - *
  • Allows the wrapping to take place at a different time
  • - *
- * - * @param inner - * The decorated uberspector. - */ - void wrap(Uberspect inner); + + /** + * Since uberspectors are dynamically enabled using a configuration string, we cannot simply call + * the constructors + * to pass the inner uberspector. We can either instantiate uberspectors using reflection and + * passing the wrapped + * object to the constructor, or explicitely "wrap" the inner uberspector. The second method has + * several advantages, + * so it was chosen here: + *
    + *
  • Doesn't require adding an extra constructor
  • + *
  • Keeps the initialization process a bit more simple
  • + *
  • Allows the wrapping to take place at a different time
  • + *
+ * + * @param inner + * The decorated uberspector. + */ + void wrap(Uberspect inner); } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/ChainingUberspector.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/ChainingUberspector.java index c7a01d02b..5d95fedaf 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/ChainingUberspector.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/ChainingUberspector.java @@ -30,149 +30,168 @@ /** *

- * Since the current version of the Velocity engine (1.5) does not allow more than one uberspector, this class is a - * workaround. It manually constructs a chain of uberspectors, loading the classes in the order defined - * in the "runtime.introspector.uberspect.chainClasses" property, and after that simply forwarding all - * calls to the top of the chain. Note that the calls will be made from the rightmost class to the leftmost one. Along - * the chain, each uberspectors can forward the call to the rest of the chain, build its own result, and/or process in - * any way the resulting value. This allows uberspectors to enhance the list of returned methods, block out methods - * returned by other uberspectors, or take various actions on the returned method (for example add or remove parameters - * before searching the method, log executed method names, or catch exceptions when executing those methods). + * Since the current version of the Velocity engine (1.5) does not allow more than one uberspector, + * this class is a + * workaround. It manually constructs a chain of uberspectors, loading the classes + * in the order defined + * in the "runtime.introspector.uberspect.chainClasses" property, and after that simply + * forwarding all + * calls to the top of the chain. Note that the calls will be made from the rightmost class to the + * leftmost one. Along + * the chain, each uberspectors can forward the call to the rest of the chain, build its own result, + * and/or process in + * any way the resulting value. This allows uberspectors to enhance the list of returned methods, + * block out methods + * returned by other uberspectors, or take various actions on the returned method (for example add + * or remove parameters + * before searching the method, log executed method names, or catch exceptions when executing those + * methods). *

*

- * This is not actually part of the chain, but is more of a handle that allows the calls intended for only one - * uberspector to reach the chain. It duplicates some of the code from the velocity runtime initialization code, hoping + * This is not actually part of the chain, but is more of a handle that allows the calls intended + * for only one + * uberspector to reach the chain. It duplicates some of the code from the velocity runtime + * initialization code, hoping * that a future version of the engine will support chaining natively. *

*

- * The chain is defined using the configuration parameter runtime.introspector.uberspect.chainClasses. This - * property should contain a list of canonical class names. Any wrong entry in the list will be ignored. If this - * property is not defined or contains only wrong classnames, then by default a SecureUberspector is used - * as the only entry in the chain. The first (leftmost) uberspector does not have to be chainable (as it will not need - * to forward calls). If a uberspector in the middle of the chain is not chainable, then it will break the chain at that + * The chain is defined using the configuration parameter + * runtime.introspector.uberspect.chainClasses. This + * property should contain a list of canonical class names. Any wrong entry in the list will be + * ignored. If this + * property is not defined or contains only wrong classnames, then by default a + * SecureUberspector is used + * as the only entry in the chain. The first (leftmost) uberspector does not have to be chainable + * (as it will not need + * to forward calls). If a uberspector in the middle of the chain is not chainable, then it will + * break the chain at that * point (all previos uberspectors will be discarded from the chain). *

* * @since 1.5M1 - * * @see ChainableUberspector - * * @version $Id$ */ public class ChainingUberspector extends AbstractChainableUberspector - implements Uberspect, RuntimeServicesAware, UberspectLoggable { - /** The key of the parameter that allows defining the list of chained uberspectors. */ - public static final String UBERSPECT_CHAIN_CLASSNAMES = "runtime.introspector.uberspect.chainClasses"; + implements Uberspect, RuntimeServicesAware, UberspectLoggable { - /** The runtime is needed for accessing the configuration. */ - private RuntimeServices runtime; + /** The key of the parameter that allows defining the list of chained uberspectors. */ + public static final String UBERSPECT_CHAIN_CLASSNAMES = "runtime.introspector.uberspect.chainClasses"; - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.RuntimeServicesAware#setRuntimeServices( - * org.apache.velocity.runtime.RuntimeServices) - */ - public void setRuntimeServices(RuntimeServices rs) { - this.runtime = rs; - } + /** The runtime is needed for accessing the configuration. */ + private RuntimeServices runtime; + + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.RuntimeServicesAware#setRuntimeServices( + * org.apache.velocity.runtime.RuntimeServices) + */ + public void setRuntimeServices(RuntimeServices rs) { + this.runtime = rs; + } - /** - * {@inheritDoc} - *

- * This implementation initializes the uberspector chain. - *

- * - * @see org.apache.velocity.util.introspection.Uberspect#init() - */ - @Override - public void init() { - this.log.debug("Initializing the chaining uberspector."); - // Create the chain - // TODO Since we're in Plexus already, should we use components? - String[] chainClassnames = this.runtime.getConfiguration().getStringArray(UBERSPECT_CHAIN_CLASSNAMES); - for (String classname : chainClassnames) { - initializeUberspector(classname); - } - // If the chain is empty, use a SecureUberspector - if (this.inner == null) { - this.log.error("No chained uberspectors defined! " - + "This uberspector is just a placeholder that relies on a real uberspector " - + "to actually allow method calls. Using SecureUberspect instead as a fallback."); - initializeUberspector(SecureUberspector.class.getCanonicalName()); - } - // Initialize all the uberspectors in the chain - try { - this.inner.init(); - } catch (Exception e) { - this.log.warn(e.getMessage()); - } + /** + * {@inheritDoc} + *

+ * This implementation initializes the uberspector chain. + *

+ * + * @see org.apache.velocity.util.introspection.Uberspect#init() + */ + @Override + public void init() { + this.log.debug("Initializing the chaining uberspector."); + // Create the chain + // TODO Since we're in Plexus already, should we use components? + String[] chainClassnames = this.runtime.getConfiguration() + .getStringArray(UBERSPECT_CHAIN_CLASSNAMES); + for (String classname : chainClassnames) { + initializeUberspector(classname); } + // If the chain is empty, use a SecureUberspector + if (this.inner == null) { + this.log.error("No chained uberspectors defined! " + + "This uberspector is just a placeholder that relies on a real uberspector " + + "to actually allow method calls. Using SecureUberspect instead as a fallback."); + initializeUberspector(SecureUberspector.class.getCanonicalName()); + } + // Initialize all the uberspectors in the chain + try { + this.inner.init(); + } catch (Exception e) { + this.log.warn(e.getMessage()); + } + } - /** - * Instantiates an uberspector class and adds it to the chain. Also set the log and runtime services, if the class - * implements the proper interfaces. The {@link Uberspect#init()} method is not called. - * - * @param classname - * The name of the uberspector class to add to the chain. - */ - protected void initializeUberspector(String classname) { - // Avoids direct recursive calls - if (!StringUtils.isEmpty(classname) && !classname.equals(this.getClass().getCanonicalName())) { - Uberspect u = instantiateUberspector(classname); - if (u == null) { - return; - } + /** + * Instantiates an uberspector class and adds it to the chain. Also set the log and runtime + * services, if the class + * implements the proper interfaces. The {@link Uberspect#init()} method is not called. + * + * @param classname + * The name of the uberspector class to add to the chain. + */ + protected void initializeUberspector(String classname) { + // Avoids direct recursive calls + if (!StringUtils.isEmpty(classname) && !classname.equals(this.getClass().getCanonicalName())) { + Uberspect u = instantiateUberspector(classname); + if (u == null) { + return; + } - // Set the log and runtime services, if applicable - if (u instanceof UberspectLoggable) { - ((UberspectLoggable) u).setLog(this.log); - } - if (u instanceof RuntimeServicesAware) { - ((RuntimeServicesAware) u).setRuntimeServices(this.runtime); - } + // Set the log and runtime services, if applicable + if (u instanceof UberspectLoggable) { + ((UberspectLoggable) u).setLog(this.log); + } + if (u instanceof RuntimeServicesAware) { + ((RuntimeServicesAware) u).setRuntimeServices(this.runtime); + } - // Link it in the chain - if (u instanceof ChainableUberspector) { - ((ChainableUberspector) u).wrap(this.inner); - } - this.inner = u; - } + // Link it in the chain + if (u instanceof ChainableUberspector) { + ((ChainableUberspector) u).wrap(this.inner); + } + this.inner = u; } + } - /** - * Tries to create an uberspector instance using reflection. - * - * @param classname - * The name of the uberspector class to instantiate. - * - * @return An instance of the specified Uberspector. If the class cannot be instantiated using the default - * constructor, or does not implement {@link Uberspect}, null is returned. - */ - protected Uberspect instantiateUberspector(String classname) { - Object o = null; - try { - o = ClassUtils.getNewInstance(classname); - } catch (ClassNotFoundException cnfe) { - this.log.warn(String.format("The specified uberspector [%s]" - + " does not exist or is not accessible to the current classloader.", classname)); - } catch (IllegalAccessException e) { - this.log.warn(String.format("The specified uberspector [%s] does not have a public default constructor.", - classname)); - } catch (InstantiationException e) { - this.log.warn(String.format("The specified uberspector [%s] cannot be instantiated.", classname)); - } catch (ExceptionInInitializerError e) { - this.log.warn( - String.format("Exception while instantiating the Uberspector [%s]: %s", classname, e.getMessage())); - } + /** + * Tries to create an uberspector instance using reflection. + * + * @param classname + * The name of the uberspector class to instantiate. + * @return An instance of the specified Uberspector. If the class cannot be instantiated using the + * default + * constructor, or does not implement {@link Uberspect}, null is returned. + */ + protected Uberspect instantiateUberspector(String classname) { + Object o = null; + try { + o = ClassUtils.getNewInstance(classname); + } catch (ClassNotFoundException cnfe) { + this.log.warn(String.format("The specified uberspector [%s]" + + " does not exist or is not accessible to the current classloader.", classname)); + } catch (IllegalAccessException e) { + this.log.warn(String.format( + "The specified uberspector [%s] does not have a public default constructor.", + classname)); + } catch (InstantiationException e) { + this.log + .warn(String.format("The specified uberspector [%s] cannot be instantiated.", classname)); + } catch (ExceptionInInitializerError e) { + this.log.warn( + String.format("Exception while instantiating the Uberspector [%s]: %s", classname, + e.getMessage())); + } - if (!(o instanceof Uberspect)) { - if (o != null) { - this.log.warn("The specified class for Uberspect [" + classname + "] does not implement " - + Uberspect.class.getName()); - } - return null; - } - return (Uberspect) o; + if (!(o instanceof Uberspect)) { + if (o != null) { + this.log.warn("The specified class for Uberspect [" + classname + "] does not implement " + + Uberspect.class.getName()); + } + return null; } + return (Uberspect) o; + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/DeprecatedCheckUberspector.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/DeprecatedCheckUberspector.java index 545c36158..7c1f0d3f1 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/DeprecatedCheckUberspector.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/DeprecatedCheckUberspector.java @@ -31,99 +31,107 @@ import org.apache.velocity.util.introspection.VelPropertySet; /** - * Chainable Velocity Uberspector that checks for deprecated method calls. It does that by checking if the returned - * method has a Deprecated annotation. Because this is a chainable uberspector, it has to re-get the method using a - * default introspector, which is not safe; future uberspectors might not be able to return a precise method name, or a + * Chainable Velocity Uberspector that checks for deprecated method calls. It does that by checking + * if the returned + * method has a Deprecated annotation. Because this is a chainable uberspector, it has to re-get the + * method using a + * default introspector, which is not safe; future uberspectors might not be able to return a + * precise method name, or a * method of the original target object. * * @since 1.5M1 - * * @version $Id$ - * * @see ChainableUberspector */ public class DeprecatedCheckUberspector extends AbstractChainableUberspector - implements Uberspect, ChainableUberspector, UberspectLoggable { - /** - * {@inheritDoc} - * - * @see Uberspect#init() - */ - public void init() { - super.init(); - this.introspector = new Introspector(log); - } + implements Uberspect, ChainableUberspector, UberspectLoggable { - /** - * {@inheritDoc} - * - * @see Uberspect#getMethod(java.lang.Object, java.lang.String, java.lang.Object[], - * org.apache.velocity.util.introspection.Info) - */ - @Override - public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) throws Exception { - VelMethod method = super.getMethod(obj, methodName, args, i); - if (method != null) { - Method m = introspector.getMethod(obj.getClass(), method.getMethodName(), args); - if (m != null && m.isAnnotationPresent(Deprecated.class)) { - logWarning("method", obj, method.getMethodName(), i); - } - } - return method; - } + /** + * {@inheritDoc} + * + * @see Uberspect#init() + */ + public void init() { + super.init(); + this.introspector = new Introspector(log); + } - /** - * {@inheritDoc} - * - * @see Uberspect#getPropertyGet(java.lang.Object, java.lang.String, org.apache.velocity.util.introspection.Info) - */ - @Override - public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception { - VelPropertyGet method = super.getPropertyGet(obj, identifier, i); - if (method != null) { - Method m = introspector.getMethod(obj.getClass(), method.getMethodName(), new Object[] {}); - if (m != null && m.isAnnotationPresent(Deprecated.class)) { - logWarning("getter", obj, method.getMethodName(), i); - } - } - return method; + /** + * {@inheritDoc} + * + * @see Uberspect#getMethod(java.lang.Object, java.lang.String, java.lang.Object[], + * org.apache.velocity.util.introspection.Info) + */ + @Override + public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) + throws Exception { + VelMethod method = super.getMethod(obj, methodName, args, i); + if (method != null) { + Method m = introspector.getMethod(obj.getClass(), method.getMethodName(), args); + if (m != null && m.isAnnotationPresent(Deprecated.class)) { + logWarning("method", obj, method.getMethodName(), i); + } } + return method; + } - /** - * {@inheritDoc} - * - * @see Uberspect#getPropertySet(java.lang.Object, java.lang.String, java.lang.Object, - * org.apache.velocity.util.introspection.Info) - */ - @Override - public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info i) throws Exception { - // TODO Auto-generated method stub - VelPropertySet method = super.getPropertySet(obj, identifier, arg, i); - if (method != null) { - Method m = introspector.getMethod(obj.getClass(), method.getMethodName(), new Object[] { arg }); - if (m != null && m.isAnnotationPresent(Deprecated.class)) { - logWarning("setter", obj, method.getMethodName(), i); - } - } - return method; + /** + * {@inheritDoc} + * + * @see Uberspect#getPropertyGet(java.lang.Object, java.lang.String, + * org.apache.velocity.util.introspection.Info) + */ + @Override + public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception { + VelPropertyGet method = super.getPropertyGet(obj, identifier, i); + if (method != null) { + Method m = introspector.getMethod(obj.getClass(), method.getMethodName(), new Object[] {}); + if (m != null && m.isAnnotationPresent(Deprecated.class)) { + logWarning("getter", obj, method.getMethodName(), i); + } } + return method; + } - /** - * Helper method to log a warning when a deprecation has been found. - * - * @param deprecationType - * the type of deprecation (eg "getter", "setter", "method") - * @param object - * the object that has a deprecation - * @param methodName - * the deprecated method's name - * @param info - * a Velocity {@link org.apache.velocity.util.introspection.Info} object containing information about - * where the deprecation was located in the Velocity template file - */ - private void logWarning(String deprecationType, Object object, String methodName, Info info) { - log.warn(String.format("Deprecated usage of %s [%s] in %s@%d,%d", deprecationType, - object.getClass().getCanonicalName() + "." + methodName, info.getTemplateName(), info.getLine(), - info.getColumn())); + /** + * {@inheritDoc} + * + * @see Uberspect#getPropertySet(java.lang.Object, java.lang.String, java.lang.Object, + * org.apache.velocity.util.introspection.Info) + */ + @Override + public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info i) + throws Exception { + // TODO Auto-generated method stub + VelPropertySet method = super.getPropertySet(obj, identifier, arg, i); + if (method != null) { + Method m = introspector.getMethod(obj.getClass(), method.getMethodName(), + new Object[] { arg }); + if (m != null && m.isAnnotationPresent(Deprecated.class)) { + logWarning("setter", obj, method.getMethodName(), i); + } } + return method; + } + + /** + * Helper method to log a warning when a deprecation has been found. + * + * @param deprecationType + * the type of deprecation (eg "getter", "setter", "method") + * @param object + * the object that has a deprecation + * @param methodName + * the deprecated method's name + * @param info + * a Velocity {@link org.apache.velocity.util.introspection.Info} object containing + * information about + * where the deprecation was located in the Velocity template file + */ + private void logWarning(String deprecationType, Object object, String methodName, Info info) { + log.warn(String.format("Deprecated usage of %s [%s] in %s@%d,%d", deprecationType, + object.getClass().getCanonicalName() + "." + methodName, info.getTemplateName(), + info.getLine(), + info.getColumn())); + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/LinkingUberspector.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/LinkingUberspector.java index 7d91a2862..6c15e5a37 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/LinkingUberspector.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/introspection/LinkingUberspector.java @@ -39,218 +39,239 @@ /** *

- * Since the current version of the Velocity engine (1.5) does not allow more than one uberspector, this class is a - * workaround. It manually constructs an array of uberspectors, loading the classes in the order - * defined in the "runtime.introspector.uberspect.arrayClasses" property, and after that forwards calls to - * each of the uberspectors, in order, until one of them returns something different than null. Note that - * the calls will be made from the leftmost class to the rightmost one. This allows building and combining different - * small uberspectors that perform a specialised search for methods, instead of bloating a single class with different + * Since the current version of the Velocity engine (1.5) does not allow more than one uberspector, + * this class is a + * workaround. It manually constructs an array of uberspectors, loading the classes + * in the order + * defined in the "runtime.introspector.uberspect.arrayClasses" property, and after + * that forwards calls to + * each of the uberspectors, in order, until one of them returns something different than + * null. Note that + * the calls will be made from the leftmost class to the rightmost one. This allows building and + * combining different + * small uberspectors that perform a specialised search for methods, instead of bloating a single + * class with different * introspection tricks. *

*

- * This is not actually part of the array, but is more of a handle that allows the calls intended for only one - * uberspector to reach the array. It duplicates some of the code from the velocity runtime initialization code, hoping + * This is not actually part of the array, but is more of a handle that allows the calls intended + * for only one + * uberspector to reach the array. It duplicates some of the code from the velocity runtime + * initialization code, hoping * that a future version of the engine will support this natively. *

*

- * The array is defined using the configuration parameter runtime.introspector.uberspect.arrayClasses. This - * property should contain a list of canonical class names. Any wrong entry in the list will be ignored. If this - * property is not defined or contains only wrong classnames, then by default a SecureUberspector is used + * The array is defined using the configuration parameter + * runtime.introspector.uberspect.arrayClasses. This + * property should contain a list of canonical class names. Any wrong entry in the list will be + * ignored. If this + * property is not defined or contains only wrong classnames, then by default a + * SecureUberspector is used * as the only entry in the array. *

* * @since 1.5RC1 - * * @see ChainingUberspector - * * @version $Id$ */ -public class LinkingUberspector extends UberspectImpl implements Uberspect, RuntimeServicesAware, UberspectLoggable { - /** The key of the parameter that allows defining the array of uberspectors. */ - public static final String UBERSPECT_ARRAY_CLASSNAMES = "runtime.introspector.uberspect.arrayClasses"; +public class LinkingUberspector extends UberspectImpl + implements Uberspect, RuntimeServicesAware, UberspectLoggable { - /** The runtime is needed for accessing the configuration. */ - private RuntimeServices runtime; + /** The key of the parameter that allows defining the array of uberspectors. */ + public static final String UBERSPECT_ARRAY_CLASSNAMES = "runtime.introspector.uberspect.arrayClasses"; - /** The array of uberspectors to use. */ - private List uberspectors; + /** The runtime is needed for accessing the configuration. */ + private RuntimeServices runtime; - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.RuntimeServicesAware#setRuntimeServices(org.apache.velocity.runtime.RuntimeServices) - */ - public void setRuntimeServices(RuntimeServices rs) { - this.runtime = rs; - } + /** The array of uberspectors to use. */ + private List uberspectors; - /** - * {@inheritDoc} - *

- * This implementation initializes the array of uberspectors. - *

- * - * @see org.apache.velocity.util.introspection.Uberspect#init() - */ - @Override - public void init() { - this.log.debug("Initializing the linking uberspector."); - // Create the array - String[] arrayClassnames = this.runtime.getConfiguration().getStringArray(UBERSPECT_ARRAY_CLASSNAMES); - this.uberspectors = new ArrayList(arrayClassnames.length); - for (String classname : arrayClassnames) { - initializeUberspector(classname); - } - // If the chain is empty, use a SecureUberspector - if (this.uberspectors.isEmpty()) { - this.log.error("No uberspectors defined! " - + "This uberspector is just a placeholder that relies on at least one real uberspector " - + "to actually allow method calls. Using SecureUberspector instead as a fallback."); - initializeUberspector(SecureUberspector.class.getCanonicalName()); - } + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.RuntimeServicesAware#setRuntimeServices(org.apache.velocity.runtime.RuntimeServices) + */ + public void setRuntimeServices(RuntimeServices rs) { + this.runtime = rs; + } + + /** + * {@inheritDoc} + *

+ * This implementation initializes the array of uberspectors. + *

+ * + * @see org.apache.velocity.util.introspection.Uberspect#init() + */ + @Override + public void init() { + this.log.debug("Initializing the linking uberspector."); + // Create the array + String[] arrayClassnames = this.runtime.getConfiguration() + .getStringArray(UBERSPECT_ARRAY_CLASSNAMES); + this.uberspectors = new ArrayList(arrayClassnames.length); + for (String classname : arrayClassnames) { + initializeUberspector(classname); + } + // If the chain is empty, use a SecureUberspector + if (this.uberspectors.isEmpty()) { + this.log.error("No uberspectors defined! " + + "This uberspector is just a placeholder that relies on at least one real uberspector " + + "to actually allow method calls. Using SecureUberspector instead as a fallback."); + initializeUberspector(SecureUberspector.class.getCanonicalName()); } + } - /** - * Instantiates and initializes an uberspector class and adds it to the array. Also set the log and runtime - * services, if the class implements the proper interfaces. - * - * @param classname - * The name of the uberspector class to add to the chain. - */ - protected void initializeUberspector(String classname) { - // Avoids direct recursive calls - if (!StringUtils.isEmpty(classname) && !classname.equals(this.getClass().getCanonicalName())) { - Uberspect u = instantiateUberspector(classname); - if (u == null) { - return; - } + /** + * Instantiates and initializes an uberspector class and adds it to the array. Also set the log + * and runtime + * services, if the class implements the proper interfaces. + * + * @param classname + * The name of the uberspector class to add to the chain. + */ + protected void initializeUberspector(String classname) { + // Avoids direct recursive calls + if (!StringUtils.isEmpty(classname) && !classname.equals(this.getClass().getCanonicalName())) { + Uberspect u = instantiateUberspector(classname); + if (u == null) { + return; + } - // Set the log and runtime services, if applicable - if (u instanceof UberspectLoggable) { - ((UberspectLoggable) u).setLog(this.log); - } - if (u instanceof RuntimeServicesAware) { - ((RuntimeServicesAware) u).setRuntimeServices(this.runtime); - } + // Set the log and runtime services, if applicable + if (u instanceof UberspectLoggable) { + ((UberspectLoggable) u).setLog(this.log); + } + if (u instanceof RuntimeServicesAware) { + ((RuntimeServicesAware) u).setRuntimeServices(this.runtime); + } - // Initialize the uberspector - try { - u.init(); - // Add it to the array - this.uberspectors.add(u); - } catch (Exception e) { - this.log.warn(e.getMessage()); - // If the initialization failed, don't add this uberspector to the chain. - } - } + // Initialize the uberspector + try { + u.init(); + // Add it to the array + this.uberspectors.add(u); + } catch (Exception e) { + this.log.warn(e.getMessage()); + // If the initialization failed, don't add this uberspector to the chain. + } } + } - /** - * Tries to create an uberspector instance using reflection. - * - * @param classname - * The name of the uberspector class to instantiate. - * - * @return An instance of the specified Uberspector. If the class cannot be instantiated using the default - * constructor, or does not implement {@link Uberspect}, null is returned. - */ - protected Uberspect instantiateUberspector(String classname) { - Object o = null; - try { - o = ClassUtils.getNewInstance(classname); - } catch (ClassNotFoundException e) { - this.log.warn(String.format("The specified uberspector [%s]" - + " does not exist or is not accessible to the current classloader.", classname)); - } catch (IllegalAccessException e) { - this.log.warn(String.format("The specified uberspector [%s] does not have a public default constructor.", - classname)); - } catch (InstantiationException e) { - this.log.warn(String.format("The specified uberspector [%s] cannot be instantiated.", classname)); - } catch (ExceptionInInitializerError e) { - this.log.warn( - String.format("Exception while instantiating the Uberspector [%s]: %s", classname, e.getMessage())); - } + /** + * Tries to create an uberspector instance using reflection. + * + * @param classname + * The name of the uberspector class to instantiate. + * @return An instance of the specified Uberspector. If the class cannot be instantiated using the + * default + * constructor, or does not implement {@link Uberspect}, null is returned. + */ + protected Uberspect instantiateUberspector(String classname) { + Object o = null; + try { + o = ClassUtils.getNewInstance(classname); + } catch (ClassNotFoundException e) { + this.log.warn(String.format("The specified uberspector [%s]" + + " does not exist or is not accessible to the current classloader.", classname)); + } catch (IllegalAccessException e) { + this.log.warn(String.format( + "The specified uberspector [%s] does not have a public default constructor.", + classname)); + } catch (InstantiationException e) { + this.log + .warn(String.format("The specified uberspector [%s] cannot be instantiated.", classname)); + } catch (ExceptionInInitializerError e) { + this.log.warn( + String.format("Exception while instantiating the Uberspector [%s]: %s", classname, + e.getMessage())); + } - if (!(o instanceof Uberspect)) { - if (o != null) { - this.log.warn("The specified class for Uberspect [" + classname + "] does not implement " - + Uberspect.class.getName()); - } - return null; - } - return (Uberspect) o; + if (!(o instanceof Uberspect)) { + if (o != null) { + this.log.warn("The specified class for Uberspect [" + classname + "] does not implement " + + Uberspect.class.getName()); + } + return null; } + return (Uberspect) o; + } - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.introspection.Uberspect#getIterator(java.lang.Object, - * org.apache.velocity.util.introspection.Info) - */ - @SuppressWarnings("unchecked") - @Override - public Iterator getIterator(Object obj, Info i) throws Exception { - Iterator it; - for (Uberspect u : this.uberspectors) { - it = u.getIterator(obj, i); - if (it != null) { - return it; - } - } - return null; + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.introspection.Uberspect#getIterator(java.lang.Object, + * org.apache.velocity.util.introspection.Info) + */ + @SuppressWarnings("unchecked") + @Override + public Iterator getIterator(Object obj, Info i) throws Exception { + Iterator it; + for (Uberspect u : this.uberspectors) { + it = u.getIterator(obj, i); + if (it != null) { + return it; + } } + return null; + } - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.introspection.Uberspect#getMethod(java.lang.Object, java.lang.String, - * java.lang.Object[], org.apache.velocity.util.introspection.Info) - */ - @Override - public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) throws Exception { - VelMethod method; - for (Uberspect u : this.uberspectors) { - method = u.getMethod(obj, methodName, args, i); - if (method != null) { - return method; - } - } - return null; + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.introspection.Uberspect#getMethod(java.lang.Object, + * java.lang.String, + * java.lang.Object[], org.apache.velocity.util.introspection.Info) + */ + @Override + public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) + throws Exception { + VelMethod method; + for (Uberspect u : this.uberspectors) { + method = u.getMethod(obj, methodName, args, i); + if (method != null) { + return method; + } } + return null; + } - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.introspection.Uberspect#getPropertyGet(java.lang.Object, java.lang.String, - * org.apache.velocity.util.introspection.Info) - */ - @Override - public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception { - VelPropertyGet getter; - for (Uberspect u : this.uberspectors) { - getter = u.getPropertyGet(obj, identifier, i); - if (getter != null) { - return getter; - } - } - return null; + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.introspection.Uberspect#getPropertyGet(java.lang.Object, + * java.lang.String, + * org.apache.velocity.util.introspection.Info) + */ + @Override + public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception { + VelPropertyGet getter; + for (Uberspect u : this.uberspectors) { + getter = u.getPropertyGet(obj, identifier, i); + if (getter != null) { + return getter; + } } + return null; + } - /** - * {@inheritDoc} - * - * @see org.apache.velocity.util.introspection.Uberspect#getPropertySet(java.lang.Object, java.lang.String, - * java.lang.Object, org.apache.velocity.util.introspection.Info) - */ - @Override - public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info i) throws Exception { - VelPropertySet setter; - for (Uberspect u : this.uberspectors) { - setter = u.getPropertySet(obj, identifier, arg, i); - if (setter != null) { - return setter; - } - } - return null; + /** + * {@inheritDoc} + * + * @see org.apache.velocity.util.introspection.Uberspect#getPropertySet(java.lang.Object, + * java.lang.String, + * java.lang.Object, org.apache.velocity.util.introspection.Info) + */ + @Override + public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info i) + throws Exception { + VelPropertySet setter; + for (Uberspect u : this.uberspectors) { + setter = u.getPropertySet(obj, identifier, arg, i); + if (setter != null) { + return setter; + } } + return null; + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/tools/EscapeTool.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/tools/EscapeTool.java index 348383186..9e610f819 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/tools/EscapeTool.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/tools/EscapeTool.java @@ -24,30 +24,32 @@ /** *

- * Tool for working with escaping in Velocity templates. It provides methods to escape outputs for Velocity, Java, + * Tool for working with escaping in Velocity templates. It provides methods to escape outputs for + * Velocity, Java, * JavaScript, HTML, XML and SQL. *

*

- * Extends the default EscapeTool from velocity-tools since the XML escape performed by it doesn't work inside HTML - * content, since {@code apos} is not a valid HTML entity name, and it always escapes non-ASCII characters, which + * Extends the default EscapeTool from velocity-tools since the XML escape performed by it doesn't + * work inside HTML + * content, since {@code apos} is not a valid HTML entity name, and it always escapes non-ASCII + * characters, which * increases the HTML length considerably, while also making the source unreadable. *

* * @version $Id$ - * * @since 2.7RC1 */ public class EscapeTool extends org.apache.velocity.tools.generic.EscapeTool { - /** - * Escapes the XML special characters in a String using numerical XML entities. - * - * @param content - * the text to escape, may be {@code null} - * - * @return a new escaped {@code String}, {@code null} if {@code null} input - */ - @Override - public String xml(Object content) { - return XMLScriptService.escape(content); - } + + /** + * Escapes the XML special characters in a String using numerical XML entities. + * + * @param content + * the text to escape, may be {@code null} + * @return a new escaped {@code String}, {@code null} if {@code null} input + */ + @Override + public String xml(Object content) { + return XMLScriptService.escape(content); + } } diff --git a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/tools/RegexTool.java b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/tools/RegexTool.java index fc80fbe89..5acf7b263 100644 --- a/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/tools/RegexTool.java +++ b/celements-xwiki-velocity/src/main/java/org/xwiki/velocity/tools/RegexTool.java @@ -26,124 +26,125 @@ import java.util.regex.PatternSyntaxException; /** - * Velocity Tool offering various Regex-based APIs to make it easy to manipulate regular expressions from Velocity. + * Velocity Tool offering various Regex-based APIs to make it easy to manipulate regular expressions + * from Velocity. * * @version $Id$ - * * @since 2.0RC2 */ public class RegexTool { - /** - * Result of a Regex search. - */ - public class RegexResult { - /** - * @see #getStart() - */ - public int start; - /** - * @see #getEnd() - */ - public int end; + /** + * Result of a Regex search. + */ + public class RegexResult { - /** - * @see #getGroup() - */ - public String group; - - /** - * @param start - * see {@link #getStart()} - * @param end - * see {@link #getEnd()} - * @param group - * see {@link #getGroup()} - */ - public RegexResult(int start, int end, String group) { - this.start = start; - this.end = end; - this.group = group; - } + /** + * @see #getStart() + */ + public int start; - /** - * @return the captured group - */ - public String getGroup() { - return this.group; - } + /** + * @see #getEnd() + */ + public int end; - /** - * @return the capture group's start position - */ - public int getStart() { - return this.start; - } + /** + * @see #getGroup() + */ + public String group; - /** - * @return the capture group's end position - */ - public int getEnd() { - return this.end; - } + /** + * @param start + * see {@link #getStart()} + * @param end + * see {@link #getEnd()} + * @param group + * see {@link #getGroup()} + */ + public RegexResult(int start, int end, String group) { + this.start = start; + this.end = end; + this.group = group; } /** - * @param content - * the content to parse - * @param regex - * the regex to look for in the passed content - * - * @return empty list if the passed regex doesn't match the content or several {@link RegexResult} objects - * containing the matched position and matched content for all capturing groups, the first group - * representing the whole . The first object is represents the entire pattern + * @return the captured group */ - public List find(String content, String regex) { - List result = new ArrayList(); - Matcher matcher = Pattern.compile(regex, Pattern.MULTILINE).matcher(content); - if (matcher.find()) { - for (int i = 0; i < matcher.groupCount() + 1; i++) { - result.add(new RegexResult(matcher.start(i), matcher.end(i), matcher.group(i))); - } - } - return result; + public String getGroup() { + return this.group; } /** - * Compiles a regular expression into a java {@code Pattern} object. - * - * @param regex - * the textual representation of the regular expression - * - * @return the {@code Pattern} object corresponding to the regular expression, or {@code null} if the expression is - * invalid - * - * @since 2.3M1 + * @return the capture group's start position */ - public Pattern compile(String regex) { - try { - return Pattern.compile(regex); - } catch (PatternSyntaxException ex) { - return null; - } + public int getStart() { + return this.start; } /** - * Returns a literal pattern String for the specified String. - *

- * This method produces a String that can be used to create a Pattern that would match the - * string s as if it were a literal pattern. - *

- * Metacharacters or escape sequences in the input sequence will be given no special meaning. - * - * @param s - * The string to be literalized - * - * @return A literal string replacement - * - * @since 2.4M2 + * @return the capture group's end position */ - public String quote(String s) { - return Pattern.quote(s); + public int getEnd() { + return this.end; + } + } + + /** + * @param content + * the content to parse + * @param regex + * the regex to look for in the passed content + * @return empty list if the passed regex doesn't match the content or several {@link RegexResult} + * objects + * containing the matched position and matched content for all capturing groups, the first + * group + * representing the whole . The first object is represents the entire pattern + */ + public List find(String content, String regex) { + List result = new ArrayList(); + Matcher matcher = Pattern.compile(regex, Pattern.MULTILINE).matcher(content); + if (matcher.find()) { + for (int i = 0; i < matcher.groupCount() + 1; i++) { + result.add(new RegexResult(matcher.start(i), matcher.end(i), matcher.group(i))); + } + } + return result; + } + + /** + * Compiles a regular expression into a java {@code Pattern} object. + * + * @param regex + * the textual representation of the regular expression + * @return the {@code Pattern} object corresponding to the regular expression, or {@code null} if + * the expression is + * invalid + * @since 2.3M1 + */ + public Pattern compile(String regex) { + try { + return Pattern.compile(regex); + } catch (PatternSyntaxException ex) { + return null; } + } + + /** + * Returns a literal pattern String for the specified String. + *

+ * This method produces a String that can be used to create a Pattern + * that would match the + * string s as if it were a literal pattern. + *

+ * Metacharacters or escape sequences in the input sequence will be given no special meaning. + * + * @param s + * The string to be literalized + * @return A literal string replacement + * @since 2.4M2 + */ + public String quote(String s) { + return Pattern.quote(s); + } } diff --git a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityConfigurationTest.java b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityConfigurationTest.java index 5cf99c24c..30f403e55 100644 --- a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityConfigurationTest.java +++ b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityConfigurationTest.java @@ -37,48 +37,52 @@ * Unit tests for {@link DefaultVelocityConfiguration}. * * @version $Id$ - * * @since 2.4RC1 */ public class DefaultVelocityConfigurationTest extends AbstractMockingComponentTestCase { - @MockingRequirement - private DefaultVelocityConfiguration configuration; - /** - * @see org.xwiki.test.AbstractMockingComponentTestCase#configure() - */ - public void configure() throws Exception { - final ConfigurationSource source = getComponentManager().lookup(ConfigurationSource.class); - getMockery().checking(new Expectations() { - { - allowing(source).getProperty("velocity.tools", Properties.class); - will(returnValue(Collections.emptyMap())); - allowing(source).getProperty("velocity.properties", Properties.class); - will(returnValue(Collections.emptyMap())); - } - }); - } + @MockingRequirement + private DefaultVelocityConfiguration configuration; + + /** + * @see org.xwiki.test.AbstractMockingComponentTestCase#configure() + */ + public void configure() throws Exception { + final ConfigurationSource source = getComponentManager().lookup(ConfigurationSource.class); + getMockery().checking(new Expectations() { + + { + allowing(source).getProperty("velocity.tools", Properties.class); + will(returnValue(Collections.emptyMap())); + allowing(source).getProperty("velocity.properties", Properties.class); + will(returnValue(Collections.emptyMap())); + } + }); + } - @Test - public void testDefaultToolsPresent() throws Exception { - // Verify for example that the List tool is present. - Assert.assertEquals(ListTool.class.getName(), this.configuration.getTools().get("listtool")); - } + @Test + public void testDefaultToolsPresent() throws Exception { + // Verify for example that the List tool is present. + Assert.assertEquals(ListTool.class.getName(), this.configuration.getTools().get("listtool")); + } - @Test - public void testDefaultPropertiesPresent() throws Exception { - // Verify that the secure uberspector is set by default - Assert.assertEquals(ChainingUberspector.class.getName(), - this.configuration.getProperties().getProperty("runtime.introspector.uberspect")); - Assert.assertEquals(SecureUberspector.class.getName() + "," + DeprecatedCheckUberspector.class.getName(), - this.configuration.getProperties().getProperty("runtime.introspector.uberspect.chainClasses")); + @Test + public void testDefaultPropertiesPresent() throws Exception { + // Verify that the secure uberspector is set by default + Assert.assertEquals(ChainingUberspector.class.getName(), + this.configuration.getProperties().getProperty("runtime.introspector.uberspect")); + Assert.assertEquals( + SecureUberspector.class.getName() + "," + DeprecatedCheckUberspector.class.getName(), + this.configuration.getProperties() + .getProperty("runtime.introspector.uberspect.chainClasses")); - // Verify that null values are allowed by default - Assert.assertEquals(Boolean.TRUE.toString(), - this.configuration.getProperties().getProperty("directive.set.null.allowed")); + // Verify that null values are allowed by default + Assert.assertEquals(Boolean.TRUE.toString(), + this.configuration.getProperties().getProperty("directive.set.null.allowed")); - // Verify that Macros are isolated by default - Assert.assertEquals(Boolean.TRUE.toString(), - this.configuration.getProperties().getProperty("velocimacro.permissions.allow.inline.local.scope")); - } + // Verify that Macros are isolated by default + Assert.assertEquals(Boolean.TRUE.toString(), + this.configuration.getProperties() + .getProperty("velocimacro.permissions.allow.inline.local.scope")); + } } diff --git a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityContextFactoryTest.java b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityContextFactoryTest.java index 484faa32c..ba9efaa0a 100644 --- a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityContextFactoryTest.java +++ b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityContextFactoryTest.java @@ -39,49 +39,57 @@ * @version $Id$ */ public class DefaultVelocityContextFactoryTest extends AbstractMockingComponentTestCase { - @MockingRequirement - private DefaultVelocityContextFactory factory; - /** - * @see org.xwiki.test.AbstractMockingComponentTestCase#configure() - */ - public void configure() throws Exception { - final VelocityConfiguration configuration = getComponentManager().lookup(VelocityConfiguration.class); - final Properties properties = new Properties(); - properties.put("listtool", ListTool.class.getName()); - getMockery().checking(new Expectations() { - { - allowing(configuration).getTools(); - will(returnValue(properties)); - } - }); - } + @MockingRequirement + private DefaultVelocityContextFactory factory; - /** - * Verify that we get different contexts when we call the createContext method but that they contain the same - * references to the Velocity tools. Also tests that objects we put in one context are not shared with other - * contexts. Also verifies that Velocity Context Initializers are called. - */ - @Test - public void testCreateDifferentContext() throws Exception { - // We also verify that the VelocityContextInitializers are called. - final VelocityContextInitializer mockInitializer = getMockery().mock(VelocityContextInitializer.class); - final ComponentManager mockComponentManager = getComponentManager().lookup(ComponentManager.class); - getMockery().checking(new Expectations() { - { - exactly(2).of(mockInitializer).initialize(with(any(VelocityContext.class))); - exactly(2).of(mockComponentManager).lookupList(VelocityContextInitializer.class); - will(returnValue(Arrays.asList(mockInitializer))); - } - }); + /** + * @see org.xwiki.test.AbstractMockingComponentTestCase#configure() + */ + public void configure() throws Exception { + final VelocityConfiguration configuration = getComponentManager() + .lookup(VelocityConfiguration.class); + final Properties properties = new Properties(); + properties.put("listtool", ListTool.class.getName()); + getMockery().checking(new Expectations() { - VelocityContext context1 = this.factory.createContext(); - context1.put("param", "value"); - VelocityContext context2 = this.factory.createContext(); + { + allowing(configuration).getTools(); + will(returnValue(properties)); + } + }); + } - Assert.assertNotSame(context1, context2); - Assert.assertNotNull(context1.get("listtool")); - Assert.assertSame(context2.get("listtool"), context1.get("listtool")); - Assert.assertNull(context2.get("param")); - } + /** + * Verify that we get different contexts when we call the createContext method but that they + * contain the same + * references to the Velocity tools. Also tests that objects we put in one context are not shared + * with other + * contexts. Also verifies that Velocity Context Initializers are called. + */ + @Test + public void testCreateDifferentContext() throws Exception { + // We also verify that the VelocityContextInitializers are called. + final VelocityContextInitializer mockInitializer = getMockery() + .mock(VelocityContextInitializer.class); + final ComponentManager mockComponentManager = getComponentManager() + .lookup(ComponentManager.class); + getMockery().checking(new Expectations() { + + { + exactly(2).of(mockInitializer).initialize(with(any(VelocityContext.class))); + exactly(2).of(mockComponentManager).lookupList(VelocityContextInitializer.class); + will(returnValue(Arrays.asList(mockInitializer))); + } + }); + + VelocityContext context1 = this.factory.createContext(); + context1.put("param", "value"); + VelocityContext context2 = this.factory.createContext(); + + Assert.assertNotSame(context1, context2); + Assert.assertNotNull(context1.get("listtool")); + Assert.assertSame(context2.get("listtool"), context1.get("listtool")); + Assert.assertNull(context2.get("param")); + } } diff --git a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityEngineTest.java b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityEngineTest.java index b518d3ba0..4bcacb9c9 100644 --- a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityEngineTest.java +++ b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/DefaultVelocityEngineTest.java @@ -41,111 +41,115 @@ * Unit tests for {@link DefaultVelocityEngine}. */ public class DefaultVelocityEngineTest extends AbstractMockingComponentTestCase { - @MockingRequirement - private DefaultVelocityEngine engine; - @Override - public void configure() throws Exception { - final Properties properties = new Properties(); - properties.put("runtime.introspector.uberspect", ChainingUberspector.class.getName()); - properties.put("runtime.introspector.uberspect.chainClasses", - SecureUberspector.class.getName() + "," + DeprecatedCheckUberspector.class.getName()); - properties.put("directive.set.null.allowed", Boolean.TRUE.toString()); - properties.put("velocimacro.permissions.allow.inline.local.scope", Boolean.TRUE.toString()); + @MockingRequirement + private DefaultVelocityEngine engine; - final VelocityConfiguration configuration = getComponentManager().lookup(VelocityConfiguration.class); - getMockery().checking(new Expectations() { - { - oneOf(configuration).getProperties(); - will(returnValue(properties)); - } - }); - } + @Override + public void configure() throws Exception { + final Properties properties = new Properties(); + properties.put("runtime.introspector.uberspect", ChainingUberspector.class.getName()); + properties.put("runtime.introspector.uberspect.chainClasses", + SecureUberspector.class.getName() + "," + DeprecatedCheckUberspector.class.getName()); + properties.put("directive.set.null.allowed", Boolean.TRUE.toString()); + properties.put("velocimacro.permissions.allow.inline.local.scope", Boolean.TRUE.toString()); - @Test - public void testEvaluateReader() throws Exception { - this.engine.initialize(new Properties()); - StringWriter writer = new StringWriter(); - this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo='hello')$foo World")); - Assert.assertEquals("hello World", writer.toString()); - } + final VelocityConfiguration configuration = getComponentManager() + .lookup(VelocityConfiguration.class); + getMockery().checking(new Expectations() { - @Test - public void testEvaluateString() throws Exception { - this.engine.initialize(new Properties()); - StringWriter writer = new StringWriter(); - this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - "#set($foo='hello')$foo World"); - Assert.assertEquals("hello World", writer.toString()); - } + { + oneOf(configuration).getProperties(); + will(returnValue(properties)); + } + }); + } - /** - * Verify that the default configuration doesn't allow calling Class.forName. - */ - @Test - public void testSecureUberspectorActiveByDefault() throws Exception { - this.engine.initialize(new Properties()); - StringWriter writer = new StringWriter(); - this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - "#set($foo = 'test')#set($object = $foo.class.forName('java.util.ArrayList')" - + ".newInstance())$object.size()"); - Assert.assertEquals("$object.size()", writer.toString()); - } + @Test + public void testEvaluateReader() throws Exception { + this.engine.initialize(new Properties()); + StringWriter writer = new StringWriter(); + this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader("#set($foo='hello')$foo World")); + Assert.assertEquals("hello World", writer.toString()); + } - /** - * Verify that the default configuration allows #setting existing variables to null. - */ - @Test - public void testSettingNullAllowedByDefault() throws Exception { - this.engine.initialize(new Properties()); - StringWriter writer = new StringWriter(); - Context context = new org.apache.velocity.VelocityContext(); - context.put("null", null); - List list = new ArrayList(); - list.add("1"); - list.add(null); - list.add("3"); - context.put("list", list); - this.engine.evaluate(context, writer, "mytemplate", "#set($foo = true)${foo}#set($foo = $null)${foo}\n" - + "#foreach($i in $list)${velocityCount}=$!{i} #end"); - Assert.assertEquals("true${foo}\n1=1 2= 3=3 ", writer.toString()); - } + @Test + public void testEvaluateString() throws Exception { + this.engine.initialize(new Properties()); + StringWriter writer = new StringWriter(); + this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + "#set($foo='hello')$foo World"); + Assert.assertEquals("hello World", writer.toString()); + } - @Test - public void testOverrideConfiguration() throws Exception { - // For example try setting a non secure Uberspector. - Properties properties = new Properties(); - properties.setProperty("runtime.introspector.uberspect", - "org.apache.velocity.util.introspection.UberspectImpl"); - this.engine.initialize(properties); - StringWriter writer = new StringWriter(); - this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - "#set($foo = 'test')#set($object = $foo.class.forName('java.util.ArrayList')" - + ".newInstance())$object.size()"); - Assert.assertEquals("0", writer.toString()); - } + /** + * Verify that the default configuration doesn't allow calling Class.forName. + */ + @Test + public void testSecureUberspectorActiveByDefault() throws Exception { + this.engine.initialize(new Properties()); + StringWriter writer = new StringWriter(); + this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + "#set($foo = 'test')#set($object = $foo.class.forName('java.util.ArrayList')" + + ".newInstance())$object.size()"); + Assert.assertEquals("$object.size()", writer.toString()); + } - @Test - public void testMacroIsolation() throws Exception { - this.engine.initialize(new Properties()); - Context context = new org.apache.velocity.VelocityContext(); - this.engine.evaluate(context, new StringWriter(), "template1", "#macro(mymacro)test#end"); - StringWriter writer = new StringWriter(); - this.engine.evaluate(context, writer, "template2", "#mymacro"); - Assert.assertEquals("#mymacro", writer.toString()); - } + /** + * Verify that the default configuration allows #setting existing variables to null. + */ + @Test + public void testSettingNullAllowedByDefault() throws Exception { + this.engine.initialize(new Properties()); + StringWriter writer = new StringWriter(); + Context context = new org.apache.velocity.VelocityContext(); + context.put("null", null); + List list = new ArrayList(); + list.add("1"); + list.add(null); + list.add("3"); + context.put("list", list); + this.engine.evaluate(context, writer, "mytemplate", + "#set($foo = true)${foo}#set($foo = $null)${foo}\n" + + "#foreach($i in $list)${velocityCount}=$!{i} #end"); + Assert.assertEquals("true${foo}\n1=1 2= 3=3 ", writer.toString()); + } - @Test - public void testConfigureMacrosToBeGlobal() throws Exception { - Properties properties = new Properties(); - // Force macros to be global - properties.put("velocimacro.permissions.allow.inline.local.scope", "false"); - this.engine.initialize(properties); - Context context = new org.apache.velocity.VelocityContext(); - this.engine.evaluate(context, new StringWriter(), "template1", "#macro(mymacro)test#end"); - StringWriter writer = new StringWriter(); - this.engine.evaluate(context, writer, "template2", "#mymacro"); - Assert.assertEquals("test", writer.toString()); - } + @Test + public void testOverrideConfiguration() throws Exception { + // For example try setting a non secure Uberspector. + Properties properties = new Properties(); + properties.setProperty("runtime.introspector.uberspect", + "org.apache.velocity.util.introspection.UberspectImpl"); + this.engine.initialize(properties); + StringWriter writer = new StringWriter(); + this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + "#set($foo = 'test')#set($object = $foo.class.forName('java.util.ArrayList')" + + ".newInstance())$object.size()"); + Assert.assertEquals("0", writer.toString()); + } + + @Test + public void testMacroIsolation() throws Exception { + this.engine.initialize(new Properties()); + Context context = new org.apache.velocity.VelocityContext(); + this.engine.evaluate(context, new StringWriter(), "template1", "#macro(mymacro)test#end"); + StringWriter writer = new StringWriter(); + this.engine.evaluate(context, writer, "template2", "#mymacro"); + Assert.assertEquals("#mymacro", writer.toString()); + } + + @Test + public void testConfigureMacrosToBeGlobal() throws Exception { + Properties properties = new Properties(); + // Force macros to be global + properties.put("velocimacro.permissions.allow.inline.local.scope", "false"); + this.engine.initialize(properties); + Context context = new org.apache.velocity.VelocityContext(); + this.engine.evaluate(context, new StringWriter(), "template1", "#macro(mymacro)test#end"); + StringWriter writer = new StringWriter(); + this.engine.evaluate(context, writer, "template2", "#mymacro"); + Assert.assertEquals("test", writer.toString()); + } } diff --git a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngineTest.java b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngineTest.java index 751f95f3a..3a9da2c91 100644 --- a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngineTest.java +++ b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/internal/jmx/JMXVelocityEngineTest.java @@ -37,34 +37,34 @@ * Unit tests for {@link JMXVelocityEngine}. * * @version $Id$ - * * @since 2.4M2 */ public class JMXVelocityEngineTest extends AbstractComponentTestCase { - @Test - public void testGetTemplates() throws Exception { - VelocityEngine engine = getComponentManager().lookup(VelocityEngine.class); - engine.initialize(new Properties()); - JMXVelocityEngine jmxBean = new JMXVelocityEngine(engine); - TabularData data = jmxBean.getTemplates(); + @Test + public void testGetTemplates() throws Exception { + VelocityEngine engine = getComponentManager().lookup(VelocityEngine.class); + engine.initialize(new Properties()); + JMXVelocityEngine jmxBean = new JMXVelocityEngine(engine); + + TabularData data = jmxBean.getTemplates(); - Assert.assertEquals(1, data.values().size()); - CompositeData cd = ((CompositeData) data.values().iterator().next()); - Assert.assertEquals("", cd.get("templateName")); - Assert.assertEquals(0, ((String[]) cd.get("macroNames")).length); + Assert.assertEquals(1, data.values().size()); + CompositeData cd = ((CompositeData) data.values().iterator().next()); + Assert.assertEquals("", cd.get("templateName")); + Assert.assertEquals(0, ((String[]) cd.get("macroNames")).length); - StringWriter out = new StringWriter(); - engine.evaluate(new VelocityContext(), out, "testmacronamespace", "#macro(testmacro)#end"); - data = jmxBean.getTemplates(); + StringWriter out = new StringWriter(); + engine.evaluate(new VelocityContext(), out, "testmacronamespace", "#macro(testmacro)#end"); + data = jmxBean.getTemplates(); - Assert.assertEquals(2, data.values().size()); - Map retrievedData = new HashMap(); - for (CompositeData cdata : (Collection) data.values()) { - retrievedData.put((String) cdata.get("templateName"), (String[]) cdata.get("macroNames")); - } - Assert.assertEquals(0, retrievedData.get("").length); - Assert.assertEquals(1, retrievedData.get("testmacronamespace").length); - Assert.assertEquals("testmacro", retrievedData.get("testmacronamespace")[0]); + Assert.assertEquals(2, data.values().size()); + Map retrievedData = new HashMap(); + for (CompositeData cdata : (Collection) data.values()) { + retrievedData.put((String) cdata.get("templateName"), (String[]) cdata.get("macroNames")); } + Assert.assertEquals(0, retrievedData.get("").length); + Assert.assertEquals(1, retrievedData.get("testmacronamespace").length); + Assert.assertEquals("testmacro", retrievedData.get("testmacronamespace")[0]); + } } diff --git a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/ChainingUberspectorTest.java b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/ChainingUberspectorTest.java index 49baa73fc..ad73453bf 100644 --- a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/ChainingUberspectorTest.java +++ b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/ChainingUberspectorTest.java @@ -37,153 +37,172 @@ */ public class ChainingUberspectorTest extends AbstractXWikiComponentTestCase { - private DefaultVelocityEngine engine; + private DefaultVelocityEngine engine; - @Override - protected void setUp() throws Exception { - super.setUp(); - this.engine = (DefaultVelocityEngine) getComponentManager().lookup(VelocityEngine.class); - } + @Override + protected void setUp() throws Exception { + super.setUp(); + this.engine = (DefaultVelocityEngine) getComponentManager().lookup(VelocityEngine.class); + } - /* - * Tests that the uberspectors in the chain are called, and without a real uberspector no methods are found. - */ - public void testEmptyChain() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, ChainingUberspector.class.getCanonicalName()); - prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, TestingUberspector.class.getCanonicalName()); - TestingUberspector.methodCalls = 0; - engine.initialize(prop); - StringWriter writer = new StringWriter(); - engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); - assertEquals("$bar", writer.toString()); - assertEquals(1, TestingUberspector.methodCalls); - } + /* + * Tests that the uberspectors in the chain are called, and without a real uberspector no methods + * are found. + */ + public void testEmptyChain() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + ChainingUberspector.class.getCanonicalName()); + prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, + TestingUberspector.class.getCanonicalName()); + TestingUberspector.methodCalls = 0; + engine.initialize(prop); + StringWriter writer = new StringWriter(); + engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); + assertEquals("$bar", writer.toString()); + assertEquals(1, TestingUberspector.methodCalls); + } - /* - * Tests that using several uberspectors in the chain works, and methods are correctly found by the last uberspector - * in the chain. - */ - public void testBasicChaining() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, ChainingUberspector.class.getCanonicalName()); - prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, - UberspectImpl.class.getCanonicalName() + "," + TestingUberspector.class.getCanonicalName()); - TestingUberspector.methodCalls = 0; - TestingUberspector.getterCalls = 0; - engine.initialize(prop); - StringWriter writer = new StringWriter(); - engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); - assertEquals("hello", writer.toString()); - assertEquals(1, TestingUberspector.methodCalls); - assertEquals(0, TestingUberspector.getterCalls); - } + /* + * Tests that using several uberspectors in the chain works, and methods are correctly found by + * the last uberspector + * in the chain. + */ + public void testBasicChaining() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + ChainingUberspector.class.getCanonicalName()); + prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, + UberspectImpl.class.getCanonicalName() + "," + TestingUberspector.class.getCanonicalName()); + TestingUberspector.methodCalls = 0; + TestingUberspector.getterCalls = 0; + engine.initialize(prop); + StringWriter writer = new StringWriter(); + engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); + assertEquals("hello", writer.toString()); + assertEquals(1, TestingUberspector.methodCalls); + assertEquals(0, TestingUberspector.getterCalls); + } - /* - * Tests that invalid uberspectors classnames are ignored. - */ - public void testInvalidUberspectorsAreIgnored() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, ChainingUberspector.class.getCanonicalName()); - prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, - UberspectImpl.class.getCanonicalName() + "," + AbstractChainableUberspector.class.getCanonicalName() - + "," + InvalidUberspector.class.getCanonicalName() + "," - + TestingUberspector.class.getCanonicalName() + "," + Date.class.getCanonicalName()); - TestingUberspector.methodCalls = 0; - InvalidUberspector.methodCalls = 0; - engine.initialize(prop); - StringWriter writer = new StringWriter(); - engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); - assertEquals("hello", writer.toString()); - assertEquals(1, TestingUberspector.methodCalls); - assertEquals(0, InvalidUberspector.methodCalls); - } + /* + * Tests that invalid uberspectors classnames are ignored. + */ + public void testInvalidUberspectorsAreIgnored() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + ChainingUberspector.class.getCanonicalName()); + prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, + UberspectImpl.class.getCanonicalName() + "," + + AbstractChainableUberspector.class.getCanonicalName() + + "," + InvalidUberspector.class.getCanonicalName() + "," + + TestingUberspector.class.getCanonicalName() + "," + Date.class.getCanonicalName()); + TestingUberspector.methodCalls = 0; + InvalidUberspector.methodCalls = 0; + engine.initialize(prop); + StringWriter writer = new StringWriter(); + engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); + assertEquals("hello", writer.toString()); + assertEquals(1, TestingUberspector.methodCalls); + assertEquals(0, InvalidUberspector.methodCalls); + } - /* - * Tests that a non-chainable entry in the chain does not forward calls. - */ - public void testChainBreakingOnNonChainableEntry() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, ChainingUberspector.class.getCanonicalName()); - prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, - TestingUberspector.class.getCanonicalName() + "," + UberspectImpl.class.getCanonicalName()); - TestingUberspector.methodCalls = 0; - engine.initialize(prop); - StringWriter writer = new StringWriter(); - engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); - assertEquals("hello", writer.toString()); - assertEquals(0, TestingUberspector.methodCalls); - } + /* + * Tests that a non-chainable entry in the chain does not forward calls. + */ + public void testChainBreakingOnNonChainableEntry() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + ChainingUberspector.class.getCanonicalName()); + prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, + TestingUberspector.class.getCanonicalName() + "," + UberspectImpl.class.getCanonicalName()); + TestingUberspector.methodCalls = 0; + engine.initialize(prop); + StringWriter writer = new StringWriter(); + engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); + assertEquals("hello", writer.toString()); + assertEquals(0, TestingUberspector.methodCalls); + } - /* - * Checks that the default (non-secure) uberspector works and allows calling restricted methods. - */ - public void testDefaultUberspectorWorks() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, ChainingUberspector.class.getCanonicalName()); - prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, UberspectImpl.class.getCanonicalName()); - engine.initialize(prop); - StringWriter writer = new StringWriter(); - engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$bar")); - assertTrue(writer.toString().startsWith("[Ljava.lang.reflect.Constructor")); - } + /* + * Checks that the default (non-secure) uberspector works and allows calling restricted methods. + */ + public void testDefaultUberspectorWorks() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + ChainingUberspector.class.getCanonicalName()); + prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, + UberspectImpl.class.getCanonicalName()); + engine.initialize(prop); + StringWriter writer = new StringWriter(); + engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader( + "#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$bar")); + assertTrue(writer.toString().startsWith("[Ljava.lang.reflect.Constructor")); + } - /* - * Checks that the secure uberspector works and does not allow calling restricted methods. - */ - public void testSecureUberspectorWorks() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, ChainingUberspector.class.getCanonicalName()); - prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, SecureUberspector.class.getCanonicalName()); - engine.initialize(prop); - StringWriter writer = new StringWriter(); - engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$foo$bar")); - assertEquals("hello$bar", writer.toString()); - } + /* + * Checks that the secure uberspector works and does not allow calling restricted methods. + */ + public void testSecureUberspectorWorks() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + ChainingUberspector.class.getCanonicalName()); + prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, + SecureUberspector.class.getCanonicalName()); + engine.initialize(prop); + StringWriter writer = new StringWriter(); + engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader( + "#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$foo$bar")); + assertEquals("hello$bar", writer.toString()); + } - /* - * Checks that when the chain property is not configured, by default the secure ubespector is used. - */ - public void testSecureUberspectorEnabledByDefault() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, ChainingUberspector.class.getCanonicalName()); - prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, ""); - engine.initialize(prop); - StringWriter writer = new StringWriter(); - engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$foo$bar")); - assertEquals("hello$bar", writer.toString()); - } + /* + * Checks that when the chain property is not configured, by default the secure ubespector is + * used. + */ + public void testSecureUberspectorEnabledByDefault() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + ChainingUberspector.class.getCanonicalName()); + prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, ""); + engine.initialize(prop); + StringWriter writer = new StringWriter(); + engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader( + "#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$foo$bar")); + assertEquals("hello$bar", writer.toString()); + } - /* - * Checks that the deprecated check uberspector works. - */ - @SuppressWarnings("deprecation") - public void testDeprecatedUberspector() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, ChainingUberspector.class.getCanonicalName()); - prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, - UberspectImpl.class.getCanonicalName() + "," + TestingUberspector.class.getCanonicalName() + "," - + DeprecatedCheckUberspector.class.getCanonicalName()); - TestingUberspector.methodCalls = 0; - TestingUberspector.getterCalls = 0; - engine.initialize(prop); - StringWriter writer = new StringWriter(); - VelocityContext context = new org.apache.velocity.VelocityContext(); - Date d = new Date(); - context.put("date", d); + /* + * Checks that the deprecated check uberspector works. + */ + @SuppressWarnings("deprecation") + public void testDeprecatedUberspector() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + ChainingUberspector.class.getCanonicalName()); + prop.setProperty(ChainingUberspector.UBERSPECT_CHAIN_CLASSNAMES, + UberspectImpl.class.getCanonicalName() + "," + TestingUberspector.class.getCanonicalName() + + "," + + DeprecatedCheckUberspector.class.getCanonicalName()); + TestingUberspector.methodCalls = 0; + TestingUberspector.getterCalls = 0; + engine.initialize(prop); + StringWriter writer = new StringWriter(); + VelocityContext context = new org.apache.velocity.VelocityContext(); + Date d = new Date(); + context.put("date", d); - engine.evaluate(context, writer, "mytemplate", - new StringReader("#set($foo = $date.getYear())$foo $date.month")); + engine.evaluate(context, writer, "mytemplate", + new StringReader("#set($foo = $date.getYear())$foo $date.month")); - assertEquals(d.getYear() + " " + d.getMonth(), writer.toString()); - assertEquals(1, TestingUberspector.methodCalls); - assertEquals(1, TestingUberspector.getterCalls); - } + assertEquals(d.getYear() + " " + d.getMonth(), writer.toString()); + assertEquals(1, TestingUberspector.methodCalls); + assertEquals(1, TestingUberspector.getterCalls); + } } diff --git a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/InvalidUberspector.java b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/InvalidUberspector.java index 11632ef43..3eb6cb652 100644 --- a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/InvalidUberspector.java +++ b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/InvalidUberspector.java @@ -4,14 +4,16 @@ import org.apache.velocity.util.introspection.VelMethod; public class InvalidUberspector extends AbstractChainableUberspector { - public static int methodCalls = 0; - private InvalidUberspector() { - // This is private to ensure that it cannot be instatiated. Nothing to do here. - } + public static int methodCalls = 0; - public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) throws Exception { - ++methodCalls; - return super.getMethod(obj, methodName, args, i); - } + private InvalidUberspector() { + // This is private to ensure that it cannot be instatiated. Nothing to do here. + } + + public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) + throws Exception { + ++methodCalls; + return super.getMethod(obj, methodName, args, i); + } } diff --git a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/LinkingUberspectorTest.java b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/LinkingUberspectorTest.java index e4e8e3e35..227a4cd95 100644 --- a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/LinkingUberspectorTest.java +++ b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/LinkingUberspectorTest.java @@ -35,111 +35,131 @@ * Unit tests for {@link LinkingUberspector}. */ public class LinkingUberspectorTest extends AbstractXWikiComponentTestCase { - private VelocityEngine engine; - @Override - protected void setUp() throws Exception { - super.setUp(); - this.engine = (VelocityEngine) getComponentManager().lookup(VelocityEngine.class); - } + private VelocityEngine engine; - /* - * Tests that the uberspectors in the list are called, and without a real uberspector no methods are found. - */ - public void testEmptyArray() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, LinkingUberspector.class.getCanonicalName()); - prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, TestingUberspector.class.getCanonicalName()); - TestingUberspector.methodCalls = 0; - this.engine.initialize(prop); - StringWriter writer = new StringWriter(); - this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); - assertEquals("$bar", writer.toString()); - assertEquals(1, TestingUberspector.methodCalls); - } + @Override + protected void setUp() throws Exception { + super.setUp(); + this.engine = (VelocityEngine) getComponentManager().lookup(VelocityEngine.class); + } - /* - * Tests that using several uberspectors in the array works, methods are correctly found by a valid uberspector in - * the chain, and after a method is found no further calls are performed. - */ - public void testBasicArray() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, LinkingUberspector.class.getCanonicalName()); - prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, - TestingUberspector.class.getCanonicalName() + "," + TestingUberspector.class.getCanonicalName() + "," - + UberspectImpl.class.getCanonicalName() + "," + TestingUberspector.class.getCanonicalName()); - TestingUberspector.methodCalls = 0; - TestingUberspector.getterCalls = 0; - this.engine.initialize(prop); - StringWriter writer = new StringWriter(); - this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); - assertEquals("hello", writer.toString()); - assertEquals(2, TestingUberspector.methodCalls); - assertEquals(0, TestingUberspector.getterCalls); - } + /* + * Tests that the uberspectors in the list are called, and without a real uberspector no methods + * are found. + */ + public void testEmptyArray() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + LinkingUberspector.class.getCanonicalName()); + prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, + TestingUberspector.class.getCanonicalName()); + TestingUberspector.methodCalls = 0; + this.engine.initialize(prop); + StringWriter writer = new StringWriter(); + this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); + assertEquals("$bar", writer.toString()); + assertEquals(1, TestingUberspector.methodCalls); + } - /* - * Tests that invalid uberspectors classnames are ignored. - */ - public void testInvalidUberspectorsAreIgnored() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, LinkingUberspector.class.getCanonicalName()); - prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, - Date.class.getCanonicalName() + "," + AbstractChainableUberspector.class.getCanonicalName() + "," - + InvalidUberspector.class.getCanonicalName() + "," - + TestingUberspector.class.getCanonicalName() + "," + UberspectImpl.class.getCanonicalName()); - TestingUberspector.methodCalls = 0; - InvalidUberspector.methodCalls = 0; - this.engine.initialize(prop); - StringWriter writer = new StringWriter(); - this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); - assertEquals("hello", writer.toString()); - assertEquals(1, TestingUberspector.methodCalls); - assertEquals(0, InvalidUberspector.methodCalls); - } + /* + * Tests that using several uberspectors in the array works, methods are correctly found by a + * valid uberspector in + * the chain, and after a method is found no further calls are performed. + */ + public void testBasicArray() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + LinkingUberspector.class.getCanonicalName()); + prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, + TestingUberspector.class.getCanonicalName() + "," + + TestingUberspector.class.getCanonicalName() + "," + + UberspectImpl.class.getCanonicalName() + "," + + TestingUberspector.class.getCanonicalName()); + TestingUberspector.methodCalls = 0; + TestingUberspector.getterCalls = 0; + this.engine.initialize(prop); + StringWriter writer = new StringWriter(); + this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); + assertEquals("hello", writer.toString()); + assertEquals(2, TestingUberspector.methodCalls); + assertEquals(0, TestingUberspector.getterCalls); + } - /* - * Checks that the default (non-secure) uberspector works and allows calling restricted methods. - */ - public void testDefaultUberspectorWorks() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, LinkingUberspector.class.getCanonicalName()); - prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, UberspectImpl.class.getCanonicalName()); - this.engine.initialize(prop); - StringWriter writer = new StringWriter(); - this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$bar")); - assertTrue(writer.toString().startsWith("[Ljava.lang.reflect.Constructor")); - } + /* + * Tests that invalid uberspectors classnames are ignored. + */ + public void testInvalidUberspectorsAreIgnored() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + LinkingUberspector.class.getCanonicalName()); + prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, + Date.class.getCanonicalName() + "," + AbstractChainableUberspector.class.getCanonicalName() + + "," + + InvalidUberspector.class.getCanonicalName() + "," + + TestingUberspector.class.getCanonicalName() + "," + + UberspectImpl.class.getCanonicalName()); + TestingUberspector.methodCalls = 0; + InvalidUberspector.methodCalls = 0; + this.engine.initialize(prop); + StringWriter writer = new StringWriter(); + this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader("#set($foo = 'hello')#set($bar = $foo.toString())$bar")); + assertEquals("hello", writer.toString()); + assertEquals(1, TestingUberspector.methodCalls); + assertEquals(0, InvalidUberspector.methodCalls); + } - /* - * Checks that the secure uberspector works and does not allow calling restricted methods. - */ - public void testSecureUberspectorWorks() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, LinkingUberspector.class.getCanonicalName()); - prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, SecureUberspector.class.getCanonicalName()); - this.engine.initialize(prop); - StringWriter writer = new StringWriter(); - this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$foo$bar")); - assertEquals("hello$bar", writer.toString()); - } + /* + * Checks that the default (non-secure) uberspector works and allows calling restricted methods. + */ + public void testDefaultUberspectorWorks() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + LinkingUberspector.class.getCanonicalName()); + prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, + UberspectImpl.class.getCanonicalName()); + this.engine.initialize(prop); + StringWriter writer = new StringWriter(); + this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader( + "#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$bar")); + assertTrue(writer.toString().startsWith("[Ljava.lang.reflect.Constructor")); + } - /* - * Checks that when the array property is not configured, by default the secure ubespector is used. - */ - public void testSecureUberspectorEnabledByDefault() throws Exception { - Properties prop = new Properties(); - prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, LinkingUberspector.class.getCanonicalName()); - prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, ""); - this.engine.initialize(prop); - StringWriter writer = new StringWriter(); - this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", - new StringReader("#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$foo$bar")); - assertEquals("hello$bar", writer.toString()); - } + /* + * Checks that the secure uberspector works and does not allow calling restricted methods. + */ + public void testSecureUberspectorWorks() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + LinkingUberspector.class.getCanonicalName()); + prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, + SecureUberspector.class.getCanonicalName()); + this.engine.initialize(prop); + StringWriter writer = new StringWriter(); + this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader( + "#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$foo$bar")); + assertEquals("hello$bar", writer.toString()); + } + + /* + * Checks that when the array property is not configured, by default the secure ubespector is + * used. + */ + public void testSecureUberspectorEnabledByDefault() throws Exception { + Properties prop = new Properties(); + prop.setProperty(RuntimeConstants.UBERSPECT_CLASSNAME, + LinkingUberspector.class.getCanonicalName()); + prop.setProperty(LinkingUberspector.UBERSPECT_ARRAY_CLASSNAMES, ""); + this.engine.initialize(prop); + StringWriter writer = new StringWriter(); + this.engine.evaluate(new org.apache.velocity.VelocityContext(), writer, "mytemplate", + new StringReader( + "#set($foo = 'hello')" + "#set($bar = $foo.getClass().getConstructors())$foo$bar")); + assertEquals("hello$bar", writer.toString()); + } } diff --git a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/TestingUberspector.java b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/TestingUberspector.java index 3434a8327..13159a440 100644 --- a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/TestingUberspector.java +++ b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/introspection/TestingUberspector.java @@ -6,17 +6,19 @@ import org.xwiki.velocity.introspection.AbstractChainableUberspector; public class TestingUberspector extends AbstractChainableUberspector { - public static int methodCalls = 0; - public static int getterCalls = 0; + public static int methodCalls = 0; - public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) throws Exception { - ++methodCalls; - return super.getMethod(obj, methodName, args, i); - } + public static int getterCalls = 0; - public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception { - ++getterCalls; - return super.getPropertyGet(obj, identifier, i); - } + public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) + throws Exception { + ++methodCalls; + return super.getMethod(obj, methodName, args, i); + } + + public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception { + ++getterCalls; + return super.getPropertyGet(obj, identifier, i); + } } diff --git a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/tools/EscapeToolTest.java b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/tools/EscapeToolTest.java index b0e9fd1ed..b394243f1 100644 --- a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/tools/EscapeToolTest.java +++ b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/tools/EscapeToolTest.java @@ -27,40 +27,41 @@ * Unit tests for {@link EscapeTool}. * * @version $Id$ - * * @since 2.7RC1 */ public class EscapeToolTest { - @Test - public void testEscapeSimpleXML() { - EscapeTool tool = new EscapeTool(); - String escapedText = tool.xml("a < a' && a' < a\" => a < a\""); - Assert.assertFalse("Failed to escape <", escapedText.contains("<")); - Assert.assertFalse("Failed to escape >", escapedText.contains(">")); - Assert.assertFalse("Failed to escape '", escapedText.contains("'")); - Assert.assertFalse("Failed to escape \"", escapedText.contains("\"")); - Assert.assertFalse("Failed to escape &", escapedText.contains("&&")); - } + @Test + public void testEscapeSimpleXML() { + EscapeTool tool = new EscapeTool(); + String escapedText = tool.xml("a < a' && a' < a\" => a < a\""); + + Assert.assertFalse("Failed to escape <", escapedText.contains("<")); + Assert.assertFalse("Failed to escape >", escapedText.contains(">")); + Assert.assertFalse("Failed to escape '", escapedText.contains("'")); + Assert.assertFalse("Failed to escape \"", escapedText.contains("\"")); + Assert.assertFalse("Failed to escape &", escapedText.contains("&&")); + } - @Test - public void testEscapeXMLApos() { - EscapeTool tool = new EscapeTool(); + @Test + public void testEscapeXMLApos() { + EscapeTool tool = new EscapeTool(); - Assert.assertFalse("' wrongly escaped to non-HTML '", tool.xml("'").equals("'")); - } + Assert.assertFalse("' wrongly escaped to non-HTML '", tool.xml("'").equals("'")); + } - @Test - public void testEscapeXMLWithNull() { - EscapeTool tool = new EscapeTool(); + @Test + public void testEscapeXMLWithNull() { + EscapeTool tool = new EscapeTool(); - Assert.assertNull("null should be null", tool.xml(null)); - } + Assert.assertNull("null should be null", tool.xml(null)); + } - @Test - public void testEscapeXMLNonAscii() { - EscapeTool tool = new EscapeTool(); + @Test + public void testEscapeXMLNonAscii() { + EscapeTool tool = new EscapeTool(); - Assert.assertTrue("Non-ASCII characters shouldn't be escaped", tool.xml("\u0123").equals("\u0123")); - } + Assert.assertTrue("Non-ASCII characters shouldn't be escaped", + tool.xml("\u0123").equals("\u0123")); + } } diff --git a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/tools/RegexToolTest.java b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/tools/RegexToolTest.java index 283402bc0..5d62e1b83 100644 --- a/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/tools/RegexToolTest.java +++ b/celements-xwiki-velocity/src/test/java/org/xwiki/velocity/tools/RegexToolTest.java @@ -31,75 +31,75 @@ * Unit tests for {@link RegexTool}. * * @version $Id$ - * * @since 2.0RC1 */ public class RegexToolTest { - @Test - public void testFind() { - RegexTool tool = new RegexTool(); - List result = tool.find("

header

whatever", - "<[hH][12].*?>(.*?)"); - Assert.assertEquals(2, result.size()); - Assert.assertEquals("

header

", result.get(0).getGroup()); - Assert.assertEquals("header", result.get(1).getGroup()); - } + @Test + public void testFind() { + RegexTool tool = new RegexTool(); + List result = tool.find("

header

whatever", + "<[hH][12].*?>(.*?)"); + + Assert.assertEquals(2, result.size()); + Assert.assertEquals("

header

", result.get(0).getGroup()); + Assert.assertEquals("header", result.get(1).getGroup()); + } - /** - * Compiling a valid regular expression should work. - */ - @Test - public void testCompileValidRegex() { - RegexTool tool = new RegexTool(); - Pattern p = tool.compile("ab?"); - Assert.assertNotNull(p); - // Try to check that the right regular expression was parsed. - Matcher m = p.matcher("xyz"); - Assert.assertFalse(m.matches()); - m = p.matcher("a"); - Assert.assertTrue(m.matches()); - m = p.matcher("aba"); - Assert.assertFalse(m.matches()); - m.reset(); - Assert.assertTrue(m.find() && m.find() && m.hitEnd()); - } + /** + * Compiling a valid regular expression should work. + */ + @Test + public void testCompileValidRegex() { + RegexTool tool = new RegexTool(); + Pattern p = tool.compile("ab?"); + Assert.assertNotNull(p); + // Try to check that the right regular expression was parsed. + Matcher m = p.matcher("xyz"); + Assert.assertFalse(m.matches()); + m = p.matcher("a"); + Assert.assertTrue(m.matches()); + m = p.matcher("aba"); + Assert.assertFalse(m.matches()); + m.reset(); + Assert.assertTrue(m.find() && m.find() && m.hitEnd()); + } - /** - * Compiling a valid regular expression with internal flags should work. - */ - @Test - public void testCompileRegexWithFlags() { - RegexTool tool = new RegexTool(); - Pattern p = tool.compile("(?im)^ab?$"); - Assert.assertNotNull(p); - // Try to check that the right regular expression was parsed. - Matcher m = p.matcher("xyz"); - Assert.assertFalse(m.matches()); - m = p.matcher("A"); - Assert.assertTrue(m.matches()); - m = p.matcher("ab\na"); - Assert.assertFalse(m.matches()); - m.reset(); - Assert.assertTrue(m.find() && m.find() && m.hitEnd()); - } + /** + * Compiling a valid regular expression with internal flags should work. + */ + @Test + public void testCompileRegexWithFlags() { + RegexTool tool = new RegexTool(); + Pattern p = tool.compile("(?im)^ab?$"); + Assert.assertNotNull(p); + // Try to check that the right regular expression was parsed. + Matcher m = p.matcher("xyz"); + Assert.assertFalse(m.matches()); + m = p.matcher("A"); + Assert.assertTrue(m.matches()); + m = p.matcher("ab\na"); + Assert.assertFalse(m.matches()); + m.reset(); + Assert.assertTrue(m.find() && m.find() && m.hitEnd()); + } - /** - * Compiling an invalid regular expression should return null, and not throw an exception. - */ - @Test - public void testCompileInvalidRegex() { - RegexTool tool = new RegexTool(); - Pattern p = tool.compile("*"); - Assert.assertNull(p); - } + /** + * Compiling an invalid regular expression should return null, and not throw an exception. + */ + @Test + public void testCompileInvalidRegex() { + RegexTool tool = new RegexTool(); + Pattern p = tool.compile("*"); + Assert.assertNull(p); + } - /** - * Escaping a string containing regex syntax characters. - */ - @Test - public void testQuote() { - RegexTool tool = new RegexTool(); - Assert.assertEquals(Pattern.quote("^(\\)[]"), tool.quote("^(\\)[]")); - } + /** + * Escaping a string containing regex syntax characters. + */ + @Test + public void testQuote() { + RegexTool tool = new RegexTool(); + Assert.assertEquals(Pattern.quote("^(\\)[]"), tool.quote("^(\\)[]")); + } }