diff --git a/src/Utils/index.ts b/src/Utils/index.ts index 009229a..84b0b00 100644 --- a/src/Utils/index.ts +++ b/src/Utils/index.ts @@ -114,6 +114,10 @@ export function artifactIdValidation(value: string): string | undefined { return (/^[a-z_][a-z0-9_]*(-[a-z_][a-z0-9_]*)*$/.test(value)) ? undefined : "Invalid Artifact Id"; } +export function packageNameValidation(value: string): string { + return (/^[a-z_][a-z0-9_]*(\.[a-z0-9_]+)*$/.test(value)) ? null : "Invalid Package Name"; +} + export async function readXmlContent(xml: string, options?: {}): Promise { const opts: {} = Object.assign({ explicitArray: true }, options); return new Promise<{}>( diff --git a/src/handler/GenerateProjectHandler.ts b/src/handler/GenerateProjectHandler.ts index 2fe679c..bbb32a8 100644 --- a/src/handler/GenerateProjectHandler.ts +++ b/src/handler/GenerateProjectHandler.ts @@ -15,6 +15,7 @@ import { BaseHandler } from "./BaseHandler"; import { IDefaultProjectData, IProjectMetadata, IStep, ParentFolder } from "./HandlerInterfaces"; import { SpecifyArtifactIdStep } from "./SpecifyArtifactIdStep"; import { SpecifyGroupIdStep } from "./SpecifyGroupIdStep"; +import { SpecifyPackageNameStep } from "./SpecifyPackageNameStep"; import { SpecifyServiceUrlStep } from "./SpecifyServiceUrlStep"; import { ProjectType } from "../model"; @@ -47,6 +48,7 @@ export class GenerateProjectHandler extends BaseHandler { SpecifyArtifactIdStep.getInstance().resetDefaultInput(); SpecifyGroupIdStep.getInstance().resetDefaultInput(); + SpecifyPackageNameStep.getInstance().resetDefaultInput(); while (step !== undefined) { step = await step.execute(operationId, this.metadata); } @@ -88,6 +90,7 @@ export class GenerateProjectHandler extends BaseHandler { `javaVersion=${this.metadata.javaVersion}`, `groupId=${this.metadata.groupId}`, `artifactId=${this.metadata.artifactId}`, + `packageName=${this.metadata.packageName}`, `name=${this.metadata.artifactId}`, `packaging=${this.metadata.packaging}`, `bootVersion=${this.metadata.bootVersion}`, diff --git a/src/handler/HandlerInterfaces.ts b/src/handler/HandlerInterfaces.ts index 96b6f8c..7099b26 100644 --- a/src/handler/HandlerInterfaces.ts +++ b/src/handler/HandlerInterfaces.ts @@ -16,6 +16,7 @@ export interface IProjectMetadata { javaVersion?: string; groupId?: string; artifactId?: string; + packageName?: string; packaging?: string; bootVersion?: string; dependencies?: IDependenciesItem; diff --git a/src/handler/SpecifyArtifactIdStep.ts b/src/handler/SpecifyArtifactIdStep.ts index a37432c..8d6e148 100644 --- a/src/handler/SpecifyArtifactIdStep.ts +++ b/src/handler/SpecifyArtifactIdStep.ts @@ -4,7 +4,7 @@ import { workspace } from "vscode"; import { instrumentOperationStep } from "vscode-extension-telemetry-wrapper"; import { IInputMetaData, IProjectMetadata, IStep } from "./HandlerInterfaces"; -import { SpecifyPackagingStep } from "./SpecifyPackagingStep"; +import { SpecifyPackageNameStep } from "./SpecifyPackageNameStep"; import { createInputBox } from "./utils"; export class SpecifyArtifactIdStep implements IStep { @@ -34,7 +34,7 @@ export class SpecifyArtifactIdStep implements IStep { } public getNextStep(): IStep | undefined { - return SpecifyPackagingStep.getInstance(); + return SpecifyPackageNameStep.getInstance(); } public async execute(operationId: string, projectMetadata: IProjectMetadata): Promise { diff --git a/src/handler/SpecifyPackageNameStep.ts b/src/handler/SpecifyPackageNameStep.ts new file mode 100644 index 0000000..9ba2eb0 --- /dev/null +++ b/src/handler/SpecifyPackageNameStep.ts @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +import { instrumentOperationStep } from "vscode-extension-telemetry-wrapper"; +import { IInputMetaData, IProjectMetadata, IStep } from "./HandlerInterfaces"; +import { SpecifyPackagingStep } from "./SpecifyPackagingStep"; +import { createInputBox } from "./utils"; + +export class SpecifyPackageNameStep implements IStep { + + public static getInstance(): SpecifyPackageNameStep { + return SpecifyPackageNameStep.specifyPackageNameStep; + } + + private static specifyPackageNameStep: SpecifyPackageNameStep = new SpecifyPackageNameStep(); + + private defaultInput: string; + + constructor() { + this.resetDefaultInput(); + } + + public getDefaultInput(): string { + return this.defaultInput; + } + + public setDefaultInput(defaultInput: string): void { + this.defaultInput = defaultInput; + } + + public resetDefaultInput(): void { + this.defaultInput = null; + } + + public getNextStep(): IStep | undefined { + return SpecifyPackagingStep.getInstance(); + } + + public async execute(operationId: string, projectMetadata: IProjectMetadata): Promise { + if (!await instrumentOperationStep(operationId, "PackageName", this.specifyPackageName)(projectMetadata)) { + return projectMetadata.pickSteps.pop(); + } + return this.getNextStep(); + } + + private async specifyPackageName(projectMetadata: IProjectMetadata): Promise { + const recommendedPackageName = `${projectMetadata.groupId}.${projectMetadata.artifactId}`.replace("-", "_"); + + const inputMetaData: IInputMetaData = { + metadata: projectMetadata, + title: "Spring Initializr: Input Package Name", + pickStep: SpecifyPackageNameStep.getInstance(), + placeholder: "e.g. com.example", + prompt: "Input Package Name for your project.", + defaultValue: recommendedPackageName || SpecifyPackageNameStep.getInstance().defaultInput + }; + return await createInputBox(inputMetaData); + } +} diff --git a/src/handler/utils.ts b/src/handler/utils.ts index 97a57b6..9de4dd9 100644 --- a/src/handler/utils.ts +++ b/src/handler/utils.ts @@ -5,7 +5,7 @@ import * as vscode from "vscode"; import { Disposable, InputBox, QuickInputButtons, QuickPick, window } from "vscode"; import { OperationCanceledError } from "../Errors"; import { Identifiable } from "../model/Metadata"; -import { artifactIdValidation, groupIdValidation } from "../Utils"; +import { artifactIdValidation, groupIdValidation, packageNameValidation } from "../Utils"; import { IHandlerItem, IInputMetaData, IPickMetadata, IProjectMetadata } from "./HandlerInterfaces"; import { SpecifyArtifactIdStep } from "./SpecifyArtifactIdStep"; import { SpecifyBootVersionStep } from "./SpecifyBootVersionStep"; @@ -14,6 +14,7 @@ import { SpecifyJavaVersionStep } from "./SpecifyJavaVersionStep"; import { SpecifyLanguageStep } from "./SpecifyLanguageStep"; import { SpecifyPackagingStep } from "./SpecifyPackagingStep"; import { SpecifyServiceUrlStep } from "./SpecifyServiceUrlStep"; +import { SpecifyPackageNameStep } from "./SpecifyPackageNameStep"; const DEFAULT_SERVICE_URL: string = "https://start.spring.io"; @@ -133,6 +134,8 @@ export async function createInputBox(inputMetaData: IInputMetaData): Promise