Skip to content

Commit

Permalink
feat: support multiple template root paths.
Browse files Browse the repository at this point in the history
Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Oct 19, 2024
1 parent 0414d3e commit a1e10fb
Show file tree
Hide file tree
Showing 37 changed files with 1,182 additions and 210 deletions.
1 change: 1 addition & 0 deletions qute.jdt/com.redhat.qute.jdt/plugin.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
pluginName=JDT Qute Extension
providerName=Red Hat

templateRootPathProviders.name=Template Root Path Providers
dataModelProviders.name=Data model providers
resolvedJavaTypeFactoriesName=Resolved Java Type Factories
25 changes: 25 additions & 0 deletions qute.jdt/com.redhat.qute.jdt/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
<?eclipse version="3.5"?>
<plugin>

<extension-point id="templateRootPathProviders"
name="%templateRootPathProviders.name"
schema="schema/templateRootPathProviders.exsd" />
<extension-point id="dataModelProviders"
name="%dataModelProviders.name"
schema="schema/dataModelProviders.exsd" />
Expand All @@ -21,6 +24,7 @@
<command id="qute/template/javaDefinition"/>
<command id="qute/template/javadoc"/>
<command id="qute/template/generateMissingJavaMember"/>
<command id="qute/template/isInTemplate"/>
</delegateCommandHandler>
</extension>

Expand All @@ -33,6 +37,11 @@
</delegateCommandHandler>
</extension>

<!-- Template root path providers for Qute core (src/main/resources/templates) -->
<extension point="com.redhat.qute.jdt.templateRootPathProviders">
<provider class="com.redhat.qute.jdt.template.rootpath.DefaultTemplateRootPathProvider" />
</extension>

<!-- Data model providers for Qute core -->
<extension point="com.redhat.qute.jdt.dataModelProviders">
<provider class="com.redhat.qute.jdt.internal.template.datamodel.TemplateFieldSupport" />
Expand All @@ -53,6 +62,8 @@
class="com.redhat.qute.jdt.internal.extensions.quarkus.InjectNamespaceResolverSupport" />
</extension>

<!-- =========== Renarde extension =========== -->

<!-- Data model providers for Quarkus Renarde -->
<extension point="com.redhat.qute.jdt.dataModelProviders">
<provider namespaces="uri,uriabs"
Expand All @@ -66,4 +77,18 @@
<factory class="com.redhat.qute.jdt.internal.extensions.renarde.RenardeResolvedJavaTypeFactory" />
</extension>

<!-- =========== Roq extension =========== -->

<!-- Template root path providers for Roq (content, etc) -->
<extension point="com.redhat.qute.jdt.templateRootPathProviders">
<provider class="com.redhat.qute.jdt.internal.extensions.roq.RoqTemplateRootPathProvider" />
</extension>

<!-- =========== Web Bundler extension =========== -->

<!-- Template root path providers for Web Bundler (src/main/resources/web/templates/) -->
<extension point="com.redhat.qute.jdt.templateRootPathProviders">
<provider class="com.redhat.qute.jdt.internal.extensions.webbundler.WebBundlerTemplateRootPathProvider" />
</extension>

</plugin>
89 changes: 89 additions & 0 deletions qute.jdt/com.redhat.qute.jdt/schema/templateRootPathProviders.exsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="com.redhat.qute.jdt" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appinfo>
<meta.schema plugin="com.redhat.qute.jdt" id="templateRootPathProviders" name="Template Root Path Providers"/>
</appinfo>
<documentation>
This extension point allows adding a template root path providers to add new templates folder to scan.
</documentation>
</annotation>

<element name="extension">
<annotation>
<appinfo>
<meta.element />
</appinfo>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="provider"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>

</documentation>
<appinfo>
<meta.attribute translatable="true"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>

<element name="provider">
<annotation>
<documentation>
Template root path provider
</documentation>
</annotation>
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
Name of a class that implements ITemplateRootPathProvider
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":com.redhat.qute.jdt.template.rootpath.ITemplateRootPathProvider"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>


<annotation>
<appinfo>
<meta.section type="examples"/>
</appinfo>
<documentation>
The following is an example of a resolved Java Type factory extension:

&lt;pre&gt;
&lt;extension point=&quot;com.redhat.qute.jdt.resolvedJavaTypeFactories&quot;&gt;
&lt;factory class=&quot;com.redhat.qute.jdt.internal.extensions.renarde.RenardeResolvedJavaTypeFactory&quot; /&gt;
&lt;/extension&gt;
&lt;/pre&gt;
</documentation>
</annotation>




</schema>
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*******************************************************************************
* Copyright (c) 2021 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.qute.commons;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;

