JaroslavTulach commented on a change in pull request #3262:
URL: https://github.com/apache/netbeans/pull/3262#discussion_r740111437



##########
File path: 
java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/layer.xml
##########
@@ -39,7 +39,7 @@
             </folder>
             <file name="Import_hidden"/>
             <folder name="Maven2">
-                <file name="JavaApplication_hidden"/>
+                <file name="maven.archetype_hidden"/>

Review comment:
       Why was existing `JavaApplication` file renamed? Or where the 
`maven.archetype` file/folder comes from.

##########
File path: 
java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/LspTemplateUI.java
##########
@@ -138,6 +138,7 @@ private LspTemplateUI() {
                 final DataFolder target = targetAndName.first();
                 final String name = targetAndName.second();
                 Map<String,String> prjParams = new HashMap<>();
+                // PENDING: this is a mavenism; 
                 prjParams.put("version", "1.0-SNAPSHOT"); // NOI18N

Review comment:
       Please modify existing templates (as exposed by VSNetBeans) to use 
`1.0-SNAPSHOT` as default and remove this attribute.

##########
File path: 
java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/package-info.java
##########
@@ -21,14 +21,6 @@
     @TemplateRegistration(folder = "Classes/Code", position = 100, content = 
"resources/GeneratedMethodBody.template", scriptEngine = "freemarker", 
displayName = "#GeneratedMethodBody", category = "java-code-snippet"),
     @TemplateRegistration(folder = "Classes/Code", position = 200, content = 
"resources/OverriddenMethodBody.template", scriptEngine = "freemarker", 
displayName = "#OverriddenMethodBody", category = "java-code-snippet"),
     @TemplateRegistration(folder = "Classes/Code", position = 300, content = 
"resources/LambdaBody.template", scriptEngine = "freemarker", displayName = 
"#LambdaBody", category = "java-code-snippet"),
-    @TemplateRegistration(

Review comment:
       Less differences between VSNetBeans and NetBeans is good.

##########
File path: 
java/maven/src/org/netbeans/modules/maven/newproject/TemplateUtils.java
##########
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.netbeans.modules.maven.newproject;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.regex.Pattern;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectInformation;
+import org.netbeans.api.project.ProjectManager;
+import org.netbeans.api.templates.CreateDescriptor;
+import org.netbeans.modules.maven.api.archetype.ProjectInfo;
+import org.netbeans.spi.project.ActionProgress;
+import org.netbeans.spi.project.ActionProvider;
+import org.netbeans.spi.project.ui.support.CommonProjectActions;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ProxyLookup;
+
+public final class TemplateUtils {

Review comment:
       Can this class be package private?

##########
File path: 
platform/api.templates/src/org/netbeans/api/templates/FileBuilder.java
##########
@@ -109,6 +135,20 @@
     public FileBuilder(@NonNull FileObject template, @NonNull FileObject 
target) {
         descriptor = new CreateDescriptor(template, target);
     }
+
+    /**
+     * Use specific Lookup for creation. This allows to pass in additional
+     * parameters or services. A GUI-aware caller may, for example, add
+     * a ProgressHandle or a project ActionProgress interface to the lookup,

Review comment:
       OK.

##########
File path: 
platform/api.templates/src/org/netbeans/api/templates/CreateFromTemplateHandler.java
##########
@@ -59,4 +64,171 @@
             CreateDescriptor    desc
     ) throws IOException;
 
+    /**
+     * Replaces ${param} tokens in a String. The parameter reference has 
syntax "${" paramName [":" defaultValue ] "}".
+     * Parameters are replaced recursively. "${" can be escaped by \, so "\${" 
will not act as parameter reference start.
+     * @param expression string template
+     * @param parameters parameter values
+     * @return evaluated string.
+     * @since 1.23
+     */
+    public static String mapParameters(String expression, Map<String, ?> 
parameters) {

Review comment:
       There is `org.openide.util.MapFormat` - if the suggestion to use 
`freemarker` isn't going to fly - wouldn't it be better to reuse the existing 
`MapFormat` or expand it?

##########
File path: 
platform/api.templates/src/org/netbeans/api/templates/CreateFromTemplateHandler.java
##########
@@ -59,4 +64,171 @@
             CreateDescriptor    desc
     ) throws IOException;
 
+    /**
+     * Replaces ${param} tokens in a String. The parameter reference has 
syntax "${" paramName [":" defaultValue ] "}".
+     * Parameters are replaced recursively. "${" can be escaped by \, so "\${" 
will not act as parameter reference start.
+     * @param expression string template
+     * @param parameters parameter values
+     * @return evaluated string.
+     * @since 1.23
+     */
+    public static String mapParameters(String expression, Map<String, ?> 
parameters) {
+        int start = 0;
+        int pos = 0;
+        StringBuilder sb = null;
+        
+        while ((pos = expression.indexOf("${", pos)) != -1) { // NOI18N
+            if (pos > 0 && expression.charAt(pos - 1) == '\\') { // NOI18N
+                pos += 2;
+                continue;
+            }
+            int endPos = pos + 2;
+            int state = 0;
+            int nested = 0;
+            A: while (endPos < expression.length()) {
+                char c = expression.charAt(endPos);
+                if (state == 1) {
+                    state = 0;
+                    endPos++;
+                    continue;
+                }
+                switch (c) {
+                    case '\\': // NOI18N
+                        state = 1;
+                        break;
+                    case '$': // NOI18N
+                        state = 2;
+                        break;
+                    case '{': // NOI18N
+                        if (state == 2) {
+                            state = 0;
+                            nested++;
+                        }
+                        break;
+                    case '}': // NOI18N
+                        if (state == 0) {
+                            if (nested-- == 0) {
+                                break A;
+                            }
+                        }
+                        break;
+                }
+                endPos++;
+            }
+            if (endPos >= expression.length()) {
+                pos += 2;
+                continue;
+            }
+            String token = expression.substring(pos + 2, endPos);
+            String defValue = null;
+            
+            int colon = token.indexOf(':'); // NOI18N
+            if (colon != -1) {
+                defValue = token.substring(colon + 1);
+                token = token.substring(0, colon);
+            }
+            
+            if (sb == null) {
+                sb = new StringBuilder();
+            }
+            Object v = parameters.get(token);
+            if (v == null) {
+                v = defValue;
+            }
+            if (v == null) {
+                pos += 2;
+                continue;
+            }
+            sb.append(expression.substring(start, pos)).append(v.toString());
+            start = endPos + 1;
+            pos = start;
+        }
+        if (sb == null) {
+            return expression;
+        }
+        if (start < expression.length()) {
+            sb.append(expression.substring(start));
+        }
+        
+        return mapParameters(sb.toString(), parameters);
+    }
+    
+    private static final String PROP_TEMPLATE = "template"; // NOI18N
+
+    /**
+     * Prefix for template-controlling attributes. Such attributes will not be 
copied
+     * during template instantiation.
+     */
+    private static final String ATTR_TEMPLATE_PREFIX = "template.";
+    
+    /**
+     * Copies template attributes over to the created file. Copies over from 
the source (template) to the target (usually
+     * the produced file), except attributes that parametrize template 
creation. By default, attributes that are prefixed
+     * with {@code "template."} are not copied. As the operation is not 
atomic, the method should be called in a 
+     * {@link 
org.openide.filesystems.FileSystem#runAtomicAction(org.openide.filesystems.FileSystem.AtomicAction)}.
+     * The {@code "template"} attribute is never copied.
+     * 
+     * @param h the Handler responsible for file creation, usually the calling 
handler.
+     * @param from the original file
+     * @param to the target file
+     * @throws IOException if an I/O error occurs.
+     */
+    public static void copyAttributesFromTemplate(CreateFromTemplateHandler h, 
FileObject from, FileObject to) throws IOException {
+        // copy attributes; some attributes are filtered by FileSystems API 
already
+        FileUtil.copyAttributes(from, to);

Review comment:
       Consider expanding the `copyAttributes` method with a `Predicate<String> 
attributeName` rather than copying everything and then cleaning it up.

##########
File path: 
java/maven/test/unit/src/org/netbeans/modules/maven/newproject/simplewizard/SimpleWizardTemplateHandlerTest.java
##########
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.netbeans.modules.maven.newproject.simplewizard;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import org.apache.maven.project.MavenProject;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectManager;
+import org.netbeans.api.templates.FileBuilder;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.modules.maven.api.NbMavenProject;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+/**
+ *
+ * @author sdedic
+ */
+public class SimpleWizardTemplateHandlerTest extends NbTestCase {
+
+    public SimpleWizardTemplateHandlerTest(String name) {
+        super(name);
+    }
+    
+    FileObject whereTo;
+    
+    private FileBuilder createProject() throws IOException {
+        clearWorkDir();
+        whereTo = FileUtil.createFolder(FileUtil.toFileObject(getWorkDir()), 
"whereTo");
+        
+        FileObject template = 
FileUtil.getConfigFile("Templates/Project/Maven2/JavaApplication2");
+        FileBuilder bld = new FileBuilder(template, whereTo);
+        bld.name("TestProject");
+        bld.defaultMode(FileBuilder.Mode.COPY);
+
+        bld.param("artifactId", "netbeans-test-project");
+        bld.param("groupId", "org.netbeans.modules.maven");
+        // leave out version

Review comment:
       Looks like the version can be left out.

##########
File path: java/maven/src/org/netbeans/modules/maven/layer.xml
##########
@@ -33,6 +33,22 @@
             <folder name="Maven2">
                 <attr name="displayName" 
bundlevalue="org.netbeans.modules.maven.newproject.Bundle#Templates/Project/Maven2"/>
                 <attr name="position" intvalue="100"/>
+
+                <!-- Simple Java project structure -->
+                <folder name="JavaApplication2">
+                    <folder name="src">
+                        <folder name="main">
+                            <folder name="java">
+                                <folder name="${packagePath}">
+                                    <file name="${mainClassName}.java" 
url="nbresloc:/org/netbeans/modules/maven/resources/App.java.template">

Review comment:
       Using new substitution mechanism for names is OK, but the syntax! Let's 
make the syntax pluggable! Sváťo, what do you think about:
   
   If there is an `<attr name="javax.script.ScriptEngine" 
stringvalue="freemarker"/>` attribute on a file or folder, apply the specified 
engine (e.g. `freemarker`) to the name of the file/folder as well. 

##########
File path: 
platform/api.templates/src/org/netbeans/api/templates/CreateDescriptor.java
##########
@@ -181,4 +187,17 @@ public boolean hasFreeExtension() {
     public boolean isPreformatted() {
         return preformatted;
     }
+
+    void setLookup(Lookup contextLookup) {
+        this.contextLookup = contextLookup;
+    }
+
+    /**
+     * Lookup that may contain additional services or instructions for
+     * the template creation.
+     * @since 1.23
+     */
+    public Lookup getLookup() {

Review comment:
       The class could now `implements Lookup.Provider`.

##########
File path: 
platform/api.templates/src/org/netbeans/api/templates/TemplateRegistration.java
##########
@@ -156,4 +156,10 @@
      * @since 1.4
      */
     String[] techIds() default {};
+
+    /**
+     * Specifies the default handler to instantiate the template. 
+     * @since 1.23
+     */
+    Class<? extends CreateFromTemplateHandler> createHandlerClass() default 
CreateFromTemplateHandler.class;

Review comment:
       Nice.

##########
File path: 
java/maven/src/org/netbeans/modules/maven/newproject/idenative/SimpleJavaNativeMWI.java
##########
@@ -19,103 +19,29 @@
 
 package org.netbeans.modules.maven.newproject.idenative;
 
-import org.netbeans.modules.maven.spi.newproject.CreateProjectBuilder;
-import java.io.File;
-import java.util.Collections;
-import java.util.List;
-import org.apache.maven.project.MavenProject;
-import org.netbeans.api.java.platform.JavaPlatform;
-import org.netbeans.api.java.platform.JavaPlatformManager;
-import org.netbeans.api.progress.ProgressHandle;
 import org.netbeans.api.templates.TemplateRegistration;
-import org.netbeans.modules.maven.api.Constants;
-import org.netbeans.modules.maven.api.PluginPropertyUtils;
 import org.netbeans.modules.maven.api.archetype.ArchetypeWizards;
-import org.netbeans.modules.maven.api.archetype.ProjectInfo;
-import org.netbeans.modules.maven.classpath.AbstractBootPathImpl;
-import org.netbeans.modules.maven.model.ModelOperation;
-import org.netbeans.modules.maven.model.pom.POMModel;
-import org.netbeans.modules.maven.model.pom.Project;
-import org.netbeans.modules.maven.model.pom.Properties;
 import static 
org.netbeans.modules.maven.newproject.idenative.Bundle.LBL_Maven_Quickstart_Archetype;
-import org.netbeans.modules.maven.options.MavenSettings;
 import org.openide.util.NbBundle.Messages;
 
 /**
  *
  * @author mkleint
  */
 @TemplateRegistration(
-    id = "JavaApplication",
+    id = "JavaApplication2/",

Review comment:
       Why is this template being renamed?

##########
File path: 
java/maven/src/org/netbeans/modules/maven/newproject/idenative/IDENativeTemplateHandler.java
##########
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.netbeans.modules.maven.newproject.idenative;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.api.project.ProjectManager;
+import org.netbeans.api.templates.CreateDescriptor;
+import org.netbeans.api.templates.CreateFromTemplateHandler;
+import org.netbeans.api.templates.FileBuilder;
+import org.netbeans.modules.maven.api.archetype.ProjectInfo;
+import org.netbeans.modules.maven.newproject.TemplateUtils;
+import org.netbeans.modules.maven.spi.newproject.CreateProjectBuilder;
+import org.netbeans.spi.project.ui.support.CommonProjectActions;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.BaseUtilities;
+import org.openide.util.NbBundle;
+
+/**
+ * Allows to create the 'ide native' projects in the headless mode. Is not 
registered as an interceptor, but rather
+ * listed explicitly for a template it handles.
+ * @author sdedic
+ */
+public class IDENativeTemplateHandler extends CreateFromTemplateHandler {

Review comment:
       Can we use some other name than IDE native? There is no native code and 
I find the name confusing.

##########
File path: 
platform/api.templates/src/org/netbeans/api/templates/CreateFromTemplateHandler.java
##########
@@ -59,4 +64,171 @@
             CreateDescriptor    desc
     ) throws IOException;
 
+    /**
+     * Replaces ${param} tokens in a String. The parameter reference has 
syntax "${" paramName [":" defaultValue ] "}".
+     * Parameters are replaced recursively. "${" can be escaped by \, so "\${" 
will not act as parameter reference start.
+     * @param expression string template
+     * @param parameters parameter values
+     * @return evaluated string.
+     * @since 1.23
+     */
+    public static String mapParameters(String expression, Map<String, ?> 
parameters) {
+        int start = 0;
+        int pos = 0;
+        StringBuilder sb = null;
+        
+        while ((pos = expression.indexOf("${", pos)) != -1) { // NOI18N
+            if (pos > 0 && expression.charAt(pos - 1) == '\\') { // NOI18N
+                pos += 2;
+                continue;
+            }
+            int endPos = pos + 2;
+            int state = 0;
+            int nested = 0;
+            A: while (endPos < expression.length()) {
+                char c = expression.charAt(endPos);
+                if (state == 1) {
+                    state = 0;
+                    endPos++;
+                    continue;
+                }
+                switch (c) {
+                    case '\\': // NOI18N
+                        state = 1;
+                        break;
+                    case '$': // NOI18N
+                        state = 2;
+                        break;
+                    case '{': // NOI18N
+                        if (state == 2) {
+                            state = 0;
+                            nested++;
+                        }
+                        break;
+                    case '}': // NOI18N
+                        if (state == 0) {
+                            if (nested-- == 0) {
+                                break A;
+                            }
+                        }
+                        break;
+                }
+                endPos++;
+            }
+            if (endPos >= expression.length()) {
+                pos += 2;
+                continue;
+            }
+            String token = expression.substring(pos + 2, endPos);
+            String defValue = null;
+            
+            int colon = token.indexOf(':'); // NOI18N
+            if (colon != -1) {
+                defValue = token.substring(colon + 1);
+                token = token.substring(0, colon);
+            }
+            
+            if (sb == null) {
+                sb = new StringBuilder();
+            }
+            Object v = parameters.get(token);
+            if (v == null) {
+                v = defValue;
+            }
+            if (v == null) {
+                pos += 2;
+                continue;
+            }
+            sb.append(expression.substring(start, pos)).append(v.toString());
+            start = endPos + 1;
+            pos = start;
+        }
+        if (sb == null) {
+            return expression;
+        }
+        if (start < expression.length()) {
+            sb.append(expression.substring(start));
+        }
+        
+        return mapParameters(sb.toString(), parameters);
+    }
+    
+    private static final String PROP_TEMPLATE = "template"; // NOI18N
+
+    /**
+     * Prefix for template-controlling attributes. Such attributes will not be 
copied
+     * during template instantiation.
+     */
+    private static final String ATTR_TEMPLATE_PREFIX = "template.";
+    
+    /**
+     * Copies template attributes over to the created file. Copies over from 
the source (template) to the target (usually
+     * the produced file), except attributes that parametrize template 
creation. By default, attributes that are prefixed
+     * with {@code "template."} are not copied. As the operation is not 
atomic, the method should be called in a 
+     * {@link 
org.openide.filesystems.FileSystem#runAtomicAction(org.openide.filesystems.FileSystem.AtomicAction)}.
+     * The {@code "template"} attribute is never copied.
+     * 
+     * @param h the Handler responsible for file creation, usually the calling 
handler.
+     * @param from the original file
+     * @param to the target file
+     * @throws IOException if an I/O error occurs.
+     */
+    public static void copyAttributesFromTemplate(CreateFromTemplateHandler h, 
FileObject from, FileObject to) throws IOException {
+        // copy attributes; some attributes are filtered by FileSystems API 
already
+        FileUtil.copyAttributes(from, to);
+        // need to filter additional template-related attributes:
+        for (String a : Collections.list(to.getAttributes())) {
+            if ("javax.script.ScriptEngine".equals(a) // NOI18N 
+                || a.startsWith(ATTR_TEMPLATE_PREFIX)) {
+                to.setAttribute(a, null);
+            }
+        }
+        // hack to overcome package-private modifier in setTemplate(fo, 
boolean)
+        to.setAttribute(PROP_TEMPLATE, null);
+    }
+    
+    
+    /**
+     * Copies the files or folders contained in the specified folder to the 
target. The original descriptor can be passed in,
+     * since it has Lookup, parameters etc set up. They will be passed on to 
individual created files. The `contentsParent` may
+     * be {@code null}, in which case the {@link 
CreateDescriptor#getTemplate()} folder will be used.
+     * @param origDescriptor original descriptor to get parameters / lookup 
from
+     * @param contentsParent template folder whose contents should be copied
+     * @param target target folder
+     * @return created files
+     * @throws IOException 
+     * @since 1.23
+     */
+    protected static List<FileObject> defaultCopyContents(CreateDescriptor 
origDescriptor, FileObject contentsParent, FileObject target) throws 
IOException {

Review comment:
       Strange method. `protected static` is a strange combination of modifiers 
- if the class is subclassable, there is nothing "protected" in this method. If 
the class isn't subclassable, making a method `protected` makes no sense.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to