package org.springframework.roo.classpath.operations;
import static org.springframework.roo.shell.OptionContexts.INTERFACE;
import static org.springframework.roo.shell.OptionContexts.SUPERCLASS;
import static org.springframework.roo.shell.OptionContexts.UPDATE_PROJECT;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.classpath.scanner.MemberDetailsScanner;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.project.LogicalPath;
import org.springframework.roo.shell.CliAvailabilityIndicator;
import org.springframework.roo.shell.CliCommand;
import org.springframework.roo.shell.CliOption;
import org.springframework.roo.shell.CommandMarker;
import org.springframework.roo.shell.ShellContext;
import java.util.Set;
/**
* Shell commands for creating classes, interfaces, and enums.
*
* @author Ben Alex
* @author Alan Stewart
* @since 1.0
*/
@Component
@Service
public class ClasspathCommands implements CommandMarker {
@Reference
private ClasspathOperations classpathOperations;
@Reference
private TypeLocationService typeLocationService;
@Reference
private MemberDetailsScanner memberDetailsScanner;
@CliCommand(value = "class", help = "Creates a new Java class source file in any project path")
public void createClass(
@CliOption(key = "class", optionContext = UPDATE_PROJECT, mandatory = true,
help = "The name of the class to create. If you consider "
+ "it necessary, you can also specify the package (base package can be specified "
+ "with `~`). Ex.: `--class ~.domain.MyClass`. You can specify module as well, if "
+ "necessary. Ex.: `--class model:~.domain.MyClass`. When working with a "
+ "multi-module project, if module is not specified the class will be created "
+ "in the module which has the focus.") final JavaType name,
@CliOption(
key = "rooAnnotations",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether the generated class should have common Roo annotations (`@RooToString`, `@RooEquals` and `@RooSerializable`). "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean rooAnnotations,
@CliOption(key = "path", mandatory = false,
unspecifiedDefaultValue = "FOCUSED:SRC_MAIN_JAVA",
specifiedDefaultValue = "FOCUSED:SRC_MAIN_JAVA",
help = "Source directory to create the class in. Default: [FOCUSED-MODULE]/src/main/java") final LogicalPath path,
@CliOption(
key = "extends",
mandatory = false,
unspecifiedDefaultValue = "java.lang.Object",
optionContext = SUPERCLASS,
help = "The superclass fully qualified name. Default if option not present: `java.lang.Object`.") final JavaType superclass,
@CliOption(key = "implements", mandatory = false, optionContext = INTERFACE,
help = "The interface to implement") final JavaType implementsType,
@CliOption(
key = "abstract",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether the generated class should be marked as abstract. Default if option present: `true`; default if option not present: `false`.") final boolean createAbstract,
@CliOption(
key = "permitReservedWords",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates whether reserved words are ignored by Roo. Default if option present: `true`; default if option not present: `false`.") final boolean permitReservedWords,
ShellContext shellContext) {
// Check if already exists a class with same name
String physicalTypeIdentifier = typeLocationService.getPhysicalTypeIdentifier(name);
if (physicalTypeIdentifier != null && !shellContext.isForce()) {
throw new IllegalArgumentException(
String
.format(
"The class '%s' already exists and cannot be created. Use '--force' parameter to overrite it.",
name));
}
classpathOperations.createClass(name, rooAnnotations, path, superclass, implementsType,
createAbstract, permitReservedWords);
}
@CliCommand(value = "constructor", help = "Creates a class constructor.")
public void createConstructor(
@CliOption(
key = "class",
mandatory = false,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to receive this constructor. If you consider it necessary, "
+ "you can also specify the package (base package can be specified with `~`). "
+ "Ex.: `--class ~.domain.MyEntity`. You can specify module as well, if necessary. "
+ "Ex.: `--class model:~.domain.MyEntity`. When working with a multi-module project, "
+ "if module is not specified, it is assumed that the class is in the module that has "
+ "set the focus. If this param is not specified, it is assumed that the target class "
+ "is the one focused.") final JavaType name,
@CliOption(
key = "fields",
mandatory = false,
specifiedDefaultValue = "",
optionContext = "constructor-fields",
help = "The fields to include in the constructor. Multiple field names must be a double-quoted list separated by spaces") final Set<String> fields) {
classpathOperations.createConstructor(name, fields);
}
@CliCommand(value = "enum type",
help = "Creates a new Java enum source file in any project path.")
public void createEnum(
@CliOption(
key = "class",
optionContext = UPDATE_PROJECT,
mandatory = true,
help = "The name of the enum class to create. If you consider it necessary, you can also specify "
+ "the package (base package can be specified with `~`). Ex.: `--class ~.domain.MyEnumClass`. "
+ "You can specify module as well, if necessary. Ex.: `--class model:~.domain.MyEnumClass`. "
+ "When working with a multi-module project, if module is not specified the projection will "
+ "be created in the module which has the focus.") final JavaType name,
@CliOption(key = "path", mandatory = false,
unspecifiedDefaultValue = "FOCUSED:SRC_MAIN_JAVA",
specifiedDefaultValue = "FOCUSED:SRC_MAIN_JAVA",
help = "Source directory where create the enum. "
+ "Default: _[FOCUSED-MODULE]/src/main/java_") final LogicalPath path,
@CliOption(key = "permitReservedWords", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates whether reserved words are ignored by Roo. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean permitReservedWords,
ShellContext shellContext) {
// Check if already exists a class with same name
String physicalTypeIdentifier = typeLocationService.getPhysicalTypeIdentifier(name);
if (physicalTypeIdentifier != null && !shellContext.isForce()) {
throw new IllegalArgumentException(
String
.format(
"The enum type '%s' already exists and cannot be created. Use '--force' parameter to overrite it.",
name));
}
classpathOperations.createEnum(name, path, permitReservedWords);
}
@CliCommand(value = "interface",
help = "Creates a new Java interface source file in any project path.")
public void createInterface(
@CliOption(
key = "class",
optionContext = UPDATE_PROJECT,
mandatory = true,
help = "The name of the class to create. If you consider it necessary, you can also specify "
+ "the package (base package can be specified with `~`). Ex.: `--class ~.domain.MyClass`. "
+ "You can specify module as well, if necessary. Ex.: `--class model:~.domain.MyClass`. "
+ "When working with a multi-module project, if module is not specified the class will "
+ "be created in the module which has the focus.") final JavaType name,
@CliOption(key = "path", mandatory = false,
unspecifiedDefaultValue = "FOCUSED:SRC_MAIN_JAVA",
specifiedDefaultValue = "FOCUSED:SRC_MAIN_JAVA",
help = "Source directory to create the interface in. "
+ "Default: _[FOCUSED-MODULE]/src/main/java_.") final LogicalPath path,
@CliOption(key = "permitReservedWords", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates whether reserved words are ignored by Roo. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean permitReservedWords,
ShellContext shellContext) {
// Check if already exists a class with same name
String physicalTypeIdentifier = typeLocationService.getPhysicalTypeIdentifier(name);
if (physicalTypeIdentifier != null && !shellContext.isForce()) {
throw new IllegalArgumentException(
String
.format(
"The interface '%s' already exists and cannot be created. Use '--force' parameter to overrite it.",
name));
}
classpathOperations.createInterface(name, path, permitReservedWords);
}
@CliCommand(value = "enum constant", help = "Inserts a new enum constant into an enum class.")
public void enumConstant(
@CliOption(key = "name", mandatory = true,
help = "The name of the constant. It will converted to upper case automatically.") final JavaSymbolName fieldName,
@CliOption(
key = "class",
mandatory = false,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "TThe name of the enum class to receive this constant. When working on a mono module project, "
+ "simply specify the name of the class in which the new constant will be included. If you "
+ "consider it necessary, you can also specify the package. Ex.: `--class ~.domain.MyEnumClass` "
+ "(where `~` is the base package). When working with multiple modules, you should specify the "
+ "name of the class and the module where it is. Ex.: `--class model:~.domain.MyEnumClass`. "
+ "If the module is not specified, it is assumed that the class is in the module which has the "
+ "focus. " + "Default if option not present: the class focused by Roo shell.") final JavaType name,
@CliOption(key = "permitReservedWords", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates whether reserved words are ignored by Roo. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean permitReservedWords) {
classpathOperations.enumConstant(name, fieldName, permitReservedWords);
}
@CliCommand(value = "focus", help = "Changes Roo Shell focus to a different type in the project.")
public void focus(
@CliOption(
key = "class",
mandatory = true,
optionContext = UPDATE_PROJECT,
help = "The type to focus on. When working on a mono module project, simply specify the name of"
+ " the class in which the new constant will be included. If you consider it necessary, you"
+ " can also specify the package. Ex.: `--class ~.domain.MyEnumClass` (where `~` is the "
+ "base package). When working with multiple modules, you should specify the name of the "
+ "class and the module where it is. Ex.: `--class model:~.domain.MyEnumClass`. If the "
+ "module is not specified, it is assumed that the class is in the module which has the "
+ "focus.") final JavaType type) {
classpathOperations.focus(type);
}
@CliAvailabilityIndicator({"class", "constructor", "interface", "enum type", "enum constant",
"focus"})
public boolean isProjectAvailable() {
return classpathOperations.isProjectAvailable();
}
}