You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2023/01/28 19:20:04 UTC

[tapestry-5] branch better-page-invalidation updated (8dae1cce0 -> 14e2243ca)

This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a change to branch better-page-invalidation
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git


    from 8dae1cce0 TAP5-2744: first pass at page dependency graph
     new 0a5b75a59 TAP5-2744: eliminating a infinite recursion
     new 14e2243ca TAP5-2744: finished Graphviz component and PageDependencyGraph page

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../META-INF/modules/t5/core/graphviz.coffee       |  29 ++++++
 .../tapestry5/corelib/components/Graphviz.java     | 104 +++++++++++++++++++++
 .../tapestry5/corelib/pages/PageCatalog.java       |  18 +---
 .../corelib/pages/PageDependencyGraph.java         |  71 ++++++++++++++
 .../ComponentDependencyGraphvizGeneratorImpl.java  |  18 ++--
 .../apache/tapestry5/modules/DashboardModule.java  |   6 +-
 .../META-INF/assets/tapestry5/PageCatalog.js       |   9 --
 .../resources/org/apache/tapestry5/core.properties |   3 +
 .../apache/tapestry5/corelib/pages/PageCatalog.tml |   4 +-
 .../corelib/pages/PageDependencyGraph.tml          |  13 +++
 10 files changed, 240 insertions(+), 35 deletions(-)
 create mode 100644 tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/graphviz.coffee
 create mode 100644 tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Graphviz.java
 create mode 100644 tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageDependencyGraph.java
 delete mode 100644 tapestry-core/src/main/resources/META-INF/assets/tapestry5/PageCatalog.js
 create mode 100644 tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageDependencyGraph.tml


[tapestry-5] 02/02: TAP5-2744: finished Graphviz component and PageDependencyGraph page

Posted by th...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a commit to branch better-page-invalidation
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit 14e2243ca5e4fa65e7c391e09564cb1aafb57fb7
Author: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
AuthorDate: Sat Jan 28 16:19:21 2023 -0300

    TAP5-2744: finished Graphviz component and PageDependencyGraph page
---
 .../META-INF/modules/t5/core/graphviz.coffee       |  29 ++++++
 .../tapestry5/corelib/components/Graphviz.java     | 104 +++++++++++++++++++++
 .../tapestry5/corelib/pages/PageCatalog.java       |  18 +---
 .../corelib/pages/PageDependencyGraph.java         |  71 ++++++++++++++
 .../ComponentDependencyGraphvizGeneratorImpl.java  |   4 +-
 .../apache/tapestry5/modules/DashboardModule.java  |   6 +-
 .../META-INF/assets/tapestry5/PageCatalog.js       |   9 --
 .../resources/org/apache/tapestry5/core.properties |   3 +
 .../apache/tapestry5/corelib/pages/PageCatalog.tml |   4 +-
 .../corelib/pages/PageDependencyGraph.tml          |  13 +++
 10 files changed, 231 insertions(+), 30 deletions(-)

diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/graphviz.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/graphviz.coffee
new file mode 100644
index 000000000..e1fbe3ee2
--- /dev/null
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/graphviz.coffee
@@ -0,0 +1,29 @@
+# Copyright 2023 The Apache Software Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http:#www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# ## t5/core/graphviz
+#
+# Support to the core/Graphviz Tapestry component.
+define ["https://cdn.jsdelivr.net/npm/@hpcc-js/wasm/dist/graphviz.umd.js"],
+  (hpccWasm) ->
+    render = (value, id, showDownloadLink) ->
+      hpccWasm.Graphviz.load().then (graphviz) ->
+        svg = graphviz.dot value
+        div = document.getElementById id
+        layout = graphviz.layout(value, "svg", "dot")
+        div.innerHTML = layout
+        if showDownloadLink
+          link = document.getElementById (id + "-download")
+          link.setAttribute "href", "data:image/svg+xml;charset=utf-8," + encodeURIComponent(layout)
+    return render
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Graphviz.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Graphviz.java
new file mode 100644
index 000000000..8fd74f4c8
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Graphviz.java
@@ -0,0 +1,104 @@
+// Copyright 2023 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.corelib.components;
+
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.commons.Messages;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
+import org.apache.tapestry5.services.javascript.JavaScriptSupport;
+
+/**
+ * Component that renders a <a href="http://graphviz.org">Graphviz</a> graph using
+ * <a href="https://www.npmjs.com/package/@hpcc-js/wasm">@hpcc-js/wasm</a>. It's mostly 
+ * intended to be used internally at Tapestry, hence the lack of options.
+ * 
+ * @tapestrydoc
+ */
+public class Graphviz
+{
+    
+    /**
+     * A Graphviz graph described in its DOT language.
+     */
+    @Parameter(required = true, allowNull = false)
+    @Property
+    private String value;
+    
+    /**
+     * Defines whether a link to download the graph as an SVG file should be provided.
+     */
+    @Parameter(defaultPrefix = BindingConstants.LITERAL, value = "false")
+    private boolean showDownloadLink;
+
+    /**
+     * Defines whether a the Graphviz source should be shown.
+     */
+    @Parameter(defaultPrefix = BindingConstants.LITERAL, value = "false")
+    private boolean showSource;
+
+    @Environmental
+    private JavaScriptSupport javaScriptSupport;
+    
+    @Inject
+    private AjaxResponseRenderer ajaxResponseRenderer;
+    
+    @Inject
+    private ComponentResources resources;
+    
+    @Inject
+    private Messages messages;
+
+    // Read value only once if showSource = true
+    private String cachedValue;
+    
+    void setupRender(MarkupWriter writer)
+    {
+     
+        cachedValue = value;
+        String elementName = resources.getElementName();
+        if (elementName == null)
+        {
+            elementName = "div";
+        }
+        
+        final String id = javaScriptSupport.allocateClientId(resources);
+        writer.element(elementName, "id", id);
+        writer.end();
+        
+        javaScriptSupport.require("t5/core/graphviz").with(cachedValue, id, showDownloadLink);
+        
+        if (showDownloadLink)
+        {
+            writer.element("a", "href", "#", "id", id + "-download", "download", id + ".svg");
+            writer.write(messages.get("download-graphviz-image"));
+            writer.end();
+        }
+        
+        if (showSource)
+        {
+            writer.element("pre", "id", id + "-source");
+            writer.write(cachedValue);
+            writer.end();
+        }
+        
+    }
+    
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java
index 0728b6fe2..74479881d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageCatalog.java
@@ -21,11 +21,9 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
-import org.apache.tapestry5.Asset;
 import org.apache.tapestry5.MarkupWriter;
 import org.apache.tapestry5.alerts.AlertManager;
 import org.apache.tapestry5.annotations.InjectComponent;
-import org.apache.tapestry5.annotations.Path;
 import org.apache.tapestry5.annotations.Persist;
 import org.apache.tapestry5.annotations.Property;
 import org.apache.tapestry5.annotations.UnknownActivationContextCheck;
@@ -152,10 +150,6 @@ public class PageCatalog
     @Inject
     private AjaxResponseRenderer ajaxResponseRenderer;
     
-    @Inject
-    @Path("classpath:/META-INF/assets/tapestry5/PageCatalog.js")
-    private Asset pageCatalogJs;
-
     void pageLoaded()
     {
         model = beanModelSource.createDisplayModel(Page.class, messages);
@@ -372,14 +366,6 @@ public class PageCatalog
     {
         selectedPage = pageSource.getPage(pageName);
         ajaxResponseRenderer.addRender("pageStructureZone", pageStructureZone.getBody());
-        ajaxResponseRenderer.addCallback((JavaScriptSupport js) -> {
-            js.importJavaScriptLibrary(pageCatalogJs);
-            js.importJavaScriptLibrary("https://cdn.jsdelivr.net/npm/@hpcc-js/wasm/dist/graphviz.umd.js");
-            final String graphvizSource = getGraphvizSource(getSelectedPageClassName());
-            System.out.println(graphvizSource);
-            js.addScript("showGraphviz('%s', '%s');", pageName, 
-                    graphvizSource.replace("\n", " "));
-        });
     }
     
     public String getDisplayLogicalName() 
@@ -462,9 +448,9 @@ public class PageCatalog
         return resolver.getLogicalName(className);
     }
     
-    private String getGraphvizSource(String className)
+    public String getGraphvizValue()
     {
-        return componentDependencyGraphvizGenerator.generate(className);
+        return componentDependencyGraphvizGenerator.generate(getClassName(selectedPage));
     }
     
 }
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageDependencyGraph.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageDependencyGraph.java
new file mode 100644
index 000000000..134b87e2c
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PageDependencyGraph.java
@@ -0,0 +1,71 @@
+// Copyright 2023 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.corelib.pages;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.annotations.UnknownActivationContextCheck;
+import org.apache.tapestry5.annotations.WhitelistAccessOnly;
+import org.apache.tapestry5.internal.services.ComponentDependencyGraphvizGenerator;
+import org.apache.tapestry5.internal.services.PageSource;
+import org.apache.tapestry5.internal.structure.Page;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.services.ComponentClassResolver;
+import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
+
+/**
+ * Shows graph showing the dependencies of all already loaded pages and its compnoents, mixins and base classes.
+ */
+@UnknownActivationContextCheck(false)
+@WhitelistAccessOnly
+public class PageDependencyGraph
+{
+
+    @Inject
+    private ComponentClassResolver resolver;
+    
+    @Inject
+    private ComponentDependencyGraphvizGenerator componentDependencyGraphvizGenerator;
+    
+    @Inject
+    private PageSource pageSource;
+
+    @Inject
+    private ComponentClassResolver componentClassResolver;
+
+    @Inject
+    private AjaxResponseRenderer ajaxResponseRenderer;
+    
+    @Property
+    private Page page;
+    
+    private String getClassName(Page page) 
+    {
+        return page.getRootComponent().getComponentResources().getComponentModel().getComponentClassName();
+    }
+
+    public String getGraphvizValue()
+    {
+        final Set<Page> allPages = pageSource.getAllPages();
+        return componentDependencyGraphvizGenerator.generate(
+                allPages.stream()
+                    .map(this::getClassName)
+                    .collect(Collectors.toList())
+                    .toArray(new String[allPages.size()]));
+    }
+    
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyGraphvizGeneratorImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyGraphvizGeneratorImpl.java
index f53816687..81a179e46 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyGraphvizGeneratorImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyGraphvizGeneratorImpl.java
@@ -42,8 +42,8 @@ public class ComponentDependencyGraphvizGeneratorImpl implements ComponentDepend
 
         dotFile.append("\trankdir=LR;\n");
         dotFile.append("\tfontname=\"Helvetica,Arial,sans-serif\";\n");
-//      dotFile.append("\tnode [fontname=\"Helvetica,Arial,sans-serif\",fontsize=\"8pt\"];\n");
-        dotFile.append("\tedge [fontname=\"Helvetica,Arial,sans-serif\"];\n");
+        dotFile.append("\tsplines=ortho;\n\n");
+        dotFile.append("\tnode [fontname=\"Helvetica,Arial,sans-serif\",fontsize=\"10pt\"];\n");
         dotFile.append("\tnode [shape=rect];\n\n");
         
         final Set<String> allClasses = new HashSet<>();
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/DashboardModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/DashboardModule.java
index 002fea71d..c4985b510 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/DashboardModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/DashboardModule.java
@@ -1,4 +1,4 @@
-// Copyright 2013, 2014 The Apache Software Foundation
+// Copyright 2013, 2014, 2023 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,6 +15,8 @@
 package org.apache.tapestry5.modules;
 
 import org.apache.tapestry5.commons.OrderedConfiguration;
+import org.apache.tapestry5.internal.services.ComponentDependencyGraphvizGenerator;
+import org.apache.tapestry5.internal.services.ComponentDependencyGraphvizGeneratorImpl;
 import org.apache.tapestry5.internal.services.dashboard.DashboardManagerImpl;
 import org.apache.tapestry5.ioc.ServiceBinder;
 import org.apache.tapestry5.ioc.annotations.Contribute;
@@ -26,6 +28,7 @@ public class DashboardModule
     public static void bind(ServiceBinder binder)
     {
         binder.bind(DashboardManager.class, DashboardManagerImpl.class);
+        binder.bind(ComponentDependencyGraphvizGenerator.class, ComponentDependencyGraphvizGeneratorImpl.class);
     }
 
     @Contribute(DashboardManager.class)
@@ -34,5 +37,6 @@ public class DashboardModule
         configuration.add("Pages", new DashboardTab("Pages", "core/PageCatalog"));
         configuration.add("Services", new DashboardTab("Services", "core/ServiceStatus"));
         configuration.add("Libraries", new DashboardTab("ComponentLibraries", "core/ComponentLibraries"));
+        configuration.add("PageDependencyGraph", new DashboardTab("PageDependencyGraph", "core/PageDependencyGraph"));
     }
 }
