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