blob: 86a7eef77b135b289ecf6360eeb1e8fe4e3f02fd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.archetype.ui.generation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.maven.archetype.catalog.Archetype;
import org.apache.maven.archetype.ui.ArchetypeDefinition;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.components.interactivity.Prompter;
import org.codehaus.plexus.components.interactivity.PrompterException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
@Component(role = ArchetypeSelectionQueryer.class, hint = "default")
public class DefaultArchetypeSelectionQueryer extends AbstractLogEnabled implements ArchetypeSelectionQueryer {
@Requirement(hint = "archetype")
private Prompter prompter;
@Override
public boolean confirmSelection(ArchetypeDefinition archetypeDefinition) throws PrompterException {
String query = "Confirm archetype selection: \n" + archetypeDefinition.getGroupId() + "/"
+ archetypeDefinition.getName() + "\n";
String answer = prompter.prompt(query, Arrays.asList(new String[] {"Y", "N"}), "Y");
return "Y".equalsIgnoreCase(answer);
}
@Override
public Archetype selectArchetype(Map<String, List<Archetype>> catalogs) throws PrompterException {
return selectArchetype(catalogs, null);
}
@Override
public Archetype selectArchetype(Map<String, List<Archetype>> catalogs, ArchetypeDefinition defaultDefinition)
throws PrompterException {
Archetype selection = null;
Map<String, List<Archetype>> filteredCatalogs = catalogs;
do {
StringBuilder query = new StringBuilder("Choose archetype:\n");
Set<String> archetypeKeys = new HashSet<>();
List<String> answers = new ArrayList<>();
Map<String, Archetype> archetypeAnswerMap = new HashMap<>();
int counter = 0;
int defaultSelection = 0;
for (Map.Entry<String, List<Archetype>> entry : filteredCatalogs.entrySet()) {
String catalog = entry.getKey();
for (Archetype archetype : entry.getValue()) {
String archetypeKey = archetype.getGroupId() + ":" + archetype.getArtifactId();
if (!archetypeKeys.add(archetypeKey)) {
continue;
}
counter++;
String description = archetype.getDescription();
if (description == null) {
description = "-";
}
String answer = String.valueOf(counter);
query.append(answer + ": " + catalog + " -> " + archetype.getGroupId() + ":"
+ archetype.getArtifactId() + " (" + description + ")\n");
answers.add(answer);
archetypeAnswerMap.put(answer, archetype);
// the version is not tested. This is intentional.
if (defaultDefinition != null
&& archetype.getGroupId().equals(defaultDefinition.getGroupId())
&& archetype.getArtifactId().equals(defaultDefinition.getArtifactId())) {
defaultSelection = counter;
}
}
}
if (counter == 0) {
query.append(" Your filter doesn't match any archetype (hint: enter to return to initial list)\n");
}
query.append("Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): ");
String answer;
if (defaultSelection == 0) {
answer = prompter.prompt(query.toString());
} else {
answer = prompter.prompt(query.toString(), Integer.toString(defaultSelection));
}
if (NumberUtils.isNumber(answer)) {
selection = archetypeAnswerMap.get(answer);
} else {
// not a number so apply filter and ask again
filteredCatalogs = ArchetypeSelectorUtils.getFilteredArchetypesByCatalog(catalogs, answer);
}
} while (selection == null);
return selectVersion(catalogs, selection.getGroupId(), selection.getArtifactId());
}
private Archetype selectVersion(Map<String, List<Archetype>> catalogs, String groupId, String artifactId)
throws PrompterException {
SortedMap<ArtifactVersion, Archetype> archetypeVersionsMap = new TreeMap<>();
for (Map.Entry<String, List<Archetype>> entry : catalogs.entrySet()) {
for (Archetype archetype : entry.getValue()) {
if (!groupId.equals(archetype.getGroupId()) || !artifactId.equals(archetype.getArtifactId())) {
continue;
}
ArtifactVersion version = new DefaultArtifactVersion(archetype.getVersion());
// don't override the first catalog containing a defined version of the artifact
if (!archetypeVersionsMap.containsKey(version)) {
archetypeVersionsMap.put(version, archetype);
}
}
}
if (archetypeVersionsMap.size() == 1) {
return archetypeVersionsMap.values().iterator().next();
}
// let the user choose between available versions
StringBuilder query = new StringBuilder("Choose " + groupId + ":" + artifactId + " version: \n");
List<String> answers = new ArrayList<>();
Map<String, Archetype> answerMap = new HashMap<>();
int counter = 1;
String mapKey = null;
for (Map.Entry<ArtifactVersion, Archetype> entry : archetypeVersionsMap.entrySet()) {
ArtifactVersion version = entry.getKey();
Archetype archetype = entry.getValue();
mapKey = String.valueOf(counter);
query.append(mapKey + ": " + version + "\n");
answers.add(mapKey);
answerMap.put(mapKey, archetype);
counter++;
}
query.append("Choose a number: ");
Archetype archetype = null;
do {
String answer = prompter.prompt(query.toString(), answers, mapKey);
archetype = answerMap.get(answer);
} while (archetype == null);
return archetype;
}
public void setPrompter(Prompter prompter) {
this.prompter = prompter;
}
}