1   package com.atlassian.maven.plugins.amps.codegen.prompter;
2   
3   import java.util.ArrayList;
4   import java.util.HashMap;
5   import java.util.List;
6   import java.util.Map;
7   
8   import com.atlassian.plugins.codegen.modules.NameBasedModuleProperties;
9   import com.atlassian.plugins.codegen.modules.PluginModuleLocation;
10  import com.atlassian.plugins.codegen.modules.PluginModuleProperties;
11  import com.atlassian.plugins.codegen.util.ClassnameUtil;
12  
13  import org.apache.commons.lang.StringUtils;
14  import org.codehaus.plexus.components.interactivity.Prompter;
15  import org.codehaus.plexus.components.interactivity.PrompterException;
16  
17  import jline.ANSIBuffer;
18  
19  /**
20   * @since 3.5
21   */
22  public abstract class AbstractModulePrompter<T extends PluginModuleProperties> implements PluginModulePrompter<T>
23  {
24      public static final String DEFAULT_BASE_PACKAGE = "com.example";
25  
26      protected final Prompter prompter;
27      protected boolean showExamplesPrompt;
28      protected boolean showAdvancedPrompt;
29      protected boolean showAdvancedNamePrompt;
30      protected String defaultBasePackage;
31      protected boolean useAnsiColor;
32  
33      public AbstractModulePrompter(Prompter prompter)
34      {
35          this.prompter = prompter;
36          this.showExamplesPrompt = true;
37          this.showAdvancedPrompt = true;
38          this.showAdvancedNamePrompt = true;
39  
40          String mavencolor = System.getenv("MAVEN_COLOR");
41          if (StringUtils.isNotBlank(mavencolor))
42          {
43              useAnsiColor = Boolean.parseBoolean(mavencolor);
44          } else
45          {
46              useAnsiColor = false;
47          }
48      }
49  
50      @Override
51      public <P extends PluginModuleProperties> P getModulePropertiesFromInput(PluginModuleLocation moduleLocation) throws PrompterException
52      {
53          //!!! REMOVE THIS WHEN WE SUPPORT EXAMPLE CODE
54          suppressExamplesPrompt();
55  
56          T props = (T) promptForBasicProperties(moduleLocation);
57  
58          if (showAdvancedPrompt)
59          {
60              boolean showAdvanced = promptForBoolean("Show Advanced Setup?", "N");
61              String moduleName;
62  
63              if (showAdvanced)
64              {
65                  if (props instanceof NameBasedModuleProperties)
66                  {
67                      NameBasedModuleProperties namedProps = (NameBasedModuleProperties) props;
68  
69                      if (showAdvancedNamePrompt)
70                      {
71                          moduleName = promptNotBlank("Plugin Name", namedProps.getModuleName());
72                      } else
73                      {
74                          moduleName = namedProps.getModuleName();
75                      }
76                      String moduleKey = promptNotBlank("Plugin Key", namedProps.getModuleKey());
77                      String moduleDescription = promptNotBlank("Plugin Description", namedProps.getDescription());
78                      String moduleI18nNameKey = promptNotBlank("i18n Name Key", namedProps.getNameI18nKey());
79                      String moduleI18nDescriptionKey = promptNotBlank("i18n Description Key", namedProps.getDescriptionI18nKey());
80  
81                      namedProps.setModuleName(moduleName);
82                      namedProps.setModuleKey(moduleKey);
83                      namedProps.setDescription(moduleDescription);
84                      namedProps.setNameI18nKey(moduleI18nNameKey);
85                      namedProps.setDescriptionI18nKey(moduleI18nDescriptionKey);
86                  }
87  
88                  promptForAdvancedProperties(props, moduleLocation);
89              }
90          }
91  
92          if (showExamplesPrompt)
93          {
94              props.setIncludeExamples(promptForBoolean("Include Example Code?", "N"));
95          }
96  
97          return (P) props;
98      }
99  
100     @Override
101     public abstract <T extends PluginModuleProperties> T promptForBasicProperties(PluginModuleLocation moduleLocation) throws PrompterException;
102 
103     @Override
104     public void promptForAdvancedProperties(T props, PluginModuleLocation moduleLocation) throws PrompterException
105     {
106     }
107 
108     protected String promptJavaClassname(String message) throws PrompterException
109     {
110         return promptJavaClassname(message, null);
111     }
112 
113     protected String promptJavaClassname(String message, String defaultValue) throws PrompterException
114     {
115         String classname;
116         if (StringUtils.isBlank(defaultValue))
117         {
118             classname = prompter.prompt(requiredMessage(message));
119         } else
120         {
121             classname = prompt(message, defaultValue);
122         }
123 
124         if (StringUtils.isBlank(classname) || !ClassnameUtil.isValidClassName(classname))
125         {
126             classname = promptJavaClassname(message, defaultValue);
127         }
128 
129         return classname;
130     }
131 
132     protected String promptJavaPackagename(String message) throws PrompterException
133     {
134         return promptJavaPackagename(message, null);
135     }
136 
137     protected String promptFullyQualifiedJavaClass(String message, String defaultValue) throws PrompterException
138     {
139         String fqName;
140         if (StringUtils.isBlank(defaultValue))
141         {
142 
143             fqName = prompter.prompt(requiredMessage(message));
144         } else
145         {
146             fqName = prompt(message, defaultValue);
147         }
148 
149         String packageName = "";
150         String className = "";
151         if (fqName.contains("."))
152         {
153             packageName = StringUtils.substringBeforeLast(fqName, ".");
154             className = StringUtils.substringAfterLast(fqName, ".");
155         } else
156         {
157             className = fqName;
158         }
159 
160         if (StringUtils.isBlank(fqName) || !ClassnameUtil.isValidPackageName(packageName) || !ClassnameUtil.isValidClassName(className))
161         {
162             fqName = promptFullyQualifiedJavaClass(message, defaultValue);
163         }
164 
165         return fqName;
166     }
167 
168     protected String promptFullyQualifiedJavaClassBlankOK(String message, String defaultValue) throws PrompterException
169     {
170         String fqName;
171         if (StringUtils.isBlank(defaultValue))
172         {
173             fqName = prompter.prompt(message);
174         } else
175         {
176             fqName = prompt(message, defaultValue);
177         }
178 
179         if (StringUtils.isNotBlank(fqName))
180         {
181             String packageName = "";
182             String className = "";
183             if (fqName.contains("."))
184             {
185                 packageName = StringUtils.substringBeforeLast(fqName, ".");
186                 className = StringUtils.substringAfterLast(fqName, ".");
187             } else
188             {
189                 className = fqName;
190             }
191 
192             if (!ClassnameUtil.isValidPackageName(packageName) || !ClassnameUtil.isValidClassName(className))
193             {
194                 fqName = promptFullyQualifiedJavaClass(message, defaultValue);
195             }
196         }
197 
198         return fqName;
199     }
200 
201     protected String promptJavaPackagename(String message, String defaultValue) throws PrompterException
202     {
203         String packagename;
204 
205         if (StringUtils.isBlank(defaultValue))
206         {
207             packagename = prompter.prompt(requiredMessage(message));
208         } else
209         {
210             packagename = prompt(message, defaultValue);
211         }
212 
213         if (StringUtils.isBlank(packagename) || !ClassnameUtil.isValidPackageName(packagename))
214         {
215             packagename = promptJavaPackagename(message, defaultValue);
216         }
217 
218         return packagename;
219     }
220 
221     protected String promptNotBlank(String message) throws PrompterException
222     {
223         return promptNotBlank(message, null);
224     }
225 
226     protected String promptNotBlank(String message, String defaultValue) throws PrompterException
227     {
228         String value;
229         if (StringUtils.isBlank(defaultValue))
230         {
231             value = prompter.prompt(requiredMessage(message));
232         } else
233         {
234             value = prompt(message, defaultValue);
235         }
236 
237         if (StringUtils.isBlank(value))
238         {
239             value = promptNotBlank(message, defaultValue);
240         }
241         return value;
242     }
243 
244     protected boolean promptForBoolean(String message) throws PrompterException
245     {
246         return promptForBoolean(message, null);
247     }
248 
249     protected boolean promptForBoolean(String message, String defaultValue) throws PrompterException
250     {
251         String answer;
252         boolean bool;
253         if (StringUtils.isBlank(defaultValue))
254         {
255             answer = prompter.prompt(requiredMessage(message), YN_ANSWERS);
256         } else
257         {
258             answer = prompt(message, YN_ANSWERS, defaultValue);
259         }
260 
261         if ("y".equals(answer.toLowerCase()))
262         {
263             bool = true;
264         } else
265         {
266             bool = false;
267         }
268 
269         return bool;
270     }
271 
272     protected Map<String, String> promptForParams(String message) throws PrompterException
273     {
274         Map<String, String> params = new HashMap<String, String>();
275         promptForParam(message, params);
276 
277         return params;
278     }
279 
280     protected void promptForParam(String message, Map<String, String> params) throws PrompterException
281     {
282         StringBuffer addBuffer = new StringBuffer();
283         if (params.size() > 0)
284         {
285             addBuffer.append("params:\n");
286             for (Map.Entry<String, String> entry : params.entrySet())
287             {
288                 addBuffer.append(entry.getKey())
289                         .append("->")
290                         .append(entry.getValue())
291                         .append("\n");
292             }
293         }
294         addBuffer.append(message);
295         boolean addParam = promptForBoolean(addBuffer.toString(), "N");
296 
297         if (addParam)
298         {
299             String key = promptNotBlank("param name");
300             String value = promptNotBlank("param value");
301             params.put(key, value);
302             promptForParam(message, params);
303         }
304     }
305 
306     protected List<String> promptForList(String addMessage, String enterMessage) throws PrompterException
307     {
308         List<String> vals = new ArrayList<String>();
309         promptForListValue(addMessage, enterMessage, vals);
310 
311         return vals;
312     }
313 
314     protected void promptForListValue(String addMessage, String enterMessage, List<String> vals) throws PrompterException
315     {
316         StringBuffer addBuffer = new StringBuffer();
317         if (vals.size() > 0)
318         {
319             addBuffer.append("values:\n");
320             for (String val : vals)
321             {
322                 addBuffer.append(val)
323                         .append("\n");
324             }
325         }
326         addBuffer.append(addMessage);
327         boolean addValue = promptForBoolean(addBuffer.toString(), "N");
328 
329         if (addValue)
330         {
331             String value = promptNotBlank(enterMessage);
332             vals.add(value);
333             promptForListValue(addMessage, enterMessage, vals);
334         }
335     }
336 
337     protected int promptForInt(String message, int defaultInt) throws PrompterException
338     {
339         String userVal = promptNotBlank(message, Integer.toString(defaultInt));
340         int userInt;
341         if (!StringUtils.isNumeric(userVal))
342         {
343             userInt = promptForInt(message, defaultInt);
344         } else
345         {
346             userInt = Integer.parseInt(userVal);
347         }
348         return userInt;
349     }
350 
351     protected String prompt(String message, String defaultValue) throws PrompterException
352     {
353         return prompter.prompt(message, defaultValue);
354     }
355 
356     protected String prompt(String message) throws PrompterException
357     {
358         return prompter.prompt(message);
359     }
360 
361     protected String prompt(String message, List possibleValues, String defaultValue) throws PrompterException
362     {
363         return prompter.prompt(message, possibleValues, defaultValue);
364     }
365 
366     protected void suppressExamplesPrompt()
367     {
368         this.showExamplesPrompt = false;
369     }
370 
371     protected void suppressAdvancedPrompt()
372     {
373         this.showAdvancedPrompt = false;
374     }
375 
376     protected void suppressAdvancedNamePrompt()
377     {
378         this.showAdvancedNamePrompt = false;
379     }
380 
381     public boolean isUseAnsiColor()
382     {
383         return useAnsiColor;
384     }
385 
386     public void setUseAnsiColor(boolean useAnsiColor)
387     {
388         this.useAnsiColor = useAnsiColor;
389     }
390 
391     protected String requiredMessage(String message)
392     {
393         String formattedMessage = message;
394         if (useAnsiColor)
395         {
396             ANSIBuffer ansiBuffer = new ANSIBuffer();
397             ansiBuffer.append(ANSIBuffer.ANSICodes
398                     .attrib(PrettyPrompter.BOLD))
399                     .append(ANSIBuffer.ANSICodes
400                             .attrib(PrettyPrompter.FG_RED))
401                     .append(message)
402                     .append(ANSIBuffer.ANSICodes
403                             .attrib(PrettyPrompter.OFF));
404             formattedMessage = ansiBuffer.toString();
405         }
406 
407         return formattedMessage;
408     }
409 
410     @Override
411     public void setDefaultBasePackage(String basePackage)
412     {
413         if (StringUtils.isNotBlank(basePackage))
414         {
415             this.defaultBasePackage = basePackage;
416         }
417     }
418 
419     @Override
420     public String getDefaultBasePackage()
421     {
422         if (StringUtils.isNotBlank(defaultBasePackage))
423         {
424             return defaultBasePackage;
425         } else
426         {
427             return DEFAULT_BASE_PACKAGE;
428         }
429     }
430 }