Skip to content

Commit afd4153

Browse files
committed
Refactor how to create an application from a command object programatically
1 parent e198571 commit afd4153

File tree

2 files changed

+71
-47
lines changed

2 files changed

+71
-47
lines changed

grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreateAppCommand.groovy

Lines changed: 70 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class CreateAppCommand extends ArgumentCompletingCommand implements ProfileRepos
5858
Map<String, String> variables = [:]
5959
String appname
6060
String groupname
61+
String defaultpackagename
6162
File targetDirectory
6263
List<String> binaryFileExtensions = ['png','gif','jpg','jpeg','ico','icns','pdf','zip','jar','class']
6364

@@ -134,27 +135,27 @@ class CreateAppCommand extends ArgumentCompletingCommand implements ProfileRepos
134135
return super.complete(commandLine, desc, candidates, cursor)
135136
}
136137

137-
@Override
138-
boolean handle(ExecutionContext executionContext) {
139-
if(profileRepository == null) throw new IllegalStateException("Property 'profileRepository' must be set")
140-
141-
142-
def mainCommandLine = executionContext.commandLine
143-
def profileName = evaluateProfileName(mainCommandLine)
138+
boolean handle(CreateAppCommandObject cmd) {
139+
if (profileRepository == null) throw new IllegalStateException("Property 'profileRepository' must be set")
144140

141+
String profileName = cmd.profileName
145142
Profile profileInstance = profileRepository.getProfile(profileName)
146-
if( !validateProfile(profileInstance, profileName, executionContext)) {
143+
if (!validateProfile(profileInstance, profileName)) {
147144
return false
148145
}
149-
List<Feature> features = evaluateFeatures(profileInstance, mainCommandLine).toList()
150-
if(profileInstance) {
151146

152-
if( !initializeVariables(profileInstance, mainCommandLine) ) {
147+
List<Feature> features = evaluateFeatures(profileInstance, cmd.features).toList()
148+
149+
if (profileInstance) {
150+
if (!initializeGroupAndName(cmd.appName, cmd.inplace)) {
153151
return false
154152
}
155153

156-
Path appFullDirectory = Paths.get(executionContext.baseDir.path, appname)
157-
targetDirectory = mainCommandLine.hasOption('inplace') || GrailsCli.isInteractiveModeActive() ? new File(".").canonicalFile : appFullDirectory.toFile()
154+
initializeVariables(cmd.appName, defaultpackagename, profileName, cmd.grailsVersion)
155+
156+
Path appFullDirectory = Paths.get(cmd.baseDir.path, appname)
157+
targetDirectory = cmd.inplace ? new File(".").canonicalFile : appFullDirectory.toFile()
158+
158159
File applicationYmlFile = new File(targetDirectory, "grails-app/conf/application.yml")
159160

160161
def profiles = profileRepository.getProfileAndDependencies(profileInstance)
@@ -197,7 +198,7 @@ class CreateAppCommand extends ArgumentCompletingCommand implements ProfileRepos
197198
}
198199

199200
replaceBuildTokens(profileName, profileInstance, features, targetDirectory)
200-
executionContext.console.addStatus(
201+
GrailsConsole.instance.addStatus(
201202
"${name == 'create-plugin' ? 'Plugin' : 'Application'} created at $targetDirectory.absolutePath"
202203
)
203204
GrailsCli.tiggerAppLoad()
@@ -209,15 +210,39 @@ class CreateAppCommand extends ArgumentCompletingCommand implements ProfileRepos
209210
}
210211
}
211212

212-
protected boolean validateProfile(Profile profileInstance, String profileName, ExecutionContext executionContext) {
213+
@Override
214+
boolean handle(ExecutionContext executionContext) {
215+
CommandLine commandLine = executionContext.commandLine
216+
217+
String profileName = evaluateProfileName(commandLine)
218+
219+
boolean inPlace = commandLine.hasOption('inplace') || GrailsCli.isInteractiveModeActive()
220+
String appName = commandLine.remainingArgs ? commandLine.remainingArgs[0] : ""
221+
222+
List<String> features = commandLine.optionValue("features")?.toString()?.split(',')?.toList()
223+
224+
CreateAppCommandObject cmd = new CreateAppCommandObject(
225+
appName: appName,
226+
baseDir: executionContext.baseDir,
227+
profileName: profileName,
228+
grailsVersion: Environment.getPackage().getImplementationVersion() ?: GRAILS_VERSION_FALLBACK_IN_IDE_ENVIRONMENTS_FOR_RUNNING_TESTS,
229+
features: features,
230+
inplace: inPlace
231+
)
232+
233+
return this.handle(cmd)
234+
}
235+
236+
protected boolean validateProfile(Profile profileInstance, String profileName) {
213237
if (profileInstance == null) {
214-
executionContext.console.error("Profile not found for name [$profileName]")
238+
GrailsConsole.instance.error("Profile not found for name [$profileName]")
215239
return false
216240
}
217241
return true
218242
}
219243

220244
private Map<URL, File> unzippedDirectories = new LinkedHashMap<URL, File>()
245+
221246
@CompileDynamic
222247
protected File unzipProfile(AntBuilder ant, Resource location) {
223248

@@ -321,15 +346,15 @@ class CreateAppCommand extends ArgumentCompletingCommand implements ProfileRepos
321346
mainCommandLine.optionValue('profile')?.toString() ?: getDefaultProfile()
322347
}
323348

324-
protected Iterable<Feature> evaluateFeatures(Profile profile, CommandLine commandLine) {
325-
String[] requestedFeatures = commandLine.optionValue("features")?.toString()?.split(',')
326-
if(requestedFeatures) {
327-
List<String> requestedFeaturesList = requestedFeatures.toList()
349+
protected Iterable<Feature> evaluateFeatures(Profile profile, List<String> requestedFeatures) {
350+
if (requestedFeatures) {
328351
List<String> allFeatureNames = profile.features*.name
329-
List<String> validFeatureNames = requestedFeaturesList.intersect(allFeatureNames)
330-
requestedFeaturesList.removeAll(allFeatureNames)
331-
requestedFeaturesList.each { String invalidFeature ->
332-
List possibleSolutions = allFeatureNames.findAll { it.substring(0, 2) == invalidFeature.substring(0, 2) }
352+
List<String> validFeatureNames = requestedFeatures.intersect(allFeatureNames)
353+
requestedFeatures.removeAll(allFeatureNames)
354+
requestedFeatures.each { String invalidFeature ->
355+
List possibleSolutions = allFeatureNames.findAll {
356+
it.substring(0, 2) == invalidFeature.substring(0, 2)
357+
}
333358
StringBuilder warning = new StringBuilder("Feature ${invalidFeature} does not exist in the profile ${profile.name}!")
334359
if (possibleSolutions) {
335360
warning.append(" Possible solutions: ")
@@ -348,7 +373,6 @@ class CreateAppCommand extends ArgumentCompletingCommand implements ProfileRepos
348373
ProfileRepository.DEFAULT_PROFILE_NAME
349374
}
350375

351-
352376
private void appendToYmlSubDocument(File applicationYmlFile, String previousApplicationYml) {
353377
String newApplicationYml = applicationYmlFile.text
354378
if(previousApplicationYml && newApplicationYml != previousApplicationYml) {
@@ -361,49 +385,45 @@ class CreateAppCommand extends ArgumentCompletingCommand implements ProfileRepos
361385
applicationYmlFile.text = appended.toString()
362386
}
363387
}
364-
365-
protected boolean initializeVariables(Profile profile, CommandLine commandLine) {
366-
String defaultPackage
367388

368-
def args = commandLine.getRemainingArgs()
369-
boolean inPlace = commandLine.hasOption('inplace') || GrailsCli.isInteractiveModeActive()
370-
371-
if(!args && !inPlace) {
389+
protected boolean initializeGroupAndName(String appName, boolean inplace) {
390+
if (!appName && !inplace) {
372391
GrailsConsole.getInstance().error("Specify an application name or use --inplace to create an application in the current directory")
373392
return false
374393
}
375-
String groupAndAppName = args ? args[0] : null
376-
if(inPlace) {
394+
String groupAndAppName = appName
395+
if(inplace) {
377396
appname = new File(".").canonicalFile.name
378397
if(!groupAndAppName) {
379398
groupAndAppName = appname
380399
}
381400
}
382-
401+
383402
if(!groupAndAppName) {
384403
GrailsConsole.getInstance().error("Specify an application name or use --inplace to create an application in the current directory")
385404
return false
386405
}
387406

388407
try {
389-
defaultPackage = establishGroupAndAppName(groupAndAppName)
408+
defaultpackagename = establishGroupAndAppName(groupAndAppName)
390409
} catch (IllegalArgumentException e ) {
391410
GrailsConsole.instance.error(e.message)
392411
return false
393412
}
413+
}
394414

395-
415+
private void initializeVariables(String appname, String defaultPackage, String profileName, String grailsVersion) {
396416
variables.APPNAME = appname
397417

398418
variables['grails.codegen.defaultPackage'] = defaultPackage
399-
variables['grails.codegen.defaultPackage.path'] = defaultPackage.replace('.', '/')
419+
variables['grails.codegen.defaultPackage.path'] = defaultPackage.replace('.', '/')
400420

401421
def projectClassName = GrailsNameUtils.getNameFromScript(appname)
402422
variables['grails.codegen.projectClassName'] = projectClassName
403423
variables['grails.codegen.projectNaturalName'] = GrailsNameUtils.getNaturalName(projectClassName)
404424
variables['grails.codegen.projectName'] = GrailsNameUtils.getScriptName(projectClassName)
405-
variables['grails.profile'] = profile.name
406-
variables['grails.version'] = Environment.getPackage().getImplementationVersion() ?: GRAILS_VERSION_FALLBACK_IN_IDE_ENVIRONMENTS_FOR_RUNNING_TESTS
425+
variables['grails.profile'] = profileName
426+
variables['grails.version'] = grailsVersion
407427
variables['grails.app.name'] = appname
408428
variables['grails.app.group'] = groupname
409429
}
@@ -424,7 +444,7 @@ class CreateAppCommand extends ArgumentCompletingCommand implements ProfileRepos
424444
}
425445

426446
private String createValidPackageName() {
427-
String defaultPackage = appname.split(/[-]+/).collect { String token -> (token.toLowerCase().toCharArray().findAll { char ch -> Character.isJavaIdentifierPart(ch) } as char[]) as String }.join('.')
447+
String defaultPackage = appname.split(/[-]+/).collect { String token -> (token.toLowerCase().toCharArray().findAll { char ch -> Character.isJavaIdentifierPart(ch) } as char[]) as String }.join('.')
428448
if(!GrailsNameUtils.isValidJavaPackage(defaultPackage)) {
429449
throw new IllegalArgumentException("Cannot create a valid package name for [$appname]. Please specify a name that is also a valid Java package.")
430450
}
@@ -530,4 +550,13 @@ class CreateAppCommand extends ArgumentCompletingCommand implements ProfileRepos
530550

531551
return v ? "${artifact.groupId}:${artifact.artifactId}:${v}" : "${artifact.groupId}:${artifact.artifactId}"
532552
}
553+
554+
static class CreateAppCommandObject {
555+
String appName
556+
File baseDir
557+
String profileName
558+
String grailsVersion
559+
List<String> features
560+
boolean inplace = false
561+
}
533562
}

grails-shell/src/main/groovy/org/grails/cli/profile/commands/CreatePluginCommand.groovy

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,8 @@
1717
package org.grails.cli.profile.commands
1818

1919
import groovy.transform.CompileStatic
20-
import org.grails.build.parsing.CommandLine
2120
import org.grails.cli.profile.ExecutionContext
2221
import org.grails.cli.profile.Profile
23-
24-
2522
/**
2623
* A command for creating a plugin
2724
*
@@ -50,16 +47,14 @@ class CreatePluginCommand extends CreateAppCommand {
5047
@Override
5148
protected String getDefaultProfile() { "web-plugin" }
5249

53-
@Override
5450
protected boolean validateProfile(Profile profileInstance, String profileName, ExecutionContext executionContext) {
55-
5651
def pluginProfile = profileInstance.extends.find() { Profile parent -> parent.name == 'plugin' }
5752
if(profileName != 'plugin' && pluginProfile == null) {
5853
executionContext.console.error("No valid plugin profile found for name [$profileName]")
5954
return false
6055
}
6156
else {
62-
return super.validateProfile(profileInstance, profileName, executionContext)
57+
return super.validateProfile(profileInstance, profileName)
6358
}
6459
}
6560
}

0 commit comments

Comments
 (0)