/**
* File utilities.
*
* @author Angelo ZERR
*
*/
public class FileUtils {

private static final String FILE_SCHEME = "file";

/**
* Returns true if the given uri is a file uri and false otherwise.
*
* @param uri the uri
*
* @return true if the given uri is a file uri and false otherwise.
*/
public static boolean isFileURI(URI uri) {
return isEmpty(uri.getScheme()) || FILE_SCHEME.equals(uri.getScheme());
}

public static URI createUri(String uriString) {
if (isEmpty(uriString)) {
return null;
}

try {
if (uriString.startsWith("file:/")) {
String convertedUri = uriString.replace("file:///", "file:/"); //$NON-NLS-1$//$NON-NLS-2$
convertedUri = convertedUri.replace("file://", "file:/"); //$NON-NLS-1$//$NON-NLS-2$
}
if (uriString.indexOf('%') != -1) {
uriString = uriDecode(uriString, StandardCharsets.UTF_8);
}
URI uri = URI.create(uriString);
/*if (!isFileURI(uri)) {
// The uri is not a file URI, ignore it.
return null;
}*/
return uri;
} catch (Exception e) {
return null;
}
}

/**
* Returns the path for the given file uri and null otherwise.
*
* @param uriString the Uri as string.
*
* @return the path for the given file uri and null otherwise.
*/
public static Path createPath(String uriString) {
URI fileURi = createUri(uriString);
if (fileURi == null) {
return null;
}
return new File(fileURi).toPath();
}

public static String toUri(Path path) {
return path.toUri().toASCIIString();
}

/**
* Decode the given encoded URI component value. Based on the following rules:
* <ul>
* <li>Alphanumeric characters {@code "a"} through {@code "z"}, {@code "A"}
* through {@code "Z"}, and {@code "0"} through {@code "9"} stay the same.</li>
* <li>Special characters {@code "-"}, {@code "_"}, {@code "."}, and {@code "*"}
* stay the same.</li>
* <li>A sequence "{@code %<i>xy</i>}" is interpreted as a hexadecimal
* representation of the character.</li>
* <li>For all other characters (including those already decoded), the output is
* undefined.</li>
* </ul>
*
* @param source the encoded String
* @param charset the character set
* @return the decoded value
* @throws IllegalArgumentException when the given source contains invalid
* encoded sequences
* @since 5.0
* @see java.net.URLDecoder#decode(String, String)
*
* This method is a copy / paste from
* https://github.com/spring-projects/spring-framework/blob/67c7b80c2bed0f4f91b27d735541e9dfad8ce5b3/spring-core/src/main/java/org/springframework/util/StringUtils.java#L821
*/
private static String uriDecode(String source, Charset charset) {
int length = source.length();
if (length == 0) {
return source;
}
// Assert.notNull(charset, "Charset must not be null");

ByteArrayOutputStream baos = new ByteArrayOutputStream(length);
boolean changed = false;
for (int i = 0; i < length; i++) {
int ch = source.charAt(i);
if (ch == '%') {
if (i + 2 < length) {
char hex1 = source.charAt(i + 1);
char hex2 = source.charAt(i + 2);
int u = Character.digit(hex1, 16);
int l = Character.digit(hex2, 16);
if (u == -1 || l == -1) {
throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\"");
}
baos.write((char) ((u << 4) + l));
i += 2;
changed = true;
} else {
throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\"");
}
} else {
baos.write(ch);
}
}
return (changed ? copyToString(baos, charset) : source);
}

private static String copyToString(ByteArrayOutputStream baos, Charset charset) {
try {
return baos.toString(charset.name());
} catch (UnsupportedEncodingException e) {
return baos.toString();
}
}

private static boolean isEmpty(String value) {
return value == null || value.isEmpty();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ public class ProjectInfo {

private String uri;

private String templateBaseDir;
private List<TemplateRootPath> templateRootPaths;

private List<String> projectDependencyUris;

public ProjectInfo() {
}

public ProjectInfo(String projectUri, List<String> projectDependencies, String templateBaseDir) {
public ProjectInfo(String projectUri, List<String> projectDependencies, List<TemplateRootPath> templateRootPaths) {
setUri(projectUri);
setProjectDependencyUris(projectDependencies);
setTemplateBaseDir(templateBaseDir);
setTemplateRootPaths(templateRootPaths);
}

/**
Expand Down Expand Up @@ -72,21 +72,11 @@ public void setProjectDependencyUris(List<String> projectDependencyUris) {
this.projectDependencyUris = projectDependencyUris;
}

/**
* Returns the Qute templates base directory and null otherwise.
*
* @return the Qute templates base directory and null otherwise.
*/
public String getTemplateBaseDir() {
return templateBaseDir;
public List<TemplateRootPath> getTemplateRootPaths() {
return templateRootPaths;
}

/**
* Set the Qute templates base directory.
*
* @param templateBaseDir the Qute templates base directory.
*/
public void setTemplateBaseDir(String templateBaseDir) {
this.templateBaseDir = templateBaseDir;
public void setTemplateRootPaths(List<TemplateRootPath> templateRootPaths) {
this.templateRootPaths = templateRootPaths;
}
}
Loading

0 comments on commit a1e10fb

Please sign in to comment.