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.lang.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 public boolean confirmSelection( ArchetypeDefinition archetypeDefinition )
52 throws PrompterException
53 {
54 String query =
55 "Confirm archetype selection: \n" + archetypeDefinition.getGroupId() + "/" + archetypeDefinition.getName()
56 + "\n";
57
58 String answer = prompter.prompt( query, Arrays.asList( new String[]{ "Y", "N" } ), "Y" );
59
60 return "Y".equalsIgnoreCase( answer );
61 }
62
63 public Archetype selectArchetype( Map<String, List<Archetype>> catalogs )
64 throws PrompterException
65 {
66 return selectArchetype( catalogs, null );
67 }
68
69 public Archetype selectArchetype( Map<String, List<Archetype>> catalogs, ArchetypeDefinition defaultDefinition )
70 throws PrompterException
71 {
72 Archetype selection = null;
73 Map<String, List<Archetype>> filteredCatalogs = catalogs;
74
75 do
76 {
77 StringBuilder query = new StringBuilder( "Choose archetype:\n" );
78
79 Set<String> archetypeKeys = new HashSet<String>();
80 List<String> answers = new ArrayList<String>();
81 Map<String, Archetype> archetypeAnswerMap = new HashMap<String, Archetype>();
82
83 int counter = 0;
84 int defaultSelection = 0;
85
86 for ( Map.Entry<String, List<Archetype>> entry : filteredCatalogs.entrySet() )
87 {
88 String catalog = entry.getKey();
89
90 for ( Archetype archetype : entry.getValue() )
91 {
92 String archetypeKey = archetype.getGroupId() + ":" + archetype.getArtifactId();
93
94 if ( !archetypeKeys.add( archetypeKey ) )
95 {
96 continue;
97 }
98
99 counter++;
100
101 String description = archetype.getDescription();
102 if ( description == null )
103 {
104 description = "-";
105 }
106
107 String answer = String.valueOf( counter );
108
109 query.append( answer + ": " + catalog + " -> " + archetype.getGroupId() + ":"
110 + archetype.getArtifactId() + " (" + description + ")\n" );
111
112 answers.add( answer );
113
114 archetypeAnswerMap.put( answer, archetype );
115
116
117 if ( defaultDefinition != null && archetype.getGroupId().equals( defaultDefinition.getGroupId() )
118 && archetype.getArtifactId().equals( defaultDefinition.getArtifactId() ) )
119 {
120 defaultSelection = counter;
121 }
122 }
123 }
124
125 if ( counter == 0 )
126 {
127 query.append( " Your filter doesn't match any archetype (hint: enter to return to initial list)\n" );
128 }
129
130 query.append( "Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): " );
131
132 String answer;
133 if ( defaultSelection == 0 )
134 {
135 answer = prompter.prompt( query.toString() );
136 }
137 else
138 {
139 answer = prompter.prompt( query.toString(), Integer.toString( defaultSelection ) );
140 }
141
142 if ( NumberUtils.isNumber( answer ) )
143 {
144 selection = archetypeAnswerMap.get( answer );
145 }
146 else
147 {
148
149 filteredCatalogs = ArchetypeSelectorUtils.getFilteredArchetypesByCatalog( catalogs, answer );
150 }
151 }
152 while ( selection == null );
153
154 return selectVersion( catalogs, selection.getGroupId(), selection.getArtifactId() );
155 }
156
157 private Archetype selectVersion( Map<String, List<Archetype>> catalogs, String groupId, String artifactId )
158 throws PrompterException
159 {
160 SortedMap<ArtifactVersion, Archetype> archetypeVersionsMap = new TreeMap<ArtifactVersion, Archetype>();
161
162 for ( Map.Entry<String, List<Archetype>> entry : catalogs.entrySet() )
163 {
164 for ( Archetype archetype : entry.getValue() )
165 {
166 if ( !groupId.equals( archetype.getGroupId() ) || !artifactId.equals( archetype.getArtifactId() ) )
167 {
168 continue;
169 }
170
171 ArtifactVersion version = new DefaultArtifactVersion( archetype.getVersion() );
172
173
174 if ( !archetypeVersionsMap.containsKey( version ) )
175 {
176 archetypeVersionsMap.put( version, archetype );
177 }
178 }
179 }
180
181 if ( archetypeVersionsMap.size() == 1 )
182 {
183 return archetypeVersionsMap.values().iterator().next();
184 }
185
186
187 StringBuilder query = new StringBuilder( "Choose " + groupId + ":" + artifactId + " version: \n" );
188
189 List<String> answers = new ArrayList<String>();
190 Map<String, Archetype> answerMap = new HashMap<String, Archetype>();
191
192 int counter = 1;
193 String mapKey = null;
194
195 for ( Map.Entry<ArtifactVersion, Archetype> entry : archetypeVersionsMap.entrySet() )
196 {
197 ArtifactVersion version = entry.getKey();
198 Archetype archetype = entry.getValue();
199
200 mapKey = String.valueOf( counter );
201
202 query.append( mapKey + ": " + version + "\n" );
203
204 answers.add( mapKey );
205
206 answerMap.put( mapKey, archetype );
207
208 counter++;
209 }
210
211 query.append( "Choose a number: " );
212
213 Archetype archetype = null;
214
215 do
216 {
217 String answer = prompter.prompt( query.toString(), answers, mapKey );
218
219 archetype = answerMap.get( answer );
220 }
221 while ( archetype == null );
222
223 return archetype;
224 }
225
226 public void setPrompter( Prompter prompter )
227 {
228 this.prompter = prompter;
229 }
230 }