diff --git a/tapestry-core/src/main/resources/META-INF/assets/tapestry5/PageCatalog.js b/tapestry-core/src/main/resources/META-INF/assets/tapestry5/PageCatalog.js
deleted file mode 100644
index c3be055a5..000000000
--- a/tapestry-core/src/main/resources/META-INF/assets/tapestry5/PageCatalog.js
+++ /dev/null
@@ -1,9 +0,0 @@
-console.log("PageCatalog.js");
-function showGraphviz(pageName, dot) {
-	var hpccWasm = require("https://cdn.jsdelivr.net/npm/@hpcc-js/wasm/dist/graphviz.umd.js");
-    hpccWasm.Graphviz.load().then(graphviz => {	        	
-		const svg = graphviz.dot(dot);
-		const div = document.getElementById(pageName + "-graphviz");
-		div.innerHTML = graphviz.layout(dot, "svg", "dot");
-	});
-};
\ No newline at end of file
diff --git a/tapestry-core/src/main/resources/org/apache/tapestry5/core.properties b/tapestry-core/src/main/resources/org/apache/tapestry5/core.properties
index 61cac585b..bda821d34 100644
--- a/tapestry-core/src/main/resources/org/apache/tapestry5/core.properties
+++ b/tapestry-core/src/main/resources/org/apache/tapestry5/core.properties
@@ -140,6 +140,9 @@ private-default-localdate-format=lll
 # see ComponentLibraries page
 not-informed=Not informed
 
