package org.springframework.roo.converters;
import static org.springframework.roo.project.maven.Pom.ROOT_MODULE_SYMBOL;
import static org.springframework.roo.shell.OptionContexts.FEATURE;
import static org.springframework.roo.shell.OptionContexts.INCLUDE_CURRENT_MODULE;
import static org.springframework.roo.shell.OptionContexts.UPDATE;
import static org.springframework.roo.shell.OptionContexts.UPDATELAST;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
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.springframework.roo.classpath.ModuleFeatureName;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.project.maven.Pom;
import org.springframework.roo.shell.Completion;
import org.springframework.roo.shell.Converter;
import org.springframework.roo.shell.MethodTarget;
@Component
@Service
public class PomConverter implements Converter<Pom> {
/**
* The value that converts to the most recently used {@link Pom}.
*/
static final String LAST_USED_INDICATOR = "*";
/**
* The value that converts to focused module {@link Pom}.
*/
static final String FOCUSED_INDICATOR = ".";
final Pattern pattern = Pattern.compile(FEATURE + "\\[(.+?)\\]");
@Reference
ProjectOperations projectOperations;
@Reference
TypeLocationService typeLocationService;
@Reference
LastUsed lastUsed;
private void addCompletion(final String moduleName, final List<Completion> completions) {
final String nonEmptyModuleName = StringUtils.defaultIfEmpty(moduleName, ROOT_MODULE_SYMBOL);
completions.add(new Completion(nonEmptyModuleName));
}
public Pom convertFromText(final String value, final Class<?> targetType,
final String optionContext) {
final String moduleName;
Pom result;
ModuleFeatureName moduleFeatureName = null;
// Get module feature
if (optionContext != null) {
final Matcher matcher = pattern.matcher(optionContext);
if (matcher.find()) {
moduleFeatureName = ModuleFeatureName.valueOf(matcher.group(1));
}
}
if (LAST_USED_INDICATOR.equals(value)) {
result = lastUsed.getModule();
if (result == null) {
throw new IllegalStateException(
"Unknown pom; please indicate the module as a command option (ie --xxxx)");
}
} else if (FOCUSED_INDICATOR.equals(value)) {
result = projectOperations.getFocusedModule();
if (moduleFeatureName != null
&& !typeLocationService.hasModuleFeature(result, moduleFeatureName)) {
// Get valid module
List<Pom> modules = (List<Pom>) typeLocationService.getModules(moduleFeatureName);
if (modules.size() == 0) {
throw new RuntimeException(String.format("ERROR: Not exists a module with %s feature",
moduleFeatureName));
} else {
result = modules.get(0);
}
}
} else {
if (ROOT_MODULE_SYMBOL.equals(value)) {
moduleName = "";
} else {
moduleName = value;
}
result = projectOperations.getPomFromModuleName(moduleName);
Validate.notNull(result, String.format("Module %s not found", moduleName));
}
// Validate feature
if (moduleFeatureName != null
&& !typeLocationService.hasModuleFeature(result, moduleFeatureName)) {
return null;
}
if (StringUtils.contains(optionContext, UPDATE)
|| StringUtils.contains(optionContext, UPDATELAST)) {
lastUsed.setTypeNotVerified(null, result);
}
return result;
}
public boolean getAllPossibleValues(final List<Completion> completions,
final Class<?> targetType, final String existingData, final String optionContext,
final MethodTarget target) {
boolean filteredByFeature = false;
if (optionContext != null) {
for (ModuleFeatureName moduleFeatureName : ModuleFeatureName.values()) {
if (optionContext.contains(moduleFeatureName.name())) {
filteredByFeature = true;
addModules(completions, optionContext,
typeLocationService.getModuleNames(moduleFeatureName));
}
}
}
if (!filteredByFeature) {
addModules(completions, optionContext, projectOperations.getModuleNames());
}
return true;
}
private void addModules(final List<Completion> completions, final String optionContext,
final Collection<String> moduleNames) {
final String focusedModuleName = projectOperations.getFocusedModuleName();
for (final String moduleName : moduleNames) {
if (isModuleRelevant(moduleName, focusedModuleName, optionContext)) {
addCompletion(moduleName, completions);
}
}
}
private boolean isModuleRelevant(final String moduleName, final String focusedModuleName,
final String optionContext) {
return StringUtils.contains(optionContext, INCLUDE_CURRENT_MODULE)
|| !moduleName.equals(focusedModuleName);
}
public boolean supports(final Class<?> type, final String optionContext) {
return Pom.class.isAssignableFrom(type);
}
}