View Javadoc

1   package org.apache.maven.archetype.ui.generation;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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.components.interactivity.Prompter;
28  import org.codehaus.plexus.components.interactivity.PrompterException;
29  import org.codehaus.plexus.logging.AbstractLogEnabled;
30  
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.HashMap;
34  import java.util.HashSet;
35  import java.util.List;
36  import java.util.Map;
37  import java.util.Set;
38  import java.util.SortedMap;
39  import java.util.TreeMap;
40  
41  /**
42   * @plexus.component
43   */
44  public class DefaultArchetypeSelectionQueryer
45      extends AbstractLogEnabled
46      implements ArchetypeSelectionQueryer
47  {
48      /**
49       * @plexus.requirement role-hint="archetype"
50       */
51      private Prompter prompter;
52  
53      public boolean confirmSelection( ArchetypeDefinition archetypeDefinition )
54          throws PrompterException
55      {
56          String query =
57              "Confirm archetype selection: \n" + archetypeDefinition.getGroupId() + "/" + archetypeDefinition.getName()
58                  + "\n";
59  
60          String answer = prompter.prompt( query, Arrays.asList( new String[]{ "Y", "N" } ), "Y" );
61  
62          return "Y".equalsIgnoreCase( answer );
63      }
64  
65      public Archetype selectArchetype( Map<String, List<Archetype>> catalogs )
66          throws PrompterException
67      {
68          return selectArchetype( catalogs, null );
69      }
70  
71      public Archetype selectArchetype( Map<String, List<Archetype>> catalogs, ArchetypeDefinition defaultDefinition )
72          throws PrompterException
73      {
74          Archetype selection = null;
75          Map<String, List<Archetype>> filteredCatalogs = catalogs;
76  
77          do
78          {
79              StringBuilder query = new StringBuilder( "Choose archetype:\n" );
80  
81              Set<String> archetypeKeys = new HashSet<String>();
82              List<String> answers = new ArrayList<String>();
83              Map<String, Archetype> archetypeAnswerMap = new HashMap<String, Archetype>();
84  
85              int counter = 0;
86              int defaultSelection = 0;
87  
88              for ( Map.Entry<String, List<Archetype>> entry : filteredCatalogs.entrySet() )
89              {
90                  String catalog = entry.getKey();
91  
92                  for ( Archetype archetype : entry.getValue() )
93                  {
94                      String archetypeKey = archetype.getGroupId() + ":" + archetype.getArtifactId();
95  
96                      if ( !archetypeKeys.add( archetypeKey ) )
97                      {
98                          continue;
99                      }
100 
101                     counter++;
102 
103                     String description = archetype.getDescription();
104                     if ( description == null )
105                     {
106                         description = "-";
107                     }
108 
109                     String answer = String.valueOf( counter );
110 
111                     query.append( answer + ": " + catalog + " -> " + archetype.getGroupId() + ":"
112                         + archetype.getArtifactId() + " (" + description + ")\n" );
113 
114                     answers.add( answer );
115 
116                     archetypeAnswerMap.put( answer, archetype );
117 
118                     // the version is not tested. This is intentional.
119                     if ( defaultDefinition != null && archetype.getGroupId().equals( defaultDefinition.getGroupId() )
120                         && archetype.getArtifactId().equals( defaultDefinition.getArtifactId() ) )
121                     {
122                         defaultSelection = counter;
123                     }
124                 }
125             }
126 
127             if ( counter == 0 )
128             {
129                 query.append( "   Your filter doesn't match any archetype (hint: enter to return to initial list)\n" );
130             }
131 
132             query.append( "Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): " );
133 
134             String answer;
135             if ( defaultSelection == 0 )
136             {
137                 answer = prompter.prompt( query.toString() );
138             }
139             else
140             {
141                 answer = prompter.prompt( query.toString(), Integer.toString( defaultSelection ) );
142             }
143 
144             if ( NumberUtils.isNumber( answer ) )
145             {
146                 selection = archetypeAnswerMap.get( answer );
147             }
148             else
149             {
150                 // not a number so apply filter and ask again
151                 filteredCatalogs = ArchetypeSelectorUtils.getFilteredArchetypesByCatalog( catalogs, answer );
152             }
153         }
154         while ( selection == null );
155 
156         return selectVersion( catalogs, selection.getGroupId(), selection.getArtifactId() );
157     }
158 
159     private Archetype selectVersion( Map<String, List<Archetype>> catalogs, String groupId, String artifactId )
160         throws PrompterException
161     {
162         SortedMap<ArtifactVersion, Archetype> archetypeVersionsMap = new TreeMap<ArtifactVersion, Archetype>();
163 
164         for ( Map.Entry<String, List<Archetype>> entry : catalogs.entrySet() )
165         {
166             for ( Archetype archetype : entry.getValue() )
167             {
168                 if ( !groupId.equals( archetype.getGroupId() ) || !artifactId.equals( archetype.getArtifactId() ) )
169                 {
170                     continue;
171                 }
172 
173                 ArtifactVersion version = new DefaultArtifactVersion( archetype.getVersion() );
174 
175                 // don't override the first catalog containing a defined version of the artifact
176                 if ( !archetypeVersionsMap.containsKey( version ) )
177                 {
178                     archetypeVersionsMap.put( version, archetype );
179                 }
180             }
181         }
182 
183         if ( archetypeVersionsMap.size() == 1 )
184         {
185             return archetypeVersionsMap.values().iterator().next();
186         }
187 
188         // let the user choose between available versions
189         StringBuilder query = new StringBuilder( "Choose version: \n" );
190 
191         List<String> answers = new ArrayList<String>();
192         Map<String, Archetype> answerMap = new HashMap<String, Archetype>();
193 
194         int counter = 1;
195         String mapKey = null;
196 
197         for ( Map.Entry<ArtifactVersion, Archetype> entry : archetypeVersionsMap.entrySet() )
198         {
199             ArtifactVersion version = entry.getKey();
200             Archetype archetype = entry.getValue();
201 
202             mapKey = String.valueOf( counter );
203 
204             query.append( mapKey + ": " + version + "\n" );
205 
206             answers.add( mapKey );
207 
208             answerMap.put( mapKey, archetype );
209 
210             counter++;
211         }
212 
213         query.append( "Choose a number: " );
214 
215         Archetype archetype = null;
216 
217         do
218         {
219             String answer = prompter.prompt( query.toString(), answers, mapKey );
220 
221             archetype = answerMap.get( answer );
222         }
223         while ( archetype == null );
224 
225         return archetype;
226     }
227 
228     public void setPrompter( Prompter prompter )
229     {
230         this.prompter = prompter;
231     }
232 }