+# see Graphviz
+download-graphviz-image = Download graph as SVG
+
 # OpenAPI generation
 openapi.viewer-title=OpenAPI definition viewer
 openapi-title=OpenAPI description
diff --git a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageCatalog.tml b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageCatalog.tml
index 688f8bd05..cc7ae7056 100644
--- a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageCatalog.tml
+++ b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageCatalog.tml
@@ -67,8 +67,8 @@
 	    </div>
 	    <div class="panel panel-default vert-offset" t:type="If" t:test="selectedPage">
 	        <div class="panel-heading">${selectedPage.name}'s dependency tree</div>
-<!-- 	        <pre id="${selectedPage.name}-graphviz-source">${getGraphVizSource(selectedPageClassName)}</pre> -->
-	        <div class="panel-body" id="${selectedPage.name}-graphviz">
+	        <div class="panel-body">
+	        	<t:graphviz value="graphvizValue"/>
 	        </div>
 	    </div>
 	</t:zone>	   
diff --git a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageDependencyGraph.tml b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageDependencyGraph.tml
new file mode 100644
index 000000000..21a6ec7c1
--- /dev/null
+++ b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/PageDependencyGraph.tml
@@ -0,0 +1,13 @@
+<t:block id="content" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
+         xmlns:p="tapestry:parameter">
+
+	<p>
+		This page provides a graph, generated with <a href="http://graphviz.org">Graphviz</a>
+		and <a href="https://www.npmjs.com/package/@hpcc-js/wasm">@hpcc-js/wasm</a>,
+		showing the dependencies of all already loaded
+		pages and its components, mixins and base classes.
+	</p>
+	
+	<t:Graphviz value="graphvizValue" showDownloadLink="true" showSource="true"/>
+
+</t:block>
\ No newline at end of file


[tapestry-5] 01/02: TAP5-2744: eliminating a infinite recursion

Posted by th...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a commit to branch better-page-invalidation
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit 0a5b75a599c48421516850b004414b1dd991cd56
Author: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
AuthorDate: Sat Jan 28 15:31:46 2023 -0300

    TAP5-2744: eliminating a infinite recursion
---
 .../ComponentDependencyGraphvizGeneratorImpl.java        | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyGraphvizGeneratorImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyGraphvizGeneratorImpl.java
index b8fb2bc19..f53816687 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyGraphvizGeneratorImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentDependencyGraphvizGeneratorImpl.java
@@ -39,11 +39,12 @@ public class ComponentDependencyGraphvizGeneratorImpl implements ComponentDepend
     {
         
         final StringBuilder dotFile = new StringBuilder("digraph {\n\n");
-        
+
+        dotFile.append("\trankdir=LR;\n");
         dotFile.append("\tfontname=\"Helvetica,Arial,sans-serif\";\n");
-        dotFile.append("\tnode [fontname=\"Helvetica,Arial,sans-serif\"];\n");
+//      dotFile.append("\tnode [fontname=\"Helvetica,Arial,sans-serif\",fontsize=\"8pt\"];\n");
         dotFile.append("\tedge [fontname=\"Helvetica,Arial,sans-serif\"];\n");
-        dotFile.append("\tnode [shape=box];\n\n");
+        dotFile.append("\tnode [shape=rect];\n\n");
         
         final Set<String> allClasses = new HashSet<>();
         
@@ -117,10 +118,13 @@ public class ComponentDependencyGraphvizGeneratorImpl implements ComponentDepend
 
     private void addDependencies(String className, Set<String> allClasses) 
     {
-        allClasses.add(className);
-        for (String dependency : componentDependencyRegistry.getDependencies(className))
+        if (!allClasses.contains(className))
         {
-            addDependencies(dependency, allClasses);
+            allClasses.add(className);
+            for (String dependency : componentDependencyRegistry.getDependencies(className))
+            {
+                addDependencies(dependency, allClasses);
+            }
         }
     }