package org.springframework.roo.addon.field.addon;
import static org.springframework.roo.model.JpaJavaType.EMBEDDABLE;
import static org.springframework.roo.shell.OptionContexts.ENUMERATION;
import static org.springframework.roo.shell.OptionContexts.PROJECT;
import static org.springframework.roo.shell.OptionContexts.UPDATE_PROJECT;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.classpath.TypeManagementService;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.FieldMetadata;
import org.springframework.roo.classpath.operations.Cardinality;
import org.springframework.roo.classpath.operations.DateTime;
import org.springframework.roo.classpath.operations.EnumType;
import org.springframework.roo.classpath.operations.Fetch;
import org.springframework.roo.classpath.operations.jsr303.DateFieldPersistenceType;
import org.springframework.roo.classpath.operations.jsr303.UploadedFileContentType;
import org.springframework.roo.classpath.scanner.MemberDetails;
import org.springframework.roo.classpath.scanner.MemberDetailsScanner;
import org.springframework.roo.converters.LastUsed;
import org.springframework.roo.metadata.MetadataService;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.RooJavaType;
import org.springframework.roo.project.LogicalPath;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.settings.project.ProjectSettingsService;
import org.springframework.roo.shell.CliAvailabilityIndicator;
import org.springframework.roo.shell.CliCommand;
import org.springframework.roo.shell.CliOption;
import org.springframework.roo.shell.CliOptionAutocompleteIndicator;
import org.springframework.roo.shell.CliOptionMandatoryIndicator;
import org.springframework.roo.shell.CliOptionVisibilityIndicator;
import org.springframework.roo.shell.CommandMarker;
import org.springframework.roo.shell.Converter;
import org.springframework.roo.shell.ShellContext;
import org.springframework.roo.shell.converters.StaticFieldConverter;
import org.springframework.roo.support.logging.HandlerUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
/**
* Additional shell commands for the purpose of creating fields.
*
* @author Ben Alex
* @author Alan Stewart
* @author Sergio Clares
* @since 1.0
*/
@Component
@Service
public class FieldCommands implements CommandMarker {
protected final static Logger LOGGER = HandlerUtils.getLogger(FieldCommands.class);
//------------ OSGi component attributes ----------------//
private BundleContext context;
@Reference
private MemberDetailsScanner memberDetailsScanner;
@Reference
private MetadataService metadataService;
@Reference
private ProjectOperations projectOperations;
@Reference
private StaticFieldConverter staticFieldConverter;
@Reference
private TypeLocationService typeLocationService;
@Reference
private TypeManagementService typeManagementService;
@Reference
private ProjectSettingsService projectSettings;
@Reference
private LastUsed lastUsed;
private Converter<JavaType> javaTypeConverter;
// FieldCreatorProvider implementations
private List<FieldCreatorProvider> fieldCreatorProviders = new ArrayList<FieldCreatorProvider>();
private final Set<String> legalNumericPrimitives = new HashSet<String>();
protected void activate(final ComponentContext context) {
this.context = context.getBundleContext();
legalNumericPrimitives.add(Short.class.getName());
legalNumericPrimitives.add(Byte.class.getName());
legalNumericPrimitives.add(Integer.class.getName());
legalNumericPrimitives.add(Long.class.getName());
legalNumericPrimitives.add(Float.class.getName());
legalNumericPrimitives.add(Double.class.getName());
staticFieldConverter.add(Cardinality.class);
staticFieldConverter.add(Fetch.class);
staticFieldConverter.add(EnumType.class);
staticFieldConverter.add(DateTime.class);
}
protected void deactivate(final ComponentContext context) {
staticFieldConverter.remove(Cardinality.class);
staticFieldConverter.remove(Fetch.class);
staticFieldConverter.remove(EnumType.class);
staticFieldConverter.remove(DateTime.class);
legalNumericPrimitives.add(Short.class.getName());
legalNumericPrimitives.add(Byte.class.getName());
legalNumericPrimitives.add(Integer.class.getName());
legalNumericPrimitives.add(Long.class.getName());
legalNumericPrimitives.add(Float.class.getName());
legalNumericPrimitives.add(Double.class.getName());
this.context = null;
}
@CliOptionMandatoryIndicator(command = "field boolean", params = {"column"})
public boolean isColumnMandatoryForFieldBoolean(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnMandatoryForFieldBoolean(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field boolean", params = {"column"},
help = "Option 'column' is not available for this type of class")
public boolean isColumnVisibleForFieldBoolean(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnVisibleForFieldBoolean(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field boolean", params = {"transient"},
help = "Option 'transient' is not available for this type of class")
public boolean isTransientVisibleForFieldBoolean(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isTransientVisibleForFieldBoolean(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field boolean", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldBoolean(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field boolean", params = {"class"})
public boolean isClassMandatoryForFieldBoolean() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionVisibilityIndicator(command = "field boolean", params = {"assertFalse"},
help = "Option `--assertFalse` is not available if option `--assertTrue` "
+ "has already been specified.")
public boolean isAssertFalseVisibleForFieldBoolean(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isAssertFalseVisibleForFieldBoolean(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field boolean", params = {"assertTrue"},
help = "Option `--assertTrue` is not available if option `--assertFalse` "
+ "has already been specified.")
public boolean isAssertTrueVisibleForFieldBoolean(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isAssertTrueVisibleForFieldBoolean(shellContext);
}
return false;
}
@CliCommand(value = "field boolean",
help = "Adds a private boolean field to an existing Java source file.")
public void addFieldBoolean(
@CliOption(key = {"", "fieldName"}, mandatory = true, help = "The name of the field to add.") final JavaSymbolName fieldName,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module "
+ "project, simply specify the name of the class in which the field will be included."
+ " If you consider it necessary, you can also specify the package. "
+ "Ex.: `--class ~.domain.MyClass` (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.MyClass`. If the module is not specified, it "
+ "is assumed that the class is in the module which has the focus. "
+ "This option is mandatory for this command when the focus is not set to one class. "
+ "Default if option not present: the class focused by Roo shell.") final JavaType typeName,
@CliOption(key = "column", mandatory = true,
help = "The JPA @Column name. This option is only available for JPA entities and "
+ "embeddable classes. "
+ "This option is mandatory if `spring.roo.jpa.require.schema-object-name` "
+ "configuration setting exists and it's `true`.") final String column,
@CliOption(
key = "transient",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates to mark the field as transient, adding JPA `javax.persistence.Transient` "
+ "annotation. This marks the field as not persistent. "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean transientModifier,
@CliOption(key = "notNull", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value cannot be null. Adds `javax.validation.constraints.NotNull` "
+ "annotation to the field. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean notNull,
@CliOption(key = "assertFalse", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether the value of this field must be false. Adds "
+ "`javax.validation.constraints.AssertFalse` annotation to the field. "
+ "This option is not available if `--asssertTrue` has already " + "been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean assertFalse,
@CliOption(key = "assertTrue", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether the value of this field must be true. Adds "
+ "`javax.validation.constraints.AssertTrue` annotation to the field. "
+ "This option is not available if `--asssertFalse` has already "
+ "been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean assertTrue,
@CliOption(
key = "value",
mandatory = false,
help = "Inserts an optional Spring `org.springframework.beans.factory.annotation.Value` annotation with the given content, typically used for expression-driven dependency injection.") final String value,
@CliOption(key = "comment", mandatory = false, help = "An optional comment for JavaDocs") final String comment,
@CliOption(key = "primitive", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true", help = "Indicates to use the primitive type. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean primitive,
@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) {
final ClassOrInterfaceTypeDetails javaTypeDetails =
typeLocationService.getTypeDetails(typeName);
Validate.notNull(javaTypeDetails, "The type specified, '%s', doesn't exist", typeName);
checkFieldExists(fieldName, shellContext, javaTypeDetails);
getFieldCreatorProvider(typeName).createBooleanField(javaTypeDetails, primitive, fieldName,
notNull, assertFalse, assertTrue, column, comment, value, permitReservedWords,
transientModifier);
}
@CliOptionMandatoryIndicator(command = "field date", params = {"column"})
public boolean isColumnMandatoryForFieldDate(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnMandatoryForFieldDate(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field date", params = {"column"},
help = "Option 'column' is not available for this type of class")
public boolean isColumnVisibleForFieldDate(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnVisibleForFieldDate(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field date", params = {"persistenceType"},
help = "Option 'persistenceType' is not available for this type of class")
public boolean isPersistenceTypeVisibleForFieldDate(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isPersistenceTypeVisibleForFieldDate(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field date", params = {"transient"},
help = "Option 'transient' is not available for this type of class")
public boolean isTransientVisibleForFieldDate(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isTransientVisibleForFieldDate(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field date", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldDate(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field date", params = {"class"})
public boolean isClassMandatoryForFieldDate() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionVisibilityIndicator(command = "field date", params = {"future"},
help = "Option '--future' is not available when option '--past' has already "
+ "been specified.")
public boolean isFutureVisibleForFieldDate(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isFutureVisibleForFieldDate(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field date", params = {"past"},
help = "Option '--past' is not available when option '--future' has already "
+ "been specified.")
public boolean isPastVisibleForFieldDate(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isPastVisibleForFieldDate(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field date", params = {"dateFormat", "timeFormat"},
help = "Options `--dateFormat` and `--timeFormat` are not available when option "
+ "`--dateTimeFormatPattern` has already been specified.")
public boolean areDateAndTimeFormatVisibleForFieldDate(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).areDateAndTimeFormatVisibleForFieldDate(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field date", params = {"dateTimeFormatPattern"},
help = "Option `--dateTimeFormatPattern` is not available when options "
+ "`--dateFormat` or `--timeFormat` have already been specified.")
public boolean isDateTimeFormatPatternVisibleForFieldDate(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isDateTimeFormatPatternVisibleForFieldDate(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field date", params = {"notNull"},
help = "Option `--notNull` is not available when option `--nullRequired` "
+ "has already been specified.")
public boolean isNotNullVisibleForFieldDate(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNotNullVisibleForFieldDate(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field date", params = {"nullRequired"},
help = "Option `--nullRequired` is not available when option `--notNull` "
+ "has already been specified.")
public boolean isNullRequiredVisibleForFieldDate(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNullRequiredVisibleForFieldDate(shellContext);
}
return false;
}
@CliCommand(value = "field date",
help = "Adds a private date field to an existing Java source file.")
public void addFieldDateJpa(
@CliOption(key = {"", "fieldName"}, mandatory = true, help = "The name of the field to add.") final JavaSymbolName fieldName,
@CliOption(
key = "type",
mandatory = true,
optionContext = "java-date",
help = "The Java date type of the field. Its value can be `java.util.Date` or `java.util.Calendar`.") final JavaType fieldType,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module project, "
+ "simply specify the name of the class in which the field will be included. If you "
+ "consider it necessary, you can also specify the package. Ex.: `--class ~.domain.MyClass` "
+ "(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.MyClass`. "
+ "If the module is not specified, it is assumed that the class is in the module which has "
+ "the focus. "
+ "This option is mandatory for this command when the focus is not set to one class. "
+ "Default if option not present: the class focused by Roo shell.") final JavaType typeName,
@CliOption(
key = "persistenceType",
mandatory = false,
help = "The type of persistent storage to be used. It adds a `javax.persistence.TemporalType` "
+ "to a `javax.persistence.Temporal` annotation into the field. "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option not present: `TemporalType.TIMESTAMP`") final DateFieldPersistenceType persistenceType,
@CliOption(
key = "column",
mandatory = true,
help = "The JPA @Column name. "
+ "This option is mandatory if `spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`. "
+ "This option is only visible for JPA entities and embeddable classes.") final String column,
@CliOption(
key = "transient",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates to mark the field as transient, adding JPA `javax.persistence.Transient` "
+ "annotation. This marks the field as not persistent. "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option present:`true`. Default if option not present: `false`.") final boolean transientModifier,
@CliOption(
key = "notNull",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value cannot be null. Adds `javax.validation.constraints.NotNull` annotation to the field. "
+ "This option is not available if `--nullRequired` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean notNull,
@CliOption(
key = "nullRequired",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value must be null. Adds `javax.validation.constraints.Null` annotation to the field. "
+ "This option is not available if `--notNull` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean nullRequired,
@CliOption(
key = "future",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value must be in the future. Adds `field.javax.validation.constraints.Future` "
+ "annotation to the field. "
+ "This option is not available if `--past` option has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean future,
@CliOption(
key = "past",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value must be in the past. Adds `field.javax.validation.constraints.Past` "
+ "annotation to the field. "
+ "This option is not available if `--future` option has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean past,
@CliOption(key = "comment", mandatory = false, help = "An optional comment for JavaDocs.") final String comment,
@CliOption(
key = "value",
mandatory = false,
help = "Inserts an optional Spring `org.springframework.beans.factory.annotation.Value` "
+ "annotation with the given content, typically used for expression-driven dependency "
+ "injection.") final String value,
@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,
@CliOption(key = "dateFormat", mandatory = false, unspecifiedDefaultValue = "MEDIUM",
specifiedDefaultValue = "MEDIUM",
help = "Indicates the style of the date format, adding `style` attribute to "
+ "`org.springframework.format.annotation.DateTimeFormat` annotation "
+ "into the field, with date style (first character of the code). "
+ "Possible values are: `MEDIUM` (style='M-'), `NONE` (style='--') and "
+ "`SHORT` (style='S-'). "
+ "This option is not available if `--dateTimeFormatPattern` has already "
+ "been specified." + "Default: `MEDIUM`.") final DateTime dateFormat,
@CliOption(key = "timeFormat", mandatory = false, unspecifiedDefaultValue = "NONE",
specifiedDefaultValue = "NONE",
help = "Indicates the style of the time format, adding `style` attribute to "
+ "`org.springframework.format.annotation.DateTimeFormat` annotation "
+ "into the field, with time style (second character of the code). "
+ "Possible values are: `MEDIUM` (style='-M'), `NONE` (style='--') and "
+ "`SHORT` (style='-S'). "
+ "This option is not available if `--dateTimeFormatPattern` has already "
+ "been specified. " + "Default: `NONE`.") final DateTime timeFormat,
@CliOption(
key = "dateTimeFormatPattern",
mandatory = false,
help = "Indicates a 'custom' DateTime format pattern such as yyyy-MM-dd hh:mm:ss, adding "
+ "`pattern` attribute to `org.springframework.format.annotation.DateTimeFormat` "
+ "annotation into the field, with the provided value. "
+ "This option is not available if `--timeFormat` or `--dateFormat` have already "
+ "been specified.") final String pattern, ShellContext shellContext) {
final ClassOrInterfaceTypeDetails javaTypeDetails =
typeLocationService.getTypeDetails(typeName);
Validate.notNull(javaTypeDetails, "The type specified, '%s', doesn't exist", typeName);
checkFieldExists(fieldName, shellContext, javaTypeDetails);
getFieldCreatorProvider(typeName).createDateField(javaTypeDetails, fieldType, fieldName,
notNull, nullRequired, future, past, persistenceType, column, comment, dateFormat,
timeFormat, pattern, value, permitReservedWords, transientModifier);
}
@CliOptionVisibilityIndicator(command = "field embedded", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldEmbedded(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field embedded", params = {"class"})
public boolean isClassMandatoryForFieldEmbedded() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionAutocompleteIndicator(command = "field embedded", param = "type",
help = "--type option should be an entity.")
public List<String> getFieldEmbeddedAllPossibleValues(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).getFieldEmbeddedAllPossibleValues(shellContext);
}
return new ArrayList<String>();
}
@CliCommand(value = "field embedded",
help = "Adds a private `@Embedded` field to an existing Java source file. "
+ "This command is only available for entities annotated with `@RooJpaEntity` (Roo JPA "
+ "entities). Therefore, you should focus the desired entity in the Roo Shell to make "
+ "this command available.")
public void addFieldEmbeddedJpa(
@CliOption(key = {"", "fieldName"}, mandatory = true, help = "The name of the field to add.") final JavaSymbolName fieldName,
@CliOption(key = "type", mandatory = true, optionContext = PROJECT,
help = "The Java type of an embeddable class, annotated with `@Embeddable`. "
+ "Possible values are: any class in the project annotated with `@Embeddable`.") final JavaType fieldType,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module project, "
+ "simply specify the name of the class in which the field will be included. If you "
+ "consider it necessary, you can also specify the package. Ex.: `--class ~.domain.MyClass`"
+ " (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.MyClass`. If the module is not specified, it is assumed "
+ "that the class is in the module which has the focus. "
+ "This option is mandatory for this command when the focus is not set to one class. "
+ "Default if option not present: the class focused by Roo Shell.") final JavaType typeName,
@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 the field type is a JPA @Embeddable class
final ClassOrInterfaceTypeDetails cid = typeLocationService.getTypeDetails(fieldType);
Validate
.notNull(cid,
"The specified target '--type' does not exist or can not be found. Please create this type first.");
Validate.notNull(cid.getAnnotation(EMBEDDABLE),
"The field embedded command is only applicable to JPA @Embeddable field types.");
checkFieldExists(fieldName, shellContext, cid);
getFieldCreatorProvider(typeName).createEmbeddedField(typeName, fieldType, fieldName,
permitReservedWords);
}
@CliOptionMandatoryIndicator(command = "field enum", params = {"column"})
public boolean isColumnMandatoryForFieldEnum(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnMandatoryForFieldEnum(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field enum", params = {"column"},
help = "Option 'column' is not available for this type of class")
public boolean isColumnVisibleForFieldEnum(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnVisibleForFieldEnum(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field enum", params = {"enumType"},
help = "Option 'enumType' is not available for this type of class")
public boolean isEnumTypeVisibleForFieldEnum(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isEnumTypeVisibleForFieldEnum(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field enum", params = {"transient"},
help = "Option 'transient' is not available for this type of class")
public boolean isTransientVisibleForFieldEnum(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isTransientVisibleForFieldEnum(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field enum", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldEnum(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field enum", params = {"class"})
public boolean isClassMandatoryForFieldEnum() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionVisibilityIndicator(command = "field enum", params = {"notNull"},
help = "Option `--notNull` is not available when option `--nullRequired` "
+ "has already been specified.")
public boolean isNotNullVisibleForFieldEnum(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNotNullVisibleForFieldEnum(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field enum", params = {"nullRequired"},
help = "Option `--nullRequired` is not available when option `--notNull` "
+ "has already been specified.")
public boolean isNullRequiredVisibleForFieldEnum(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNullRequiredVisibleForFieldEnum(shellContext);
}
return false;
}
@CliCommand(
value = "field enum",
help = "Adds a private enum field to an existing Java source file. The field type must be a Java enum type.")
public void addFieldEnum(
@CliOption(key = {"", "fieldName"}, mandatory = true, help = "The name of the field to add.") final JavaSymbolName fieldName,
@CliOption(key = "type", mandatory = true, optionContext = ENUMERATION,
help = "The Java type of the field. It must be a Java enum type. "
+ "Possible values are: any enumerated class in the user's project.") final JavaType fieldType,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module project, "
+ "simply specify the name of the class in which the field will be included. If you "
+ "consider it necessary, you can also specify the package. Ex.: `--class ~.domain.MyClass`"
+ " (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.MyClass`."
+ " If the module is not specified, it is assumed that the class is in the module which has"
+ " the focus. "
+ "This option is mandatory for this command when the focus is not set to one class. "
+ "Default if option not present: the class focused by Roo Shell.") final JavaType typeName,
@CliOption(
key = "column",
mandatory = true,
help = "The JPA `@Column` name. "
+ "This option is mandatory if `spring.roo.jpa.require.schema-object-name` configuration "
+ "setting exists and it's `true`. "
+ "This option is only available for JPA entities and embeddable classes.") final String column,
@CliOption(
key = "transient",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates to mark the field as transient, adding JPA `javax.persistence.Transient` "
+ "annotation. This marks the field as not persistent. "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option present:`true`; default if option not present: `false`.") final boolean transientModifier,
@CliOption(
key = "enumType",
mandatory = false,
help = "Defines how the enumerated field should be persisted at a JPA level. Adds the "
+ "`javax.persistence.Enumerated` annotation to the field, with `javax.persistence.EnumType`"
+ " attribute. "
+ "Possible values are: `ORDINAL` (persists as an integer) and `STRING` "
+ "(persists as a String). "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option not present: `ORDINAL` (no `@Enumerated` - default by JPA).") final EnumType enumType,
@CliOption(
key = "notNull",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value cannot be null. Adds `javax.validation.constraints.NotNull` annotation to the field. "
+ "This option is not available if `--nullRequired` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean notNull,
@CliOption(
key = "nullRequired",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value must be null. Adds `javax.validation.constraints.Null` annotation to the field. "
+ "This option is not available if `--notNull` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean nullRequired,
@CliOption(key = "comment", mandatory = false, help = "An optional comment for JavaDocs") final String comment,
@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) {
final ClassOrInterfaceTypeDetails enumTypeCid = typeLocationService.getTypeDetails(fieldType);
Validate.notNull(enumTypeCid,
"The enum type specified, '%s', doesn't exist. Please, specify an existent enum type.",
fieldType.getSimpleTypeName());
final ClassOrInterfaceTypeDetails cid = typeLocationService.getTypeDetails(typeName);
Validate.notNull(cid,
"The class specified, '%s', doesn't exist. Please, specify an existent class.",
typeName.getSimpleTypeName());
checkFieldExists(fieldName, shellContext, cid);
getFieldCreatorProvider(typeName).createEnumField(cid, fieldType, fieldName, column, notNull,
nullRequired, enumType, comment, permitReservedWords, transientModifier);
}
@CliOptionMandatoryIndicator(command = "field number", params = {"column"})
public boolean isColumnMandatoryForFieldNumber(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnMandatoryForFieldNumber(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field number", params = {"column"},
help = "Option 'column' is not available for this type of class")
public boolean isColumnVisibleForFieldNumber(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnVisibleForFieldNumber(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field number", params = {"unique"},
help = "Option 'unique' is not available for this type of class")
public boolean isUniqueVisibleForFieldNumber(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isUniqueVisibleForFieldNumber(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field number", params = {"transient"},
help = "Option 'transient' is not available for this type of class")
public boolean isTransientVisibleForFieldNumber(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isTransientVisibleForFieldNumber(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field number", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldNumber(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field number", params = {"class"})
public boolean isClassMandatoryForFieldNumber() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionVisibilityIndicator(command = "field number", params = {"notNull"},
help = "Option `--notNull` is not available when option `--nullRequired` "
+ "has already been specified.")
public boolean isNotNullVisibleForFieldNumber(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNotNullVisibleForFieldNumber(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field number", params = {"nullRequired"},
help = "Option `--nullRequired` is not available if numeric type is primitive "
+ "or `--notNull` option has been specified.")
public boolean isNullRequiredVisibleForFieldNumber(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNullRequiredVisibleForFieldNumber(shellContext);
}
return false;
}
@CliCommand(
value = "field number",
help = "Adds a private numeric field to an existing Java source file. User can choose the field type between a wide range of numeric types.")
public void addFieldNumber(
@CliOption(key = {"", "fieldName"}, mandatory = true, help = "The name of the field to add.") final JavaSymbolName fieldName,
@CliOption(
key = "type",
mandatory = true,
optionContext = "java-number",
help = "The Java type of the field. Only numeric types allowed. "
+ "Possible values are: `java.math.BigDecimal`, `java.math.BigInteger`, `byte`, "
+ "`java.lang.Byte`, `double`, `java.lang.Double`, `float`, `java.lang.Float`, `int`, "
+ "`java.lang.Integer`, `long`, `java.lang.Long`, `java.lang.Number`, `short` and "
+ "`java.lang.Short`.") JavaType fieldType,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module "
+ "project, simply specify the name of the class in which the field will be included. "
+ "If you consider it necessary, you can also specify the package. "
+ "Ex.: `--class ~.domain.MyClass` (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.MyClass`. If the module is not specified, it is "
+ "assumed that the class is in the module which has the focus. "
+ "This option is mandatory for this command when the focus is not set to one class. "
+ "Default if option not present: the class focused by Roo Shell.") final JavaType typeName,
@CliOption(key = "column", mandatory = true, help = "The JPA `@Column` name."
+ "This option is mandatory if `spring.roo.jpa.require.schema-object-name` "
+ "configuration setting exists and it's `true`. "
+ "This option is only available for JPA entities and embeddable classes.") final String column,
@CliOption(key = "unique", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates whether to mark the field with a unique constraint. "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean unique,
@CliOption(
key = "transient",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates to mark the field as transient, adding JPA `javax.persistence.Transient` "
+ "annotation. This marks the field as not persistent. "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option present:`true`. Default if option not present: `false`.") final boolean transientModifier,
@CliOption(
key = "notNull",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value cannot be null. Adds `javax.validation.constraints.NotNull` annotation to the field. "
+ "This option is not available if `--nullRequired` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean notNull,
@CliOption(
key = "nullRequired",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value must be null. Adds `javax.validation.constraints.Null` annotation to the field. "
+ "This option is not available if `--notNull` or `--primitive` option have already been specified "
+ "with value `true` or without value. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean nullRequired,
@CliOption(
key = "decimalMin",
mandatory = false,
help = "The BigDecimal string-based representation of the minimum value. It adds to the field "
+ "`javax.validation.constraints.DecimalMin` annotation with provided value.") final String decimalMin,
@CliOption(
key = "decimalMax",
mandatory = false,
help = "The BigDecimal string based representation of the maximum value. It adds to the field "
+ "`javax.validation.constraints.DecimalMax` annotation with provided value.") final String decimalMax,
@CliOption(
key = "digitsInteger",
mandatory = false,
help = "Maximum number of integral digits accepted for this number. It creates or updates field "
+ "`javax.validation.constraints.Digits` annotation, adding `integer` attribute with the "
+ "provided value.") final Integer digitsInteger,
@CliOption(
key = "digitsFraction",
mandatory = false,
help = "Maximum number of fractional digits accepted for this number. It creates or updates field "
+ "`javax.validation.constraints.Digits` annotation, adding `fraction` attribute with the "
+ "provided value.") final Integer digitsFraction,
@CliOption(key = "min", mandatory = false,
help = "The minimum value of the numeric field. It adds "
+ "`javax.validation.constraints.Min` with provided value to the field.") final Long min,
@CliOption(key = "max", mandatory = false,
help = "The maximum value of the numeric field. It adds "
+ "`javax.validation.constraints.Max` with provided value to the field.") final Long max,
@CliOption(key = "comment", mandatory = false, help = "An optional comment for JavaDocs.") final String comment,
@CliOption(
key = "value",
mandatory = false,
help = "Inserts an optional Spring `org.springframework.beans.factory.annotation.Value` "
+ "annotation with the given content, typically used for expression-driven dependency "
+ "injection. ") final String value,
@CliOption(key = "primitive", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true", help = "Indicates to use a primitive type if possible. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean primitive,
@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) {
final ClassOrInterfaceTypeDetails javaTypeDetails =
typeLocationService.getTypeDetails(typeName);
Validate.notNull(javaTypeDetails, "The type specified, '%s', doesn't exist", typeName);
checkFieldExists(fieldName, shellContext, javaTypeDetails);
getFieldCreatorProvider(typeName).createNumericField(javaTypeDetails, fieldType, primitive,
legalNumericPrimitives, fieldName, notNull, nullRequired, decimalMin, decimalMax,
digitsInteger, digitsFraction, min, max, column, comment, unique, value,
permitReservedWords, transientModifier);
}
@CliOptionAutocompleteIndicator(command = "field reference", param = "type",
help = "--type option should be an entity.")
public List<String> getReferenceTypePossibleValues(ShellContext shellContext) {
// Get current value of class
String currentText = shellContext.getParameters().get("type");
List<String> allPossibleValues = new ArrayList<String>();
// Getting all existing entities
Set<ClassOrInterfaceTypeDetails> entitiesInProject =
typeLocationService.findClassesOrInterfaceDetailsWithAnnotation(RooJavaType.ROO_JPA_ENTITY);
for (ClassOrInterfaceTypeDetails entity : entitiesInProject) {
String name = replaceTopLevelPackageString(entity, currentText);
if (!allPossibleValues.contains(name)) {
allPossibleValues.add(name);
}
}
return allPossibleValues;
}
@CliOptionMandatoryIndicator(command = "field reference", params = {"joinColumnName"})
public boolean isColumnMandatoryForFieldReference(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnMandatoryForFieldReference(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field reference", params = {"joinColumnName"},
help = "Option 'joinColumnName' is not available for this type of class")
public boolean isJoinColumnNameVisibleForFieldReference(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isJoinColumnNameVisibleForFieldReference(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field reference", params = {"referencedColumnName"},
help = "Option 'referencedColumnName' is not available for this type of class")
public boolean isReferencedColumnNameVisibleForFieldReference(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isReferencedColumnNameVisibleForFieldReference(
shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field reference", params = {"fetch"},
help = "Option 'fetch' is not available for this type of class")
public boolean isFetchVisibleForFieldReference(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isFetchVisibleForFieldReference(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field reference", params = {"cascadeType"},
help = "Option 'cascadeType' is not available for this type of class")
public boolean isCascadeTypeVisibleForFieldReference(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isCascadeTypeVisibleForFieldReference(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field reference", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldReference(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field reference", params = {"class"})
public boolean isClassMandatoryForFieldReference() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionVisibilityIndicator(command = "field reference", params = {"notNull"},
help = "Option `--notNull` is not available when option `--nullRequired` "
+ "has already been specified.")
public boolean isNotNullVisibleForFieldReference(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNotNullVisibleForFieldReference(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field reference", params = {"nullRequired"},
help = "Option `--nullRequired` is not available if numeric type is primitive "
+ "or `--notNull` option has been specified.")
public boolean isNullRequiredVisibleForFieldReference(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNullRequiredVisibleForFieldReference(shellContext);
}
return false;
}
@CliCommand(
value = "field reference",
help = "Adds a private reference field, representing (always) a bidirectional 'one-to-one' "
+ "relation, to an existing Java source file. Therefore, this command will add as well a "
+ "'one-to-one' field on the other side of the relation. "
+ "This command is only available for entities annotated with `@RooJpaEntity`, so you "
+ "should focus the desired entity in the Roo Shell to make this command available.")
public void addFieldReferenceJpa(
@CliOption(key = {"", "fieldName"}, mandatory = true, help = "The name of the field to add.") final JavaSymbolName fieldName,
@CliOption(key = "type", mandatory = true, optionContext = PROJECT,
help = "The Java type of the entity to reference.") final JavaType fieldType,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module "
+ "project, simply specify the name of the class in which the field will be "
+ "included. If you consider it necessary, you can also specify the package. "
+ "Ex.: `--class ~.domain.MyClass` (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.MyClass`. If the module is not "
+ "specified, it is assumed that the class is in the module which has the focus. "
+ "This option is mandatory for this command when the focus is not set to one class. "
+ "Default if option not present: the class focused by Roo Shell.") final JavaType typeName,
@CliOption(key = "joinColumnName", mandatory = true,
help = "The JPA `@JoinColumn` `name` attribute. "
+ "This option is mandatory if `spring.roo.jpa.require.schema-object-name` "
+ "configuration setting exists and it's `true`. "
+ "This option is only available for JPA entities.") final String joinColumnName,
@CliOption(key = "referencedColumnName", mandatory = false,
help = "The JPA `@JoinColumn` `referencedColumnName` attribute."
+ "This option is only available for JPA entities.") final String referencedColumnName,
@CliOption(
key = "fetch",
mandatory = false,
help = "The fetch semantics at a JPA level. It adds the provided value to `fetch` attribute "
+ "of JPA `@OneToOne`. If this option is not provided, default fetch type will be `LAZY`. "
+ "Possible values are `LAZY`and `EAGER`. "
+ "This option is only available for JPA entities.") final Fetch fetch,
@CliOption(
key = "mappedBy",
mandatory = false,
help = "The field name on the referenced type which owns the relationship, which will be also "
+ "created due to bidirectional relation. If not specified, it will take the lower camel "
+ "case of the current entity (focused entity or specified in `--class` option). If the "
+ "field already exists in the related entity, command won't be executed. "
+ "This option is only available for JPA entities. "
+ "Default if not present: current entity name in lower camel case.") final JavaSymbolName mappedBy,
@CliOption(key = "aggregation", mandatory = false, specifiedDefaultValue = "true",
unspecifiedDefaultValue = "true",
help = "Whether the relationship type is 'aggregation' or 'composition'. An aggregation "
+ "relation means that children entities aren't dependent from parent entity "
+ "(current entity) and they can exist without parent entity. In the other hand, in "
+ "a composition relation the parent entity of the relationship also owns the life "
+ "cycle of related entities. The parent entity is responsible for the creation and "
+ "destruction of children entities, these being linked to a single parent entity. "
+ "A child entity cannot be in two different composition relationships. "
+ "Default: `true`.") final boolean aggregation,
@CliOption(key = "orphanRemoval", mandatory = false, specifiedDefaultValue = "true",
help = "Indicates whether to apply the remove operation to entities that have been "
+ "removed from the relationship and to cascade the remove operation to those "
+ "entities. If this relation represents a 'composition' relation and this option "
+ "is not present, `--orphanRemoval` value will be `true`. "
+ "Default if option present: `true`.") Boolean orphanRemoval,
@CliOption(
key = "notNull",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value cannot be null. Adds `javax.validation.constraints.NotNull` annotation to the field. "
+ "This option is not available if `--nullRequired` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean notNull,
@CliOption(
key = "nullRequired",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value must be null. Adds `javax.validation.constraints.Null` annotation to the field. "
+ "This option is not available if `--notNull` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean nullRequired,
@CliOption(key = "comment", mandatory = false, help = "An optional comment for JavaDocs.") final String comment,
@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,
@CliOption(
key = "entityFormatExpression",
mandatory = false,
help = "The SpEL expression used to format the related entity when showing it in presentation layer e.g. "
+ "`{#fieldA} {#fieldB}`. It adds the `value` attribute to `io.springlets.format.EntityFormat` "
+ "annotation.") String formatExpression,
@CliOption(
key = "entityFormatMessage",
mandatory = false,
help = "The message key used to obtain a localized SpEL expression to format the related entity when "
+ "showing it in presentation layer. It adds the `message` attribute to "
+ "`io.springlets.format.EntityFormat` annotation and creates a message in all message bundles "
+ "with the provided key. Message value should be modified by developer.") String formatMessage,
// @CliOption(
// key = "cascadeType",
// mandatory = false,
// help = "CascadeType. Possible values are ALL, DETACH, MERGE, PERSIST, REFRESH and REMOVE.") final Cascade cascadeType,
ShellContext shellContext) {
// TODO support multiple cascade type
getFieldCreatorProvider(typeName)
.createReferenceField(typeName, fieldType, fieldName, aggregation, mappedBy, null, notNull,
joinColumnName, referencedColumnName, fetch, comment, permitReservedWords,
orphanRemoval, shellContext.isForce(), formatExpression, formatMessage);
}
@CliOptionMandatoryIndicator(command = "field set", params = {"joinColumnName"})
public boolean isColumnMandatoryForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isJoinColumnNameMandatoryForFieldSet(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field set", params = {"joinColumnName"},
help = "Option 'joinColumnName' is not available for this type of class")
public boolean isJoinColumnNameVisibleForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isJoinColumnNameVisibleForFieldSet(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field set", params = {"referencedColumnName"},
help = "Option 'referencedColumnName' is not available for this type of class")
public boolean isReferencedColumnNameVisibleForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isReferencedColumnNameVisibleForFieldSet(shellContext);
}
return false;
}
@CliOptionMandatoryIndicator(command = "field set", params = {"joinColumns", "referencedColumns",
"inverseJoinColumns", "inverseReferencedColumns"})
public boolean areJoinTableParamsMandatoryForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).areJoinTableParamsMandatoryForFieldSet(shellContext);
}
return false;
}
@CliOptionMandatoryIndicator(command = "field set", params = {"joinTable"})
public boolean isJoinTableMandatoryForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isJoinTableMandatoryForFieldSet(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field set", params = {"joinColumns",
"referencedColumns", "inverseJoinColumns", "inverseReferencedColumns"},
help = "Options --joinColumns, --referencedColumns, --inverseJoinColumns and "
+ "--inverseReferencedColumns must be used with a specific --joinTable option.")
public boolean areJoinTableParamsVisibleForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).areJoinTableParamsVisibleForFieldSet(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field set", params = {"mappedBy"},
help = "Option 'mappedBy' is not available for this type of class")
public boolean isMappedByVisibleForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isMappedByVisibleForFieldSet(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field set", params = {"cardinality"},
help = "Option 'cardinality' is not available for this type of class")
public boolean isCardinalityVisibleForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isCardinalityVisibleForFieldSet(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field set", params = {"fetch"},
help = "Option 'fetch' is not available for this type of class")
public boolean isFetchVisibleForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isFetchVisibleForFieldSet(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field set", params = {"joinTable"},
help = "Option 'joinTable' is not available for this type of class")
public boolean isJoinTableVisibleForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isJoinTableVisibleForFieldSet(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field set", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldSet(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field set", params = {"class"})
public boolean isClassMandatoryForFieldSet() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionAutocompleteIndicator(command = "field set", param = "type",
help = "--type option should be an entity.")
public List<String> getFieldSetTypeAllPossibleValues(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).getFieldSetTypeAllPossibleValues(shellContext);
}
return new ArrayList<String>();
}
@CliOptionVisibilityIndicator(command = "field set", params = {"aggregation", "comment", "fetch",
"force", "mappedBy", "notNull", "nullRequired", "orphanRemoval", "permitReservedWords",
"profile", "sizeMax", "sizeMin"}, help = "--joinTable or --joinColumnName must be defined")
public boolean areOptionalParametersVisibleForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).areOptionalParametersVisibleForFieldSet(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field set", params = {"notNull"},
help = "Option `--notNull` is not available when option `--nullRequired` "
+ "has already been specified.")
public boolean isNotNullVisibleForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNotNullVisibleForFieldSet(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field set", params = {"nullRequired"},
help = "Option `--nullRequired` is not available if numeric type is primitive "
+ "or `--notNull` option has been specified.")
public boolean isNullRequiredVisibleForFieldSet(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNullRequiredVisibleForFieldSet(shellContext);
}
return false;
}
@CliCommand(
value = "field set",
help = "Adds a private `Set` field to an existing Java source file, representing (always) a "
+ "bidirectional relation with other entity. Therefore, this command will also add a field "
+ "on the other side of the relation (the owner side, with `mappedBy` attribute), which will"
+ " be a `Set` field for 'many-to-many' relations, or a *not* `Collection` field for a "
+ "'one-to-many' relation. All added fields will have the needed JPA annotations to properly "
+ "manage bidirectional relations. "
+ "This command is only available for entities annotated with `@RooJpaEntity` (Roo JPA "
+ "entities). Therefore, you should focus the desired entity in the Roo Shell to make "
+ "this command available.")
public void addFieldSetJpa(
@CliOption(key = {"", "fieldName"}, mandatory = true, help = "The name of the field to add.") final JavaSymbolName fieldName,
@CliOption(key = "type", mandatory = true,
help = "The entity related to this one, which will be contained within the `List`."
+ "Possible values are: any of the entities in the project.") final JavaType fieldType,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module "
+ "project, simply specify the name of the class in which the field will be included."
+ " If you consider it necessary, you can also specify the package. "
+ "Ex.: `--class ~.domain.MyClass` (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.MyClass`. If the module is not specified, it "
+ "is assumed that the class is in the module which has the focus."
+ "This option is mandatory for this command when the focus is not set to one class."
+ "Default if option not present: the class focused by Roo shell.") final JavaType typeName,
@CliOption(
key = "joinColumnName",
mandatory = true,
help = "The JPA `@JoinColumn` `name` attribute. When this option is set, cardinality will be set as `ONE_TO_MANY`."
+ "This option is mandatory for 'ONE_TO_MANY' relationships without join table, "
+ "if `spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`.") final String joinColumnName,
@CliOption(
key = "referencedColumnName",
mandatory = false,
help = "The JPA `@JoinColumn` `referencedColumnName` attribute. This option is only available"
+ " when `--joinColumnName` option is set.") final String referencedColumnName,
@CliOption(
key = "joinTable",
mandatory = true,
help = "Join table name. Most usually used in @ManyToMany relations."
+ "This option is mandatory for this command if `--cardinality` is set to `MANY_TO_MANY` "
+ "and `spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`.") final String joinTable,
@CliOption(
key = "joinColumns",
mandatory = true,
help = "Comma separated list of join table's foreign key columns which references the table "
+ "of the related entity (the owner entity in bidirectional relations)."
+ "This option is mandatory if `--joinTable` option has been specified and if "
+ "`spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`."
+ "This option is only available when `--joinTable` " + "option is set.") final String joinColumns,
@CliOption(
key = "referencedColumns",
mandatory = true,
help = "Comma separated list of foreign key referenced columns in the primary table of the "
+ "related entity (the owner entity in bidirectional relations)."
+ "This option is mandatory if `--joinTable` option has been specified and if "
+ "`spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`."
+ "This option is only available when `--joinTable` " + "option is set.") final String referencedColumns,
@CliOption(
key = "inverseJoinColumns",
mandatory = true,
help = "Comma separated list of join table's foreign key columns which references the table of "
+ "the entity that does not own the relation (current entity)."
+ "This option is mandatory if `--joinTable` option has been specified and if "
+ "`spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`."
+ "This option is only available when `--joinTable` " + "option is set.") final String inverseJoinColumns,
@CliOption(
key = "inverseReferencedColumns",
mandatory = true,
help = "Comma separated list of foreign key referenced columns in the primary table of the "
+ "entity that does not own the relation (current entity)."
+ "This option is mandatory if `--joinTable` option has been specified and if "
+ "`spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`."
+ "This option is only available when `--joinTable` " + "option is set.") final String inverseReferencedColumns,
@CliOption(
key = "mappedBy",
mandatory = false,
help = "The field name on the referenced type which owns the relationship, which will be also "
+ "created due to bidirectional relation. If not specified, it will take the lower camel "
+ "case of the current entity (focused entity or specified in `--class` option). If the "
+ "field already exists in the related entity, command won't be executed."
+ "This option is only available for JPA entities."
+ "Default if not present: current entity name in lower camel case.") final JavaSymbolName mappedBy,
@CliOption(key = "cardinality", mandatory = false, unspecifiedDefaultValue = "ONE_TO_MANY",
specifiedDefaultValue = "ONE_TO_MANY",
help = "The relationship cardinality at a JPA level. "
+ "This option is only available for JPA entities and embeddable classes."
+ "Default: `ONE_TO_MANY`.") CardinalitySupported cardinality,
@CliOption(
key = "fetch",
mandatory = false,
help = "The fetch semantics at a JPA level. It adds the provided value to `fetch` attribute of "
+ "JPA `@OneToMany`, `@ManyToMany` and `@ManyToOne`. "
+ "Possible values are: `LAZY`and `EAGER`."
+ "Default if option not present: `LAZY`.") final Fetch fetch,
@CliOption(
key = "aggregation",
mandatory = false,
specifiedDefaultValue = "true",
unspecifiedDefaultValue = "true",
help = "Whether the relationship type is 'aggregation' or 'composition'. An aggregation "
+ "relation means that children entities aren't dependent from parent entity (current "
+ "entity) and they can exist without parent entity. In the other hand, in a composition "
+ "relation the parent entity of the relationship also owns the life cycle of related "
+ "entities. The parent entity is responsible for the creation and destruction of children"
+ " entities, these being linked to a single parent entity. A child entity cannot be in two"
+ " different composition relationships." + "Default: `true`.") final boolean aggregation,
@CliOption(
key = "orphanRemoval",
mandatory = false,
specifiedDefaultValue = "true",
help = "Indicates whether to apply the remove operation to entities that have been removed from"
+ " the relationship and to cascade the remove operation to those entities. If this "
+ "relation represents a 'composition' relation and this option is not present, "
+ "`--orphanRemoval` value will be `true`." + "Default if option present: `true`.") Boolean orphanRemoval,
@CliOption(
key = "sizeMin",
mandatory = false,
help = "The minimum number of elements in the collection. This option adds or updates "
+ "`javax.validation.constraints.Size` with the provided value as `min` attribute value.") final Integer sizeMin,
@CliOption(
key = "sizeMax",
mandatory = false,
help = "The maximum number of elements in the collection. This option adds or updates "
+ "`javax.validation.constraints.Size` with the provided value as `max` attribute value.") final Integer sizeMax,
@CliOption(
key = "notNull",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value cannot be null. Adds `javax.validation.constraints.NotNull` annotation to the field. "
+ "This option is not available if `--nullRequired` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean notNull,
@CliOption(
key = "nullRequired",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value must be null. Adds `javax.validation.constraints.Null` annotation to the field. "
+ "This option is not available if `--notNull` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean nullRequired,
@CliOption(key = "comment", mandatory = false, help = "An optional comment for JavaDocs") final String comment,
@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,
@CliOption(
key = "entityFormatExpression",
mandatory = false,
help = "The SpEL expression used to format the related entity when showing it in presentation layer e.g. "
+ "{#fieldA} {#fieldB}. It adds the `value` attribute to `io.springlets.format.EntityFormat` "
+ "annotation."
+ "This option is available only if `--entityFormatMessage` has not been specified and "
+ "`--cardinality` is `MANY_TO_ONE`.") String formatExpression,
@CliOption(
key = "entityFormatMessage",
mandatory = false,
help = "The message key used to obtain a localized SpEL expression to format the related entity when "
+ "showing it in presentation layer. It adds the `message` attribute to "
+ "`io.springlets.format.EntityFormat` annotation and creates a message in all message bundles "
+ "with the provided key. Message value should be modified by developer."
+ "This option is available only if `--entityFormatExpression` has not been specified and "
+ "`--cardinality` is `MANY_TO_ONE`.") String formatMessage,
// @CliOption(key = "cascadeType", mandatory = false, unspecifiedDefaultValue = "ALL",
// specifiedDefaultValue = "ALL",
// help = "CascadeType. Possible values are ALL, DETACH, MERGE, PERSIST, REFRESH "
// + "and REMOVE.") final Cascade cascadeType,
ShellContext shellContext) {
// TODO support multiple cascade type
getFieldCreatorProvider(typeName).createSetField(typeName, fieldType, fieldName,
cardinality.getCardinality(), null, notNull, sizeMin, sizeMax, mappedBy, fetch, comment,
joinColumnName, referencedColumnName, joinTable, joinColumns, referencedColumns,
inverseJoinColumns, inverseReferencedColumns, permitReservedWords, aggregation,
orphanRemoval, shellContext.isForce(), formatExpression, formatMessage);
}
@CliOptionVisibilityIndicator(command = "field list", params = {"joinColumns",
"referencedColumns", "inverseJoinColumns", "inverseReferencedColumns"},
help = "Options --joinColumns, --referencedColumns, --inverseJoinColumns and "
+ "--inverseReferencedColumns must be used with a specific --joinTable option.")
public boolean areJoinTableParamsVisibleForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).areJoinTableParamsVisibleForFieldList(shellContext);
}
return false;
}
@CliOptionMandatoryIndicator(command = "field list", params = {"joinColumnName"})
public boolean isColumnMandatoryForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isJoinColumnNameMandatoryForFieldList(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field list", params = {"joinColumnName"},
help = "Option 'joinColumnName' is not available for this type of class")
public boolean isJoinColumnNameVisibleForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isJoinColumnNameVisibleForFieldList(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field list", params = {"referencedColumnName"},
help = "Option 'referencedColumnName' is not available for this type of class")
public boolean isReferencedColumnNameVisibleForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isReferencedColumnNameVisibleForFieldList(shellContext);
}
return false;
}
@CliOptionMandatoryIndicator(command = "field list", params = {"joinTable"})
public boolean isJoinTableMandatoryForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isJoinTableMandatoryForFieldList(shellContext);
}
return false;
}
@CliOptionMandatoryIndicator(command = "field list", params = {"joinColumns",
"referencedColumns", "inverseJoinColumns", "inverseReferencedColumns"})
public boolean areJoinTableParamsMandatoryForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).areJoinTableParamsMandatoryForFieldList(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field list", params = {"mappedBy"},
help = "Option 'mappedBy' is not available for this type of class")
public boolean isMappedByVisibleForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isMappedByVisibleForFieldList(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field list", params = {"cardinality"},
help = "Option 'cardinality' is not available for this type of class")
public boolean isCardinalityVisibleForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isCardinalityVisibleForFieldList(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field list", params = {"fetch"},
help = "Option 'fetch' is not available for this type of class")
public boolean isFetchVisibleForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isFetchVisibleForFieldList(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field list", params = {"joinTable"},
help = "Option 'joinTable' is not available for this type of class")
public boolean isJoinTableVisibleForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isJoinTableVisibleForFieldList(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field list", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldList(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field list", params = {"class"})
public boolean isClassMandatoryForFieldList() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionAutocompleteIndicator(command = "field list", param = "type",
help = "--type option should be an entity.")
public List<String> getFieldListTypePossibleValues(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).getFieldListTypeAllPossibleValues(shellContext);
}
return new ArrayList<String>();
}
@CliOptionVisibilityIndicator(command = "field list", params = {"aggregation", "comment",
"fetch", "force", "mappedBy", "notNull", "orphanRemoval", "permitReservedWords", "profile",
"sizeMax", "sizeMin"}, help = "--joinTable or --joinColumnName must be defined first.")
public boolean areOptionalParametersVisibleForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).areOptionalParametersVisibleForFieldList(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field list", params = {"notNull"},
help = "Option `--notNull` is not available when option `--nullRequired` "
+ "has already been specified.")
public boolean isNotNullVisibleForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNotNullVisibleForFieldList(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field list", params = {"nullRequired"},
help = "Option `--nullRequired` is not available if numeric type is primitive "
+ "or `--notNull` option has been specified.")
public boolean isNullRequiredVisibleForFieldList(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNullRequiredVisibleForFieldList(shellContext);
}
return false;
}
@CliCommand(
value = "field list",
help = "Adds a private `List` field to an existing Java source file, representing (always) a "
+ "bidirectional relation with other entity. Therefore, this command will also add a field "
+ "on the other side of the relation (the owner side, with `mappedBy` attribute), which will"
+ " be a `List` field for 'many-to-many' relations, or a *not* `Collection` field for a "
+ "'one-to-many' relation. All added fields will have the needed JPA annotations to properly "
+ "manage bidirectional relations."
+ "This command is only available for entities annotated with `@RooJpaEntity` (Roo JPA "
+ "entities). Therefore, you should focus the desired entity in the Roo Shell to make "
+ "this command available.")
public void addFieldListJpa(
@CliOption(key = {"", "fieldName"}, mandatory = true, help = "The name of the field to add.") final JavaSymbolName fieldName,
@CliOption(key = "type", mandatory = true,
help = "The entity related to this one, which will be contained within the `List`. "
+ "Possible values are: any of the entities in the project.") final JavaType fieldType,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module "
+ "project, simply specify the name of the class in which the field will be included."
+ " If you consider it necessary, you can also specify the package. "
+ "Ex.: `--class ~.domain.MyClass` (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.MyClass`. If the module is not specified, it "
+ "is assumed that the class is in the module which has the focus. "
+ "This option is mandatory for this command when the focus is not set to one class. "
+ "Default if option not present: the class focused by Roo shell.") final JavaType typeName,
@CliOption(
key = "joinColumnName",
mandatory = true,
help = "The JPA `@JoinColumn` `name` attribute. When this option is set, cardinality will be set as `ONE_TO_MANY`."
+ "This option is mandatory for 'ONE_TO_MANY' relationships without join table, "
+ "if `spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`.") final String joinColumnName,
@CliOption(
key = "referencedColumnName",
mandatory = false,
help = "The JPA `@JoinColumn` `referencedColumnName` attribute. This option is only available"
+ " when `--joinColumnName` option is set.") final String referencedColumnName,
@CliOption(
key = "joinTable",
mandatory = true,
help = "Join table name. Most usually used in `@ManyToMany` relations. "
+ "This option is mandatory for this command if `--cardinality` is set to `MANY_TO_MANY` "
+ "and `spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`.") final String joinTable,
@CliOption(
key = "joinColumns",
mandatory = true,
help = "Comma separated list of join table's foreign key columns which references the table "
+ "of the related entity (the owner entity in bidirectional relations). "
+ "This option is mandatory if `--joinTable` option has been specified and if "
+ "`spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`. "
+ "This option is only available when `--joinTable` " + "option is set.") final String joinColumns,
@CliOption(
key = "referencedColumns",
mandatory = true,
help = "Comma separated list of foreign key referenced columns in the primary table of the "
+ "related entity (the owner entity in bidirectional relations). "
+ "This option is mandatory if `--joinTable` option has been specified and if "
+ "`spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`. "
+ "This option is only available when `--joinTable` " + "option is set.") final String referencedColumns,
@CliOption(
key = "inverseJoinColumns",
mandatory = true,
help = "Comma separated list of join table's foreign key columns which references the table of "
+ "the entity that does not own the relation (current entity). "
+ "This option is mandatory if `--joinTable` option has been specified and if "
+ "`spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`. "
+ "This option is only available when `--joinTable` " + "option is set.") final String inverseJoinColumns,
@CliOption(
key = "inverseReferencedColumns",
mandatory = true,
help = "Comma separated list of foreign key referenced columns in the primary table of the "
+ "entity that does not own the relation (current entity). "
+ "This option is mandatory if `--joinTable` option has been specified and if "
+ "`spring.roo.jpa.require.schema-object-name` configuration setting exists and it's `true`. "
+ "This option is only available when `--joinTable` " + "option is set.") final String inverseReferencedColumns,
@CliOption(
key = "mappedBy",
mandatory = false,
help = "The field name on the referenced type which owns the relationship, which will be also "
+ "created due to bidirectional relation. If not specified, it will take the lower camel "
+ "case of the current entity (focused entity or specified in `--class` option). If the "
+ "field already exists in the related entity, command won't be executed. "
+ "This option is only available for JPA entities. "
+ "Default if not present: current entity name in lower camel case.") final JavaSymbolName mappedBy,
@CliOption(key = "cardinality", mandatory = false, unspecifiedDefaultValue = "ONE_TO_MANY",
specifiedDefaultValue = "ONE_TO_MANY",
help = "The relationship cardinality at a JPA level. " + "Default: `ONE_TO_MANY`.") CardinalitySupported cardinality,
@CliOption(
key = "fetch",
mandatory = false,
help = "The fetch semantics at a JPA level. It adds the provided value to `fetch` attribute of "
+ "JPA `@OneToMany`, `@ManyToMany` and `@ManyToOne`. "
+ "Possible values are: `LAZY`and `EAGER`. "
+ "Default if option not present: `LAZY`.") final Fetch fetch,
@CliOption(
key = "aggregation",
mandatory = false,
specifiedDefaultValue = "true",
unspecifiedDefaultValue = "true",
help = "Whether the relationship type is 'aggregation' or 'composition'. An aggregation "
+ "relation means that children entities aren't dependent from parent entity (current "
+ "entity) and they can exist without parent entity. In the other hand, in a composition "
+ "relation the parent entity of the relationship also owns the life cycle of related "
+ "entities. The parent entity is responsible for the creation and destruction of children"
+ " entities, these being linked to a single parent entity. A child entity cannot be in two"
+ " different composition relationships. " + "Default: `true`.") final boolean aggregation,
@CliOption(
key = "orphanRemoval",
mandatory = false,
specifiedDefaultValue = "true",
help = "Indicates whether to apply the remove operation to entities that have been removed from"
+ " the relationship and to cascade the remove operation to those entities. If this "
+ "relation represents a 'composition' relation and this option is not present, "
+ "`--orphanRemoval` value will be `true`. " + "Default if option present: `true`.") Boolean orphanRemoval,
@CliOption(
key = "sizeMin",
mandatory = false,
help = "The minimum number of elements in the collection. This option adds or updates "
+ "`javax.validation.constraints.Size` with the provided value as `min` attribute value.") final Integer sizeMin,
@CliOption(
key = "sizeMax",
mandatory = false,
help = "The maximum number of elements in the collection. This option adds or updates "
+ "`javax.validation.constraints.Size` with the provided value as `max` attribute value.") final Integer sizeMax,
@CliOption(
key = "notNull",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value cannot be null. Adds `javax.validation.constraints.NotNull` annotation to the field. "
+ "This option is not available if `--nullRequired` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean notNull,
@CliOption(
key = "nullRequired",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value must be null. Adds `javax.validation.constraints.Null` annotation to the field. "
+ "This option is not available if `--notNull` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean nullRequired,
@CliOption(key = "comment", mandatory = false, help = "An optional comment for JavaDocs.") final String comment,
@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,
@CliOption(
key = "entityFormatExpression",
mandatory = false,
help = "The SpEL expression used to format the related entity when showing it in presentation layer e.g. "
+ "`{#fieldA} {#fieldB}`. It adds the `value` attribute to `io.springlets.format.EntityFormat` "
+ "annotation.") String formatExpression,
@CliOption(
key = "entityFormatMessage",
mandatory = false,
help = "The message key used to obtain a localized SpEL expression to format the related entity when "
+ "showing it in presentation layer. It adds the `message` attribute to "
+ "`io.springlets.format.EntityFormat` annotation and creates a message in all message bundles "
+ "with the provided key. Message value should be modified by developer.") String formatMessage,
// @CliOption(key = "cascadeType", mandatory = false, unspecifiedDefaultValue = "ALL",
// specifiedDefaultValue = "ALL",
// help = "CascadeType. Possible values are ALL, DETACH, MERGE, PERSIST, REFRESH "
// + "and REMOVE.") final Cascade cascadeType,
ShellContext shellContext) {
// TODO Support multiple cascade type
getFieldCreatorProvider(typeName).createListField(typeName, fieldType, fieldName,
cardinality.getCardinality(), null, notNull, sizeMin, sizeMax, mappedBy, fetch, comment,
joinColumnName, referencedColumnName, joinTable, joinColumns, referencedColumns,
inverseJoinColumns, inverseReferencedColumns, permitReservedWords, aggregation,
orphanRemoval, shellContext.isForce(), formatExpression, formatMessage);
}
@CliOptionMandatoryIndicator(command = "field string", params = {"column"})
public boolean isColumnMandatoryForFieldString(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnMandatoryForFieldString(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field string", params = {"column"},
help = "Option 'column' is not available for this type of class")
public boolean isColumnVisibleForFieldString(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnVisibleForFieldString(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field string", params = {"unique"},
help = "Option 'unique' is not available for this type of class")
public boolean isUniqueVisibleForFieldString(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isUniqueVisibleForFieldString(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field string", params = {"transient"},
help = "Option 'transient' is not available for this type of class")
public boolean isTransientVisibleForFieldString(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isTransientVisibleForFieldString(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field string", params = {"lob"},
help = "Option 'lob' is not available for this type of class")
public boolean isLobVisibleForFieldString(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isLobVisibleForFieldString(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field string", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldString(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field string", params = {"class"})
public boolean isClassMandatoryForFieldString() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionVisibilityIndicator(command = "field string", params = {"notNull"},
help = "Option `--notNull` is not available when option `--nullRequired` "
+ "has already been specified.")
public boolean isNotNullVisibleForFieldString(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNotNullVisibleForFieldString(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field string", params = {"nullRequired"},
help = "Option `--nullRequired` is not available if numeric type is primitive "
+ "or `--notNull` option has been specified.")
public boolean isNullRequiredVisibleForFieldString(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNullRequiredVisibleForFieldString(shellContext);
}
return false;
}
@CliCommand(value = "field string",
help = "Adds a private String field to an existing Java source file.")
public void addFieldString(
@CliOption(key = {"", "fieldName"}, mandatory = true, help = "The name of the field to add.") final JavaSymbolName fieldName,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module project, "
+ "simply specify the name of the class in which the field will be included. If you "
+ "consider it necessary, you can also specify the package. Ex.: `--class ~.domain.MyClass`"
+ " (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.MyClass`."
+ " If the module is not specified, it is assumed that the class is in the module which has"
+ " the focus. "
+ "This option is mandatory for this command when the focus is not set to one class. "
+ "Default if option not present: the class focused by Roo Shell.") final JavaType typeName,
@CliOption(
key = "column",
mandatory = true,
help = "The JPA `@Column` name. "
+ "This option is mandatory if `spring.roo.jpa.require.schema-object-name` configuration "
+ "setting exists and it's `true`. "
+ "This option is only available for JPA entities and embeddable classes.") final String column,
@CliOption(
key = "transient",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates to mark the field as transient, adding JPA `javax.persistence.Transient` "
+ "annotation. This marks the field as not persistent. "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option present:`true`. Default if option not present: `false`") final boolean transientModifier,
@CliOption(
key = "lob",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates that this field is a Large Object. This option adds `javax.persistence.Lob` "
+ "annotation to the field. "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean lob,
@CliOption(key = "unique", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates whether to mark the field with a unique constraint. "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean unique,
@CliOption(
key = "regexp",
mandatory = false,
help = "The required regular expression pattern. This option adds "
+ "`javax.validation.constraints.Pattern` with the provided value as `regexp` attribute.") final String regexp,
@CliOption(
key = "sizeMin",
mandatory = false,
help = "The minimum string length. This option adds or updates "
+ "`javax.validation.constraints.Size` with the provided value as `min` attribute value.") final Integer sizeMin,
@CliOption(
key = "sizeMax",
mandatory = false,
help = "The maximum string length. This option adds or updates "
+ "`javax.validation.constraints.Size` with the provided value as `max` attribute value.") final Integer sizeMax,
@CliOption(
key = "notNull",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value cannot be null. Adds `javax.validation.constraints.NotNull` annotation to the field. "
+ "This option is not available if `--nullRequired` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean notNull,
@CliOption(
key = "nullRequired",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value must be null. Adds `javax.validation.constraints.Null` annotation to the field. "
+ "This option is not available if `--notNull` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean nullRequired,
@CliOption(
key = "value",
mandatory = false,
help = "Inserts an optional Spring `org.springframework.beans.factory.annotation.Value` "
+ "annotation with the given content, typically used for expression-driven dependency "
+ "injection.") final String value,
@CliOption(key = "comment", mandatory = false, help = "An optional comment for JavaDocs.") final String comment,
@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) {
final ClassOrInterfaceTypeDetails cid = typeLocationService.getTypeDetails(typeName);
Validate.notNull(cid, "The type specified, '%s', doesn't exist", typeName);
checkFieldExists(fieldName, shellContext, cid);
getFieldCreatorProvider(typeName).createStringField(cid, fieldName, notNull, nullRequired,
null, null, sizeMin, sizeMax, regexp, column, comment, unique, value, lob,
permitReservedWords, transientModifier);
}
@CliOptionMandatoryIndicator(command = "field file", params = {"column"})
public boolean isColumnMandatoryForFieldFile(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnMandatoryForFieldFile(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field file", params = {"column"},
help = "Option 'column' is not available for this type of class")
public boolean isColumnVisibleForFieldFile(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnVisibleForFieldFile(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field file", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldFile(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field file", params = {"class"})
public boolean isClassMandatoryForFieldFile() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliCommand(value = "field file",
help = "Adds a byte array field for storing uploaded file contents.")
public void addFileUploadField(
@CliOption(key = {"", "fieldName"}, mandatory = true,
help = "The name of the file upload field to add.") final JavaSymbolName fieldName,
@CliOption(key = "contentType", mandatory = true, help = "The content type of the file. "
+ "Possible values are: `CSS`, `CSV`, `DOC`, `GIF`, `HTML`, `JAVASCRIPT`, `JPG`, "
+ "`JSON`, `MP3`, `MP4`, `MPEG`, `PDF`, `PNG`, `TXT`, `XLS`, `XML` and `ZIP`.") final UploadedFileContentType contentType,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module project, "
+ "simply specify the name of the class in which the field will be included. If you "
+ "consider it necessary, you can also specify the package. Ex.: `--class ~.domain.MyClass`"
+ " (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.MyClass`."
+ " If the module is not specified, it is assumed that the class is in the module which has"
+ " the focus. "
+ "This option is mandatory for this command when the focus is not set to one class. "
+ "Default if option not present: the class focused by Roo Shell.") final JavaType typeName,
@CliOption(
key = "column",
mandatory = true,
help = "The JPA `@Column` name. "
+ "This option is mandatory if `spring.roo.jpa.require.schema-object-name` configuration "
+ "setting exists and it's `true`. "
+ "This option is only available for JPA entities and embeddable classes.") final String column,
@CliOption(key = "autoUpload", mandatory = false, specifiedDefaultValue = "true",
unspecifiedDefaultValue = "false",
help = "Whether the file is uploaded automatically when selected. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean autoUpload,
@CliOption(
key = "notNull",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value cannot be null. Adds `javax.validation.constraints.NotNull` annotation to the field."
+ "Default if option present: `true`; default if option not present: `false`.") final boolean notNull,
@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) {
final ClassOrInterfaceTypeDetails cid = typeLocationService.getTypeDetails(typeName);
Validate.notNull(cid, "The type specified, '%s', doesn't exist", typeName);
checkFieldExists(fieldName, shellContext, cid);
getFieldCreatorProvider(typeName).createFileField(cid, fieldName, contentType, autoUpload,
notNull, column, permitReservedWords);
}
@CliOptionMandatoryIndicator(command = "field other", params = {"column"})
public boolean isColumnMandatoryForFieldOther(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnMandatoryForFieldOther(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field other", params = {"column"},
help = "Option 'column' is not available for this type of class")
public boolean isColumnVisibleForFieldOther(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isColumnVisibleForFieldOther(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field other", params = {"transient"},
help = "Option 'transient' is not available for this type of class")
public boolean isTransientVisibleForFieldOther(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isTransientVisibleForFieldOther(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field other", params = {"class"},
help = "Option 'class' is not available "
+ "for this command when the focus is set to one class.")
public boolean isClassVisibleForFieldOther(ShellContext shellContext) {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionMandatoryIndicator(command = "field other", params = {"class"})
public boolean isClassMandatoryForFieldOther() {
if (lastUsed.getJavaType() == null) {
return true;
}
return false;
}
@CliOptionVisibilityIndicator(command = "field other", params = {"notNull"},
help = "Option `--notNull` is not available when option `--nullRequired` "
+ "has already been specified.")
public boolean isNotNullVisibleForFieldOther(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNotNullVisibleForFieldOther(shellContext);
}
return false;
}
@CliOptionVisibilityIndicator(command = "field other", params = {"nullRequired"},
help = "Option `--nullRequired` is not available if numeric type is primitive "
+ "or `--notNull` option has been specified.")
public boolean isNullRequiredVisibleForFieldOther(ShellContext shellContext) {
JavaType type = getTypeFromCommand(shellContext);
if (type != null) {
return getFieldCreatorProvider(type).isNullRequiredVisibleForFieldOther(shellContext);
}
return false;
}
@CliCommand(
value = "field other",
help = "Inserts a private field into the specified file. User can choose a custom type for the field by specifying its fully qualified name.")
public void insertField(
@CliOption(key = "fieldName", mandatory = true, help = "The name of the field.") final JavaSymbolName fieldName,
@CliOption(key = "type", mandatory = true, help = "The Java type of this field.") final JavaType fieldType,
@CliOption(
key = "class",
mandatory = true,
unspecifiedDefaultValue = "*",
optionContext = UPDATE_PROJECT,
help = "The name of the class to generate the field. When working on a mono module "
+ "project, simply specify the name of the class in which the field will be included."
+ " If you consider it necessary, you can also specify the package. "
+ "Ex.: `--class ~.domain.MyClass` (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.MyClass`. If the module is not "
+ "specified, it is assumed that the class is in the module which has the focus. "
+ "This option is mandatory for this command when the focus is not set to one class. "
+ "Default if option not present: the class focused by Roo Shell.") final JavaType typeName,
@CliOption(key = "column", mandatory = true, help = "The JPA `@Column` name."
+ "This option is mandatory if `spring.roo.jpa.require.schema-object-name` configuration"
+ " setting exists and it's `true`. "
+ "This option is only available for JPA entities and embeddable classes.") final String column,
@CliOption(
key = "transient",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Indicates to mark the field as transient, adding JPA `javax.persistence.Transient` "
+ "annotation. This marks the field as not persistent. "
+ "This option is only available for JPA entities and embeddable classes. "
+ "Default if option present:`true`. Default if option not present: `false`") final boolean transientModifier,
@CliOption(key = "notNull", mandatory = false, unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value cannot be null. Adds `javax.validation.constraints.NotNull` "
+ "annotation to the field. "
+ "This option is not available if `--nullRequired` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean notNull,
@CliOption(
key = "nullRequired",
mandatory = false,
unspecifiedDefaultValue = "false",
specifiedDefaultValue = "true",
help = "Whether this value must be null. Adds `javax.validation.constraints.Null` annotation to the field. "
+ "This option is not available if `--notNull` has already been specified. "
+ "Default if option present: `true`; default if option not present: `false`.") final boolean nullRequired,
@CliOption(key = "comment", mandatory = false, help = "An optional comment for JavaDocs.") final String comment,
@CliOption(key = "value", mandatory = false,
help = "Inserts an optional Spring `org.springframework.beans.factory.annotation.Value` "
+ "annotation with the given content, typically used for expression-driven "
+ "dependency injection.") final String value,
@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) {
final ClassOrInterfaceTypeDetails cid = typeLocationService.getTypeDetails(typeName);
Validate.notNull(cid, "The type specified, '%s', doesn't exist", typeName);
checkFieldExists(fieldName, shellContext, cid);
getFieldCreatorProvider(typeName).createOtherField(cid, fieldType, fieldName, notNull,
nullRequired, comment, column, permitReservedWords, transientModifier);
}
// Availability indicators //
@CliAvailabilityIndicator({"field other", "field number", "field string", "field date",
"field boolean", "field enum", "field file"})
public boolean isFieldManagementAvailable() {
return getFieldCreatorAvailable();
}
@CliAvailabilityIndicator({"field embedded"})
public boolean isFieldEmbeddedAvailable() {
JavaType type = lastUsed.getJavaType();
if (type != null) {
return getFieldCreatorProvider(type).isFieldEmbeddedAvailable();
}
return getFieldCreatorAvailable();
}
@CliAvailabilityIndicator({"field reference"})
public boolean isFieldReferenceAvailable() {
JavaType type = lastUsed.getJavaType();
if (type != null) {
return getFieldCreatorProvider(type).isFieldReferenceAvailable();
}
return getFieldCreatorAvailable();
}
@CliAvailabilityIndicator({"field set", "field list"})
public boolean isFieldCollectionAvailable() {
JavaType type = lastUsed.getJavaType();
if (type != null) {
return getFieldCreatorProvider(type).isFieldCollectionAvailable();
}
return getFieldCreatorAvailable();
}
/**
* Checks if entity has already a field with the same name and throws an exception
* in that case.
*
* @param fieldName
* @param shellContext
* @param javaTypeDetails
*
* @deprecated this should be done by operation class (see JpaFieldCreatorProvider.checkFieldExists)
*/
private void checkFieldExists(final JavaSymbolName fieldName, ShellContext shellContext,
final ClassOrInterfaceTypeDetails javaTypeDetails) {
MemberDetails memberDetails =
memberDetailsScanner.getMemberDetails(this.getClass().getName(), javaTypeDetails);
List<FieldMetadata> fields = memberDetails.getFields();
for (FieldMetadata field : fields) {
if (field.getFieldName().equals(fieldName) && !shellContext.isForce()) {
throw new IllegalArgumentException(
String
.format(
"Field '%s' already exists and cannot be created. Try to use a "
+ "different field name on --fieldName parameter or use --force parameter to overwrite it.",
fieldName));
}
}
}
/**
* Tries to obtain JavaType indicated in command or which has the focus
* in the Shell
*
* @param shellContext the Roo Shell context
* @return JavaType or null if no class has the focus or no class is
* specified in the command
*/
private JavaType getTypeFromCommand(ShellContext shellContext) {
// Try to get 'class' from ShellContext
String typeString = shellContext.getParameters().get("class");
JavaType type = null;
if (typeString != null) {
type = getJavaTypeConverter().convertFromText(typeString, JavaType.class, PROJECT);
} else {
type = lastUsed.getJavaType();
}
return type;
}
/**
* Gets the right implementation of FieldCreatorProvider for a JavaType
*
* @param type the JavaType to get the implementation
* @return FieldCreatorProvider implementation
*/
public FieldCreatorProvider getFieldCreatorProvider(JavaType type) {
// Get all Services implement FieldCreatorProvider interface
if (fieldCreatorProviders.isEmpty()) {
try {
ServiceReference<?>[] references =
this.context.getAllServiceReferences(FieldCreatorProvider.class.getName(), null);
for (ServiceReference<?> ref : references) {
FieldCreatorProvider fieldCreatorProvider =
(FieldCreatorProvider) this.context.getService(ref);
fieldCreatorProviders.add(fieldCreatorProvider);
}
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load FieldCreatorProvider on FieldCommands.");
return null;
}
}
for (FieldCreatorProvider provider : fieldCreatorProviders) {
if (provider.isValid(type)) {
return provider;
}
}
return null;
}
/**
* Checks all FieldCreator implementations looking for any available
*
* @return <code>true</code> if any of the implementations is available or
* <code>false</code> if none of the implementations are available.
*/
private boolean getFieldCreatorAvailable() {
// Get all Services implement FieldCreatorProvider interface
if (fieldCreatorProviders.isEmpty()) {
try {
ServiceReference<?>[] references =
this.context.getAllServiceReferences(FieldCreatorProvider.class.getName(), null);
for (ServiceReference<?> ref : references) {
FieldCreatorProvider fieldCreatorProvider =
(FieldCreatorProvider) this.context.getService(ref);
fieldCreatorProviders.add(fieldCreatorProvider);
}
} catch (InvalidSyntaxException e) {
LOGGER.warning("Cannot load FieldCreatorProvider on FieldCommands.");
return false;
}
}
for (FieldCreatorProvider provider : fieldCreatorProviders) {
if (provider.isFieldManagementAvailable()) {
return true;
}
}
return false;
}
@SuppressWarnings("unchecked")
public Converter<JavaType> getJavaTypeConverter() {
if (javaTypeConverter == null) {
// Get all Services implement JavaTypeConverter interface
try {
ServiceReference<?>[] references =
this.context.getAllServiceReferences(Converter.class.getName(), null);
for (ServiceReference<?> ref : references) {
Converter<?> converter = (Converter<?>) this.context.getService(ref);
if (converter.supports(JavaType.class, PROJECT)) {
javaTypeConverter = (Converter<JavaType>) converter;
return javaTypeConverter;
}
}
return null;
} catch (InvalidSyntaxException e) {
LOGGER.warning("ERROR: Cannot load JavaTypeConverter on FieldCommands.");
return null;
}
} else {
return javaTypeConverter;
}
}
/**
* Replaces a JavaType fullyQualifiedName for a shorter name using '~' for TopLevelPackage
*
* @param cid ClassOrInterfaceTypeDetails of a JavaType
* @param currentText String current text for option value
* @return the String representing a JavaType with its name shortened
*/
private String replaceTopLevelPackageString(ClassOrInterfaceTypeDetails cid, String currentText) {
String javaTypeFullyQualilfiedName = cid.getType().getFullyQualifiedTypeName();
String javaTypeString = "";
String topLevelPackageString = "";
// Add module value to topLevelPackage when necessary
if (StringUtils.isNotBlank(cid.getType().getModule())
&& !cid.getType().getModule().equals(projectOperations.getFocusedModuleName())) {
// Target module is not focused
javaTypeString = cid.getType().getModule().concat(LogicalPath.MODULE_PATH_SEPARATOR);
topLevelPackageString =
projectOperations.getTopLevelPackage(cid.getType().getModule())
.getFullyQualifiedPackageName();
} else if (StringUtils.isNotBlank(cid.getType().getModule())
&& cid.getType().getModule().equals(projectOperations.getFocusedModuleName())
&& (currentText.startsWith(cid.getType().getModule()) || cid.getType().getModule()
.startsWith(currentText)) && StringUtils.isNotBlank(currentText)) {
// Target module is focused but user wrote it
javaTypeString = cid.getType().getModule().concat(LogicalPath.MODULE_PATH_SEPARATOR);
topLevelPackageString =
projectOperations.getTopLevelPackage(cid.getType().getModule())
.getFullyQualifiedPackageName();
} else {
// Not multimodule project
topLevelPackageString =
projectOperations.getFocusedTopLevelPackage().getFullyQualifiedPackageName();
}
// Autocomplete with abbreviate or full qualified mode
String auxString =
javaTypeString.concat(StringUtils.replace(javaTypeFullyQualilfiedName,
topLevelPackageString, "~"));
if ((StringUtils.isBlank(currentText) || auxString.startsWith(currentText))
&& StringUtils.contains(javaTypeFullyQualilfiedName, topLevelPackageString)) {
// Value is for autocomplete only or user wrote abbreviate value
javaTypeString = auxString;
} else {
// Value could be for autocomplete or for validation
javaTypeString = String.format("%s%s", javaTypeString, javaTypeFullyQualilfiedName);
}
return javaTypeString;
}
}