{"action":"created","comment":{"url":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/comments/359206511","pull_request_review_id":333795056,"id":359206511,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDM1OTIwNjUxMQ==","diff_hunk":"@@ -6,550 +6,100 @@\n \n package com.microsoft.azure.maven.function;\n \n-import com.fasterxml.jackson.databind.ObjectMapper;\n-import com.microsoft.azure.maven.function.template.BindingTemplate;\n-import com.microsoft.azure.maven.function.template.BindingsTemplate;\n-import com.microsoft.azure.maven.function.template.FunctionSettingTemplate;\n-import com.microsoft.azure.maven.function.template.FunctionTemplate;\n-import com.microsoft.azure.maven.function.template.FunctionTemplates;\n-import com.microsoft.azure.maven.function.template.TemplateResources;\n+import java.io.File;\n+import java.nio.file.Paths;\n+import java.util.List;\n \n import org.apache.commons.lang3.StringUtils;\n-import org.apache.maven.plugin.MojoFailureException;\n import org.apache.maven.plugins.annotations.Mojo;\n import org.apache.maven.plugins.annotations.Parameter;\n-import org.codehaus.plexus.util.IOUtil;\n-\n-import javax.annotation.Nullable;\n-import java.io.File;\n-import java.io.FileOutputStream;\n-import java.io.IOException;\n-import java.io.InputStream;\n-import java.io.OutputStream;\n-import java.nio.file.FileAlreadyExistsException;\n-import java.nio.file.Paths;\n-import java.util.Arrays;\n-import java.util.HashMap;\n-import java.util.List;\n-import java.util.Map;\n-import java.util.Objects;\n-import java.util.Optional;\n-import java.util.Scanner;\n-import java.util.function.Consumer;\n-import java.util.function.Function;\n-import java.util.stream.Collectors;\n \n-import static java.lang.String.format;\n-import static java.lang.System.out;\n-import static javax.lang.model.SourceVersion.isName;\n+import com.microsoft.azure.common.function.AddFunctionHandler;\n \n /**\n  * Create new Azure Functions (as Java class) and add to current project.\n  */\n @Mojo(name = \"add\")\n public class AddMojo extends AbstractFunctionMojo {\n-    public static final String LOAD_TEMPLATES = \"Step 1 of 4: Load all function templates\";\n-    public static final String LOAD_TEMPLATES_DONE = \"Successfully loaded all function templates\";\n-    public static final String LOAD_TEMPLATES_FAIL = \"Failed to load all function templates.\";\n-    public static final String FIND_TEMPLATE = \"Step 2 of 4: Select function template\";\n-    public static final String FIND_TEMPLATE_DONE = \"Successfully found function template: \";\n-    public static final String FIND_TEMPLATE_FAIL = \"Function template not found: \";\n-    public static final String LOAD_BINDING_TEMPLATES_FAIL = \"Failed to load function binding template.\";\n-    public static final String PREPARE_PARAMS = \"Step 3 of 4: Prepare required parameters\";\n-    public static final String FOUND_VALID_VALUE = \"Found valid value. Skip user input.\";\n-    public static final String SAVE_FILE = \"Step 4 of 4: Saving function to file\";\n-    public static final String SAVE_FILE_DONE = \"Successfully saved new function at \";\n-    public static final String FILE_EXIST = \"Function already exists at %s. Please specify a different function name.\";\n-    public static final String DEFAULT_INPUT_ERROR_MESSAGE = \"Invalid input, please check and try again.\";\n-    public static final String PROMPT_STRING_WITH_DEFAULTVALUE = \"Enter value for %s(Default: %s): \";\n-    public static final String PROMPT_STRING_WITHOUT_DEFAULTVALUE = \"Enter value for %s: \";\n-    private static final String FUNCTION_NAME_REGEXP = \"^[a-zA-Z][a-zA-Z\\\\d_\\\\-]*$\";\n-\n-    //region Properties\n-\n-    @Parameter(defaultValue = \"${project.basedir}\", readonly = true, required = true)\n-    protected File basedir;\n-\n-    @Parameter(defaultValue = \"${project.compileSourceRoots}\", readonly = true, required = true)\n-    protected List<String> compileSourceRoots;\n-\n-    /**\n-     * Package name of the new function.\n-     *\n-     * @since 0.1.0\n-     */\n-    @Parameter(property = \"functions.package\")\n-    protected String functionPackageName;\n-\n-    /**\n-     * Name of the new function.\n-     *\n-     * @since 0.1.0\n-     */\n-    @Parameter(property = \"functions.name\")\n-    protected String functionName;\n-\n-    /**\n-     * Template for the new function\n-     *\n-     * @since 0.1.0\n-     */\n-    @Parameter(property = \"functions.template\")\n-    protected String functionTemplate;\n-\n-    //endregion\n-\n-    //region Getter and Setter\n-\n-    public String getFunctionPackageName() {\n-        return functionPackageName;\n-    }\n-\n-    public String getFunctionName() {\n-        return functionName;\n-    }\n-\n-    public String getClassName() {\n-        return getFunctionName().replace('-', '_');\n-    }\n-\n-    public String getFunctionTemplate() {\n-        return functionTemplate;\n-    }\n-\n-    protected String getBasedir() {\n-        return basedir.getAbsolutePath();\n-    }\n-\n-    protected String getSourceRoot() {\n-        return compileSourceRoots == null || compileSourceRoots.isEmpty() ?\n-                Paths.get(getBasedir(), \"src\", \"main\", \"java\").toString() :\n-                compileSourceRoots.get(0);\n-    }\n-\n-    protected void setFunctionPackageName(String functionPackageName) {\n-        this.functionPackageName = StringUtils.lowerCase(functionPackageName);\n-    }\n-\n-    protected void setFunctionName(String functionName) {\n-        this.functionName = StringUtils.capitalize(functionName);\n-    }\n-\n-    protected void setFunctionTemplate(String functionTemplate) {\n-        this.functionTemplate = functionTemplate;\n-    }\n-\n-    //endregion\n-\n-    //region Entry Point\n-\n-    @Override\n-    protected void doExecute() throws Exception {\n-        final List<FunctionTemplate> templates = loadAllFunctionTemplates();\n-\n-        final FunctionTemplate template = getFunctionTemplate(templates);\n-        final BindingTemplate bindingTemplate = loadBindingTemplate(template.getTriggerType());\n-\n-        final Map params = prepareRequiredParameters(template, bindingTemplate);\n-\n-        final String newFunctionClass = substituteParametersInTemplate(template, params);\n-\n-        saveNewFunctionToFile(newFunctionClass);\n-    }\n-\n-    //endregion\n-\n-    //region Load templates\n-    protected BindingTemplate loadBindingTemplate(String type) {\n-        try (final InputStream is = AddMojo.class.getResourceAsStream(\"/bindings.json\")) {\n-            final String bindingsJsonStr = IOUtil.toString(is);\n-            final BindingsTemplate bindingsTemplate = new ObjectMapper()\n-                .readValue(bindingsJsonStr, BindingsTemplate.class);\n-            return bindingsTemplate.getBindingTemplateByName(type);\n-        } catch (IOException e) {\n-            warning(LOAD_BINDING_TEMPLATES_FAIL);\n-            // Add mojo could work without Binding Template, just return null if binding load fail\n-            return null;\n-        }\n-    }\n-\n-    protected List<FunctionTemplate> loadAllFunctionTemplates() throws Exception {\n-        info(\"\");\n-        info(LOAD_TEMPLATES);\n-\n-        try (final InputStream is = AddMojo.class.getResourceAsStream(\"/templates.json\")) {\n-            final String templatesJsonStr = IOUtil.toString(is);\n-            final List<FunctionTemplate> templates = parseTemplateJson(templatesJsonStr);\n-            info(LOAD_TEMPLATES_DONE);\n-            return templates;\n-        } catch (Exception e) {\n-            error(LOAD_TEMPLATES_FAIL);\n-            throw e;\n-        }\n-    }\n-\n-    protected List<FunctionTemplate> parseTemplateJson(final String templateJson) throws Exception {\n-        final FunctionTemplates templates = new ObjectMapper().readValue(templateJson, FunctionTemplates.class);\n-        return templates.getTemplates();\n-    }\n-\n-    //endregion\n-\n-    //region Get function template\n-    protected FunctionTemplate getFunctionTemplate(final List<FunctionTemplate> templates) throws Exception {\n-        info(\"\");\n-        info(FIND_TEMPLATE);\n-\n-        if (settings != null && !settings.isInteractiveMode()) {\n-            assureInputInBatchMode(getFunctionTemplate(),\n-                str -> getTemplateNames(templates)\n-                    .stream()\n-                    .filter(Objects::nonNull)\n-                    .anyMatch(o -> o.equalsIgnoreCase(str)),\n-                this::setFunctionTemplate,\n-                true);\n-        } else {\n-            assureInputFromUser(\"template for new function\",\n-                getFunctionTemplate(),\n-                getTemplateNames(templates),\n-                this::setFunctionTemplate);\n-        }\n-\n-        return findTemplateByName(templates, getFunctionTemplate());\n-    }\n-\n-    protected List<String> getTemplateNames(final List<FunctionTemplate> templates) {\n-        return templates.stream().map(t -> t.getMetadata().getName()).collect(Collectors.toList());\n-    }\n-\n-    protected FunctionTemplate findTemplateByName(final List<FunctionTemplate> templates, final String templateName)\n-            throws Exception {\n-        info(\"Selected function template: \" + templateName);\n-        final Optional<FunctionTemplate> template = templates.stream()\n-            .filter(t -> t.getMetadata().getName().equalsIgnoreCase(templateName))\n-            .findFirst();\n-\n-        if (template.isPresent()) {\n-            info(FIND_TEMPLATE_DONE + templateName);\n-            return template.get();\n-        }\n-\n-        throw new Exception(FIND_TEMPLATE_FAIL + templateName);\n-    }\n-\n-    //endregion\n-\n-    //region Prepare parameters\n-\n-    protected Map<String, String> prepareRequiredParameters(final FunctionTemplate template,\n-                                                            final BindingTemplate bindingTemplate)\n-        throws MojoFailureException {\n-        info(\"\");\n-        info(PREPARE_PARAMS);\n-\n-        prepareFunctionName();\n-\n-        preparePackageName();\n-\n-        final Map<String, String> params = new HashMap<>();\n-        params.put(\"functionName\", getFunctionName());\n-        params.put(\"className\", getClassName());\n-        params.put(\"packageName\", getFunctionPackageName());\n-\n-        prepareTemplateParameters(template, bindingTemplate, params);\n-\n-        displayParameters(params);\n-\n-        return params;\n-    }\n-\n-    protected void prepareFunctionName() throws MojoFailureException {\n-        info(\"Common parameter [Function Name]: name for both the new function and Java class\");\n-\n-        if (settings != null && !settings.isInteractiveMode()) {\n-            assureInputInBatchMode(getFunctionName(),\n-                str -> StringUtils.isNotEmpty(str) && str.matches(FUNCTION_NAME_REGEXP),\n-                this::setFunctionName,\n-                true);\n-        } else {\n-            assureInputFromUser(\"Enter value for Function Name: \",\n-                getFunctionName(),\n-                str -> StringUtils.isNotEmpty(str) && str.matches(FUNCTION_NAME_REGEXP),\n-                \"Function name must start with a letter and can contain letters, digits, '_' and '-'\",\n-                this::setFunctionName);\n-        }\n-    }\n-\n-    protected void preparePackageName() throws MojoFailureException {\n-        info(\"Common parameter [Package Name]: package name of the new Java class\");\n-\n-        if (settings != null && !settings.isInteractiveMode()) {\n-            assureInputInBatchMode(getFunctionPackageName(),\n-                str -> StringUtils.isNotEmpty(str) && isName(str),\n-                this::setFunctionPackageName,\n-                true);\n-        } else {\n-            assureInputFromUser(\"Enter value for Package Name: \",\n-                getFunctionPackageName(),\n-                str -> StringUtils.isNotEmpty(str) && isName(str),\n-                \"Input should be a valid Java package name.\",\n-                this::setFunctionPackageName);\n-        }\n-    }\n-\n-    protected Map<String, String> prepareTemplateParameters(final FunctionTemplate template,\n-                                                            final BindingTemplate bindingTemplate,\n-                                                            final Map<String, String> params)\n-        throws MojoFailureException {\n-        for (final String property : template.getMetadata().getUserPrompt()) {\n-            String initValue = System.getProperty(property);\n-            final List<String> options = getOptionsForUserPrompt(property);\n-            final FunctionSettingTemplate settingTemplate = bindingTemplate == null ?\n-                null : bindingTemplate.getSettingTemplateByName(property);\n-            final String helpMessage = (settingTemplate != null && settingTemplate.getHelp() != null) ?\n-                settingTemplate.getHelp() : \"\";\n-\n-            info(format(\"Trigger specific parameter [%s]:%s\", property,\n-                TemplateResources.getResource(helpMessage)));\n-            if (settings != null && !settings.isInteractiveMode()) {\n-                if (options != null && options.size() > 0) {\n-                    final String foundElement = findElementInOptions(options, initValue);\n-                    initValue = foundElement == null ? options.get(0) : foundElement;\n-                }\n-\n-                assureInputInBatchMode(\n-                    initValue,\n-                    StringUtils::isNotEmpty,\n-                    str -> params.put(property, str),\n-                    false\n-                );\n-            } else {\n-                if (options == null) {\n-                    params.put(property, getStringInputFromUser(property, initValue, settingTemplate));\n-                } else {\n-                    assureInputFromUser(\n-                        format(\"the value for %s: \", property),\n-                        System.getProperty(property),\n-                        options,\n-                        str -> params.put(property, str)\n-                    );\n-                }\n-            }\n-        }\n-\n-        return params;\n-    }\n-\n-    protected String getStringInputFromUser(String attributeName, String initValue, FunctionSettingTemplate template) {\n-        final String defaultValue = template == null ? null : template.getDefaultValue();\n-        final Function<String, Boolean> validator = getStringInputValidator(template);\n-\n-        if (validator.apply(initValue)) {\n-            info(FOUND_VALID_VALUE);\n-            return initValue;\n-        }\n-\n-        final Scanner scanner = getScanner();\n-        while (true) {\n-            out.printf(getStringInputPromptString(attributeName, defaultValue));\n-            out.flush();\n-            final String input = scanner.nextLine();\n-            if (validator.apply(input)) {\n-                return input;\n-            } else if (StringUtils.isNotEmpty(defaultValue) && StringUtils.isEmpty(input)) {\n-                return defaultValue;\n-            }\n-            warning(getStringInputErrorMessage(template));\n-        }\n-    }\n-\n-    protected String getStringInputErrorMessage(FunctionSettingTemplate template) {\n-        return (template != null && template.getErrorText() != null) ?\n-            TemplateResources.getResource(template.getErrorText()) : DEFAULT_INPUT_ERROR_MESSAGE;\n-    }\n-\n-    protected String getStringInputPromptString(String attributeName, String defaultValue) {\n-        return StringUtils.isBlank(defaultValue) ?\n-            String.format(PROMPT_STRING_WITHOUT_DEFAULTVALUE, attributeName) :\n-            String.format(PROMPT_STRING_WITH_DEFAULTVALUE, attributeName, defaultValue);\n-    }\n-\n-    protected Function<String, Boolean> getStringInputValidator(FunctionSettingTemplate template) {\n-        final String regex = template == null ? null : template.getSettingRegex();\n-        if (regex == null) {\n-            return StringUtils::isNotEmpty;\n-        } else {\n-            return (attribute) -> StringUtils.isNotEmpty(attribute) && attribute.matches(regex);\n-        }\n-    }\n-\n-    protected void displayParameters(final Map<String, String> params) {\n-        info(\"\");\n-        info(\"Summary of parameters for function template:\");\n-\n-        params.entrySet().stream().forEach(e -> info(format(\"%s: %s\", e.getKey(), e.getValue())));\n-    }\n-\n-    //endregion\n-\n-    //region Substitute parameters\n-\n-    protected String substituteParametersInTemplate(final FunctionTemplate template, final Map<String, String> params) {\n-        String ret = template.getFiles().get(\"function.java\");\n-        for (final Map.Entry<String, String> entry : params.entrySet()) {\n-            ret = ret.replace(String.format(\"$%s$\", entry.getKey()), entry.getValue());\n-        }\n-        return ret;\n-    }\n-\n-    //endregion\n-\n-    //region Save function to file\n-\n-    protected void saveNewFunctionToFile(final String newFunctionClass) throws Exception {\n-        info(\"\");\n-        info(SAVE_FILE);\n-\n-        final File packageDir = getPackageDir();\n-\n-        final File targetFile = getTargetFile(packageDir);\n-\n-        createPackageDirIfNotExist(packageDir);\n-\n-        saveToTargetFile(targetFile, newFunctionClass);\n-\n-        info(SAVE_FILE_DONE + targetFile.getAbsolutePath());\n-    }\n-\n-    protected File getPackageDir() {\n-        final String sourceRoot = getSourceRoot();\n-        final String[] packageName = getFunctionPackageName().split(\"\\\\.\");\n-        return Paths.get(sourceRoot, packageName).toFile();\n-    }\n-\n-    protected File getTargetFile(final File packageDir) throws Exception {\n-        final String javaFileName = getClassName() + \".java\";\n-        final File targetFile = new File(packageDir, javaFileName);\n-        if (targetFile.exists()) {\n-            throw new FileAlreadyExistsException(format(FILE_EXIST, targetFile.getAbsolutePath()));\n-        }\n-        return targetFile;\n-    }\n-\n-    protected void createPackageDirIfNotExist(final File packageDir) {\n-        if (!packageDir.exists()) {\n-            packageDir.mkdirs();\n-        }\n-    }\n-\n-    protected void saveToTargetFile(final File targetFile, final String newFunctionClass) throws Exception {\n-        try (final OutputStream os = new FileOutputStream(targetFile)) {\n-            IOUtil.copy(newFunctionClass, os);\n-        }\n-    }\n-\n-    //endregion\n-\n-    //region Helper methods\n-\n-    protected void assureInputFromUser(final String prompt, final String initValue, final List<String> options,\n-                                       final Consumer<String> setter) {\n-        final String option = findElementInOptions(options, initValue);\n-        if (option != null) {\n-            info(FOUND_VALID_VALUE);\n-            setter.accept(option);\n-            return;\n-        }\n-\n-        out.printf(\"Choose from below options as %s %n\", prompt);\n-        for (int i = 0; i < options.size(); i++) {\n-            out.printf(\"%d. %s%n\", i, options.get(i));\n-        }\n-\n-        assureInputFromUser(\"Enter index to use: \", null,\n-            str -> {\n-                try {\n-                    final int index = Integer.parseInt(str);\n-                    return 0 <= index && index < options.size();\n-                } catch (Exception e) {\n-                    return false;\n-                }\n-            },\n-            \"Invalid index.\", str -> {\n-                final int index = Integer.parseInt(str);\n-                setter.accept(options.get(index));\n-            }\n-        );\n-    }\n-\n-    protected void assureInputFromUser(final String prompt, final String initValue,\n-                                       final Function<String, Boolean> validator, final String errorMessage,\n-                                       final Consumer<String> setter) {\n-        if (validator.apply(initValue)) {\n-            info(FOUND_VALID_VALUE);\n-            setter.accept(initValue);\n-            return;\n-        }\n-\n-        final Scanner scanner = getScanner();\n-\n-        while (true) {\n-            out.printf(prompt);\n-            out.flush();\n-            try {\n-                final String input = scanner.nextLine();\n-                if (validator.apply(input)) {\n-                    setter.accept(input);\n-                    break;\n-                }\n-            } catch (Exception ignored) {\n-            }\n-            // Reaching here means invalid input\n-            warning(errorMessage);\n-        }\n-    }\n-\n-    protected void assureInputInBatchMode(final String input, final Function<String, Boolean> validator,\n-                                          final Consumer<String> setter, final boolean required)\n-            throws MojoFailureException {\n-        if (validator.apply(input)) {\n-            info(FOUND_VALID_VALUE);\n-            setter.accept(input);\n-            return;\n-        }\n-\n-        if (required) {\n-            throw new MojoFailureException(String.format(\"invalid input: %s\", input));\n-        } else {\n-            out.printf(\"The input is invalid. Use empty string.%n\");\n-            setter.accept(\"\");\n-        }\n-    }\n-\n-    protected Scanner getScanner() {\n-        return new Scanner(System.in, \"UTF-8\");\n-    }\n-\n-    @Nullable\n-    private String findElementInOptions(List<String> options, String item) {\n-        return options.stream()\n-            .filter(o -> o != null && o.equalsIgnoreCase(item))\n-            .findFirst()\n-            .orElse(null);\n-    }\n \n-    @Nullable\n-    private List<String> getOptionsForUserPrompt(final String promptName) {\n-        // HTTP Trigger\n-        if (\"authlevel\".equalsIgnoreCase(promptName.trim())) {\n-            return Arrays.asList(\"ANONYMOUS\", \"FUNCTION\", \"ADMIN\");\n-        }\n-        // Cosmos DB Trigger\n-        if (\"createLeaseCollectionIfNotExists\".equalsIgnoreCase(promptName.trim())) {\n-            return Arrays.asList(\"true\", \"false\");\n-        }\n-        return null;\n-    }\n+\t@Parameter(defaultValue = \"${project.basedir}\", readonly = true, required = true)\n+\tprotected File basedir;\n+\n+\t@Parameter(defaultValue = \"${project.compileSourceRoots}\", readonly = true, required = true)\n+\tprotected List<String> compileSourceRoots;\n+\n+\t/**\n+\t * Package name of the new function.\n+\t *\n+\t * @since 0.1.0\n+\t */\n+\t@Parameter(property = \"functions.package\")\n+\tprotected String functionPackageName;\n+\n+\t/**\n+\t * Name of the new function.\n+\t *\n+\t * @since 0.1.0\n+\t */\n+\t@Parameter(property = \"functions.name\")\n+\tprotected String functionName;\n+\n+\t/**\n+\t * Template for the new function\n+\t *\n+\t * @since 0.1.0\n+\t */\n+\t@Parameter(property = \"functions.template\")\n+\tprotected String functionTemplate;\n+\n+\tpublic String getFunctionPackageName() {\n+\t\treturn functionPackageName;\n+\t}\n+\n+\tpublic String getFunctionName() {\n+\t\treturn functionName;\n+\t}\n+\n+\tpublic String getClassName() {\n+\t\treturn getFunctionName().replace('-', '_');\n+\t}\n+\n+\tpublic String getFunctionTemplate() {\n+\t\treturn functionTemplate;\n+\t}\n+\n+\tprotected String getBasedir() {\n+\t\treturn basedir.getAbsolutePath();\n+\t}\n+\n+\tprotected String getSourceRoot() {\n+\t\treturn compileSourceRoots == null || compileSourceRoots.isEmpty()\n+\t\t\t\t? Paths.get(getBasedir(), \"src\", \"main\", \"java\").toString()\n+\t\t\t\t: compileSourceRoots.get(0);\n+\t}\n+\n+\tprotected void setFunctionPackageName(String functionPackageName) {\n+\t\tthis.functionPackageName = StringUtils.lowerCase(functionPackageName);\n+\t}\n+\n+\tprotected void setFunctionName(String functionName) {\n+\t\tthis.functionName = StringUtils.capitalize(functionName);\n+\t}\n+\n+\tprotected void setFunctionTemplate(String functionTemplate) {\n+\t\tthis.functionTemplate = functionTemplate;\n+\t}\n+\n+\t@Override\n+\tprotected void doExecute() throws Exception {\n+\t\tAddFunctionHandler handler = new AddFunctionHandler();","path":"azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AddMojo.java","position":622,"original_position":622,"commit_id":"26b6c09da6cc6d0278670c04faa48de6645ba9b0","original_commit_id":"26b6c09da6cc6d0278670c04faa48de6645ba9b0","user":{"login":"Flanker32","id":12445236,"node_id":"MDQ6VXNlcjEyNDQ1MjM2","avatar_url":"https://avatars3.githubusercontent.com/u/12445236?v=4","gravatar_id":"","url":"https://api.github.com/users/Flanker32","html_url":"https://github.com/Flanker32","followers_url":"https://api.github.com/users/Flanker32/followers","following_url":"https://api.github.com/users/Flanker32/following{/other_user}","gists_url":"https://api.github.com/users/Flanker32/gists{/gist_id}","starred_url":"https://api.github.com/users/Flanker32/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Flanker32/subscriptions","organizations_url":"https://api.github.com/users/Flanker32/orgs","repos_url":"https://api.github.com/users/Flanker32/repos","events_url":"https://api.github.com/users/Flanker32/events{/privacy}","received_events_url":"https://api.github.com/users/Flanker32/received_events","type":"User","site_admin":false},"body":"Mojo should do the job of asking for parameters and handler should only accept the inputs and generate function file","created_at":"2019-12-18T08:17:38Z","updated_at":"2019-12-18T08:17:39Z","html_url":"https://github.com/microsoft/azure-maven-plugins/pull/950#discussion_r359206511","pull_request_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/950","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/comments/359206511"},"html":{"href":"https://github.com/microsoft/azure-maven-plugins/pull/950#discussion_r359206511"},"pull_request":{"href":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/950"}}},"pull_request":{"url":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/950","id":354410228,"node_id":"MDExOlB1bGxSZXF1ZXN0MzU0NDEwMjI4","html_url":"https://github.com/microsoft/azure-maven-plugins/pull/950","diff_url":"https://github.com/microsoft/azure-maven-plugins/pull/950.diff","patch_url":"https://github.com/microsoft/azure-maven-plugins/pull/950.patch","issue_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/issues/950","number":950,"state":"open","locked":false,"title":"Refactor main logic from mojo to common","user":{"login":"andxu","id":17075863,"node_id":"MDQ6VXNlcjE3MDc1ODYz","avatar_url":"https://avatars3.githubusercontent.com/u/17075863?v=4","gravatar_id":"","url":"https://api.github.com/users/andxu","html_url":"https://github.com/andxu","followers_url":"https://api.github.com/users/andxu/followers","following_url":"https://api.github.com/users/andxu/following{/other_user}","gists_url":"https://api.github.com/users/andxu/gists{/gist_id}","starred_url":"https://api.github.com/users/andxu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andxu/subscriptions","organizations_url":"https://api.github.com/users/andxu/orgs","repos_url":"https://api.github.com/users/andxu/repos","events_url":"https://api.github.com/users/andxu/events{/privacy}","received_events_url":"https://api.github.com/users/andxu/received_events","type":"User","site_admin":false},"body":"","created_at":"2019-12-18T03:41:24Z","updated_at":"2019-12-18T08:17:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a050c084405cc2b77c027dc80df00a8cd4f0aed8","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/950/commits","review_comments_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/950/comments","review_comment_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/comments{/number}","comments_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/issues/950/comments","statuses_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/statuses/26b6c09da6cc6d0278670c04faa48de6645ba9b0","head":{"label":"microsoft:andy-common6","ref":"andy-common6","sha":"26b6c09da6cc6d0278670c04faa48de6645ba9b0","user":{"login":"microsoft","id":6154722,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYxNTQ3MjI=","avatar_url":"https://avatars2.githubusercontent.com/u/6154722?v=4","gravatar_id":"","url":"https://api.github.com/users/microsoft","html_url":"https://github.com/microsoft","followers_url":"https://api.github.com/users/microsoft/followers","following_url":"https://api.github.com/users/microsoft/following{/other_user}","gists_url":"https://api.github.com/users/microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/microsoft/subscriptions","organizations_url":"https://api.github.com/users/microsoft/orgs","repos_url":"https://api.github.com/users/microsoft/repos","events_url":"https://api.github.com/users/microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/microsoft/received_events","type":"Organization","site_admin":false},"repo":{"id":95752629,"node_id":"MDEwOlJlcG9zaXRvcnk5NTc1MjYyOQ==","name":"azure-maven-plugins","full_name":"microsoft/azure-maven-plugins","private":false,"owner":{"login":"microsoft","id":6154722,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYxNTQ3MjI=","avatar_url":"https://avatars2.githubusercontent.com/u/6154722?v=4","gravatar_id":"","url":"https://api.github.com/users/microsoft","html_url":"https://github.com/microsoft","followers_url":"https://api.github.com/users/microsoft/followers","following_url":"https://api.github.com/users/microsoft/following{/other_user}","gists_url":"https://api.github.com/users/microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/microsoft/subscriptions","organizations_url":"https://api.github.com/users/microsoft/orgs","repos_url":"https://api.github.com/users/microsoft/repos","events_url":"https://api.github.com/users/microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/microsoft/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/microsoft/azure-maven-plugins","description":"Maven plugins for Azure","fork":false,"url":"https://api.github.com/repos/microsoft/azure-maven-plugins","forks_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/forks","keys_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/keys{/key_id}","collaborators_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/teams","hooks_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/hooks","issue_events_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/issues/events{/number}","events_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/events","assignees_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/assignees{/user}","branches_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/branches{/branch}","tags_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/tags","blobs_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/git/refs{/sha}","trees_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/git/trees{/sha}","statuses_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/statuses/{sha}","languages_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/languages","stargazers_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/stargazers","contributors_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/contributors","subscribers_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/subscribers","subscription_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/subscription","commits_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/commits{/sha}","git_commits_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/git/commits{/sha}","comments_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/comments{/number}","issue_comment_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/issues/comments{/number}","contents_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/contents/{+path}","compare_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/compare/{base}...{head}","merges_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/merges","archive_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/downloads","issues_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/issues{/number}","pulls_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls{/number}","milestones_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/milestones{/number}","notifications_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/labels{/name}","releases_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/releases{/id}","deployments_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/deployments","created_at":"2017-06-29T07:52:01Z","updated_at":"2019-12-18T04:47:07Z","pushed_at":"2019-12-18T04:56:56Z","git_url":"git://github.com/microsoft/azure-maven-plugins.git","ssh_url":"git@github.com:microsoft/azure-maven-plugins.git","clone_url":"https://github.com/microsoft/azure-maven-plugins.git","svn_url":"https://github.com/microsoft/azure-maven-plugins","homepage":"","size":2315,"stargazers_count":165,"watchers_count":165,"language":"Java","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":60,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":67,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":60,"open_issues":67,"watchers":165,"default_branch":"develop"}},"base":{"label":"microsoft:feature-common","ref":"feature-common","sha":"1eefcf0bf1f367882a019edb95bd743d49436415","user":{"login":"microsoft","id":6154722,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYxNTQ3MjI=","avatar_url":"https://avatars2.githubusercontent.com/u/6154722?v=4","gravatar_id":"","url":"https://api.github.com/users/microsoft","html_url":"https://github.com/microsoft","followers_url":"https://api.github.com/users/microsoft/followers","following_url":"https://api.github.com/users/microsoft/following{/other_user}","gists_url":"https://api.github.com/users/microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/microsoft/subscriptions","organizations_url":"https://api.github.com/users/microsoft/orgs","repos_url":"https://api.github.com/users/microsoft/repos","events_url":"https://api.github.com/users/microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/microsoft/received_events","type":"Organization","site_admin":false},"repo":{"id":95752629,"node_id":"MDEwOlJlcG9zaXRvcnk5NTc1MjYyOQ==","name":"azure-maven-plugins","full_name":"microsoft/azure-maven-plugins","private":false,"owner":{"login":"microsoft","id":6154722,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYxNTQ3MjI=","avatar_url":"https://avatars2.githubusercontent.com/u/6154722?v=4","gravatar_id":"","url":"https://api.github.com/users/microsoft","html_url":"https://github.com/microsoft","followers_url":"https://api.github.com/users/microsoft/followers","following_url":"https://api.github.com/users/microsoft/following{/other_user}","gists_url":"https://api.github.com/users/microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/microsoft/subscriptions","organizations_url":"https://api.github.com/users/microsoft/orgs","repos_url":"https://api.github.com/users/microsoft/repos","events_url":"https://api.github.com/users/microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/microsoft/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/microsoft/azure-maven-plugins","description":"Maven plugins for Azure","fork":false,"url":"https://api.github.com/repos/microsoft/azure-maven-plugins","forks_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/forks","keys_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/keys{/key_id}","collaborators_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/teams","hooks_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/hooks","issue_events_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/issues/events{/number}","events_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/events","assignees_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/assignees{/user}","branches_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/branches{/branch}","tags_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/tags","blobs_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/git/refs{/sha}","trees_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/git/trees{/sha}","statuses_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/statuses/{sha}","languages_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/languages","stargazers_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/stargazers","contributors_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/contributors","subscribers_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/subscribers","subscription_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/subscription","commits_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/commits{/sha}","git_commits_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/git/commits{/sha}","comments_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/comments{/number}","issue_comment_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/issues/comments{/number}","contents_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/contents/{+path}","compare_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/compare/{base}...{head}","merges_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/merges","archive_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/downloads","issues_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/issues{/number}","pulls_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls{/number}","milestones_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/milestones{/number}","notifications_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/labels{/name}","releases_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/releases{/id}","deployments_url":"https://api.github.com/repos/microsoft/azure-maven-plugins/deployments","created_at":"2017-06-29T07:52:01Z","updated_at":"2019-12-18T04:47:07Z","pushed_at":"2019-12-18T04:56:56Z","git_url":"git://github.com/microsoft/azure-maven-plugins.git","ssh_url":"git@github.com:microsoft/azure-maven-plugins.git","clone_url":"https://github.com/microsoft/azure-maven-plugins.git","svn_url":"https://github.com/microsoft/azure-maven-plugins","homepage":"","size":2315,"stargazers_count":165,"watchers_count":165,"language":"Java","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":60,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":67,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":60,"open_issues":67,"watchers":165,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/950"},"html":{"href":"https://github.com/microsoft/azure-maven-plugins/pull/950"},"issue":{"href":"https://api.github.com/repos/microsoft/azure-maven-plugins/issues/950"},"comments":{"href":"https://api.github.com/repos/microsoft/azure-maven-plugins/issues/950/comments"},"review_comments":{"href":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/950/comments"},"review_comment":{"href":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/microsoft/azure-maven-plugins/pulls/950/commits"},"statuses":{"href":"https://api.github.com/repos/microsoft/azure-maven-plugins/statuses/26b6c09da6cc6d0278670c04faa48de6645ba9b0"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"Flanker32"}}