1 package org.apache.maven.archetype.ui.generation;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.commons.lang3.math.NumberUtils;
23 import org.apache.maven.archetype.catalog.Archetype;
24 import org.apache.maven.archetype.ui.ArchetypeDefinition;
25 import org.apache.maven.artifact.versioning.ArtifactVersion;
26 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
27 import org.codehaus.plexus.component.annotations.Component;
28 import org.codehaus.plexus.component.annotations.Requirement;
29 import org.codehaus.plexus.components.interactivity.Prompter;
30 import org.codehaus.plexus.components.interactivity.PrompterException;
31 import org.codehaus.plexus.logging.AbstractLogEnabled;
32
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.SortedMap;
41 import java.util.TreeMap;
42
43 @Component( role = ArchetypeSelectionQueryer.class, hint = "default" )
44 public class DefaultArchetypeSelectionQueryer
45 extends AbstractLogEnabled
46 implements ArchetypeSelectionQueryer
47 {
48 @Requirement( hint = "archetype" )
49 private Prompter prompter;
50
51 @Override
52 public boolean confirmSelection( ArchetypeDefinition archetypeDefinition )
53 throws PrompterException
54 {
55 String query =
56 "Confirm archetype selection: \n" + archetypeDefinition.getGroupId() + "/" + archetypeDefinition.getName()
57 + "\n";
58
59 String answer = prompter.prompt( query, Arrays.asList( new String[]{ "Y", "N" } ), "Y" );
60
61 return "Y".equalsIgnoreCase( answer );
62 }
63
64 @Override
65 public Archetype selectArchetype( Map<String, List<Archetype>> catalogs )
66 throws PrompterException
67 {
68 return selectArchetype( catalogs, null );
69 }
70
71 @Override
72 public Archetype selectArchetype( Map<String, List<Archetype>> catalogs, ArchetypeDefinition defaultDefinition )
73 throws PrompterException
74 {
75 Archetype selection = null;
76 Map<String, List<Archetype>> filteredCatalogs = catalogs;
77
78 do
79 {
80 StringBuilder query = new StringBuilder( "Choose archetype:\n" );
81
82 Set<String> archetypeKeys = new HashSet<>();
83 List<String> answers = new ArrayList<>();
84 Map<String, Archetype> archetypeAnswerMap = new HashMap<>();
85
86 int counter = 0;
87 int defaultSelection = 0;
88
89 for ( Map.Entry<String, List<Archetype>> entry : filteredCatalogs.entrySet() )
90 {
91 String catalog = entry.getKey();
92
93 for ( Archetype archetype : entry.getValue() )
94 {
95 String archetypeKey = archetype.getGroupId() + ":" + archetype.getArtifactId();
96
97 if ( !archetypeKeys.add( archetypeKey ) )
98 {
99 continue;
100 }
101
102 counter++;
103
104 String description = archetype.getDescription();
105 if ( description == null )
106 {
107 description = "-";
108 }
109
110 String answer = String.valueOf( counter );
111
112 query.append( answer + ": " + catalog + " -> " + archetype.getGroupId() + ":"
113 + archetype.getArtifactId() + " (" + description + ")\n" );
114
115 answers.add( answer );
116
117 archetypeAnswerMap.put( answer, archetype );
118
119
120 if ( defaultDefinition != null && archetype.getGroupId().equals( defaultDefinition.getGroupId() )
121 && archetype.getArtifactId().equals( defaultDefinition.getArtifactId() ) )
122 {
123 defaultSelection = counter;
124 }
125 }
126 }
127
128 if ( counter == 0 )
129 {
130 query.append( " Your filter doesn't match any archetype (hint: enter to return to initial list)\n" );
131 }
132
133 query.append( "Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): " );
134
135 String answer;
136 if ( defaultSelection == 0 )
137 {
138 answer = prompter.prompt( query.toString() );
139 }
140 else
141 {
142 answer = prompter.prompt( query.toString(), Integer.toString( defaultSelection ) );
143 }
144
145 if ( NumberUtils.isNumber( answer ) )
146 {
147 selection = archetypeAnswerMap.get( answer );
148 }
149 else
150 {
151
152 filteredCatalogs = ArchetypeSelectorUtils.getFilteredArchetypesByCatalog( catalogs, answer );
153 }
154 }
155 while ( selection == null );
156
157 return selectVersion( catalogs, selection.getGroupId(), selection.getArtifactId() );
158 }
159
160 private Archetype selectVersion( Map<String, List<Archetype>> catalogs, String groupId, String artifactId )
161 throws PrompterException
162 {
163 SortedMap<ArtifactVersion, Archetype> archetypeVersionsMap = new TreeMap<>();
164
165 for ( Map.Entry<String, List<Archetype>> entry : catalogs.entrySet() )
166 {
167 for ( Archetype archetype : entry.getValue() )
168 {
169 if ( !groupId.equals( archetype.getGroupId() ) || !artifactId.equals( archetype.getArtifactId() ) )
170 {
171 continue;
172 }
173
174 ArtifactVersion version = new DefaultArtifactVersion( archetype.getVersion() );
175
176
177 if ( !archetypeVersionsMap.containsKey( version ) )
178 {
179 archetypeVersionsMap.put( version, archetype );
180 }
181 }
182 }
183
184 if ( archetypeVersionsMap.size() == 1 )
185 {
186 return archetypeVersionsMap.values().iterator().next();
187 }
188
189
190 StringBuilder query = new StringBuilder( "Choose " + groupId + ":" + artifactId + " version: \n" );
191
192 List<String> answers = new ArrayList<>();
193 Map<String, Archetype> answerMap = new HashMap<>();
194
195 int counter = 1;
196 String mapKey = null;
197
198 for ( Map.Entry<ArtifactVersion, Archetype> entry : archetypeVersionsMap.entrySet() )
199 {
200 ArtifactVersion version = entry.getKey();
201 Archetype archetype = entry.getValue();
202
203 mapKey = String.valueOf( counter );
204
205 query.append( mapKey + ": " + version + "\n" );
206
207 answers.add( mapKey );
208
209 answerMap.put( mapKey, archetype );
210
211 counter++;
212 }
213
214 query.append( "Choose a number: " );
215
216 Archetype archetype = null;
217
218 do
219 {
220 String answer = prompter.prompt( query.toString(), answers, mapKey );
221
222 archetype = answerMap.get( answer );
223 }
224 while ( archetype == null );
225
226 return archetype;
227 }
228
229 public void setPrompter( Prompter prompter )
230 {
231 this.prompter = prompter;
232 }
233 }