1 package org.andromda.andromdapp;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.IOException;
6 import java.io.InputStreamReader;
7 import java.net.MalformedURLException;
8 import java.net.URL;
9 import java.util.ArrayList;
10 import java.util.Iterator;
11 import java.util.LinkedHashMap;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15 import org.andromda.core.common.AndroMDALogger;
16 import org.andromda.core.common.ResourceFinder;
17 import org.andromda.core.common.ResourceUtils;
18 import org.andromda.core.common.XmlObjectFactory;
19 import org.apache.commons.lang.StringUtils;
20
21
22
23
24
25
26
27 public class AndroMDApp
28 {
29
30
31
32
33 private static final String INTERNAL_CONFIGURATION_URI = "META-INF/andromdapp/configuration.xml";
34
35
36
37
38 public void run()
39 {
40 try
41 {
42 AndroMDALogger.initialize();
43 final URL internalConfiguration = ResourceUtils.getResource(INTERNAL_CONFIGURATION_URI);
44 if (internalConfiguration == null)
45 {
46 throw new AndroMDAppException("No configuration could be loaded from --> '" +
47 INTERNAL_CONFIGURATION_URI + '\'');
48 }
49 this.addConfigurationUri(internalConfiguration.toString());
50 this.initialize();
51 this.chooseTypeAndRun(true);
52 }
53 catch (final Throwable throwable)
54 {
55 if (throwable instanceof AndroMDAppException)
56 {
57 throw (AndroMDAppException)throwable;
58 }
59 throw new AndroMDAppException(throwable);
60 }
61 }
62
63
64
65
66 static final String DESCRIPTOR = "andromdapp.xml";
67
68
69
70
71 private static final String DESCRIPTOR_DIRECTORY = "META-INF/andromdapp";
72
73
74
75
76 private final Map<String, AndroMDAppType> types = new LinkedHashMap<String, AndroMDAppType>();
77
78
79
80
81
82 private void initialize()
83 throws Exception
84 {
85 final URL[] descriptorDirectories = ResourceFinder.findResources(DESCRIPTOR_DIRECTORY);
86 if (descriptorDirectories != null && descriptorDirectories.length > 0)
87 {
88 final int numberOfDescriptorDirectories = descriptorDirectories.length;
89 for (int ctr = 0; ctr < numberOfDescriptorDirectories; ctr++)
90 {
91 final List<String> directoryContents =
92 ResourceUtils.getDirectoryContents(
93 descriptorDirectories[ctr],
94 true,
95 null);
96 for (final String uri : directoryContents)
97 {
98 if (uri.replaceAll(".*(\\\\+|/)","").equals(DESCRIPTOR))
99 {
100 final XmlObjectFactory factory = XmlObjectFactory.getInstance(AndroMDApp.class);
101 final URL descriptorUri = ResourceUtils.toURL(uri);
102 final AndroMDAppType andromdapp = (AndroMDAppType) factory.getObject(descriptorUri);
103 andromdapp.setResource(descriptorUri);
104 final String type = andromdapp.getType();
105 AndroMDALogger.info("discovered andromdapp type --> '" + type + '\'');
106 this.types.put(
107 type,
108 andromdapp);
109 }
110 }
111 }
112 }
113 }
114
115
116
117
118 private final List<Configuration> configurations = new ArrayList<Configuration>();
119
120
121
122
123
124
125
126 public void addConfigurationUri(final String configurationUri)
127 {
128 if (StringUtils.isNotBlank(configurationUri))
129 {
130 final XmlObjectFactory factory = XmlObjectFactory.getInstance(Configuration.class);
131 final URL configurationUrl = ResourceUtils.toURL(configurationUri);
132 if (configurationUrl == null)
133 {
134 throw new AndroMDAppException("configuriationUri is invalid --> '" + configurationUri + '\'');
135 }
136 this.configurations.add((Configuration)factory.getObject(configurationUrl));
137 }
138 }
139
140
141
142
143
144
145 public void addConfiguration(final String configuration)
146 {
147 if (StringUtils.isNotBlank(configuration))
148 {
149 final XmlObjectFactory factory = XmlObjectFactory.getInstance(Configuration.class);
150 this.configurations.add((Configuration)factory.getObject(configuration));
151 }
152 }
153
154
155
156
157
158 private List<File> chooseTypeAndRun(final boolean write)
159 throws Exception
160 {
161 if (this.types.isEmpty())
162 {
163 throw new AndroMDAppException("No '" + DESCRIPTOR + "' descriptor files could be found");
164 }
165 final Map<String, String> properties = new LinkedHashMap<String, String>();
166 for (Configuration configuration : this.configurations)
167 {
168 properties.putAll(configuration.getAllProperties());
169 }
170 final String applicationType = properties.get(APPLICATION_TYPE);
171 final Set<String> validTypes = this.types.keySet();
172 AndroMDAppType andromdapp = this.types.get(applicationType);
173 if (andromdapp == null)
174 {
175 if (this.types.size() > 1)
176 {
177 final StringBuilder typesChoice = new StringBuilder("[");
178 for (final Iterator<String> iterator = validTypes.iterator(); iterator.hasNext();)
179 {
180 final String type = iterator.next();
181 typesChoice.append(type);
182 if (iterator.hasNext())
183 {
184 typesChoice.append(", ");
185 }
186 }
187 typesChoice.append(']');
188 this.printText("Please choose the type of application to generate " + typesChoice);
189 String selectedType = this.readLine();
190 while (!this.types.containsKey(selectedType))
191 {
192 selectedType = this.readLine();
193 }
194 andromdapp = this.types.get(selectedType);
195 }
196 else if (!this.types.isEmpty())
197 {
198 andromdapp = this.types.entrySet().iterator().next().getValue();
199 }
200 }
201
202 if (andromdapp == null)
203 {
204 throw new AndroMDAppException("AndromdaPP is null " + this.types.entrySet());
205 }
206 andromdapp.setConfigurations(this.configurations);
207 andromdapp.initialize();
208
209 final Map templateContext = andromdapp.getTemplateContext();
210
211 final XmlObjectFactory factory = XmlObjectFactory.getInstance(AndroMDApp.class);
212 final String contents = andromdapp.promptUser();
213
214 andromdapp = (AndroMDAppType)factory.getObject(contents);
215 andromdapp.setConfigurations(this.configurations);
216 andromdapp.addToTemplateContext(templateContext);
217 return andromdapp.processResources(write);
218 }
219
220
221
222
223 private static final String APPLICATION_TYPE = "andromdappType";
224
225
226
227
228 public void clean()
229 {
230 try
231 {
232 AndroMDALogger.initialize();
233 this.initialize();
234 final List<File> list = this.chooseTypeAndRun(false);
235 for (final File file : list)
236 {
237 this.deleteFile(file);
238 }
239 }
240 catch (final Throwable throwable)
241 {
242 if (throwable instanceof AndroMDAppException)
243 {
244 throw (AndroMDAppException)throwable;
245 }
246 throw new AndroMDAppException(throwable);
247 }
248 }
249
250
251
252
253
254
255
256
257 private void deleteFile(final File file) throws MalformedURLException
258 {
259 if (file != null && file.exists())
260 {
261 final File[] children = file.listFiles();
262 if (children == null || children.length == 0)
263 {
264 if (file.delete())
265 {
266 AndroMDALogger.info("Removed: '" + file.toURI().toURL() + '\'');
267 }
268 this.deleteFile(file.getParentFile());
269 }
270 }
271 }
272
273
274
275
276
277
278 private void printText(final String text)
279 {
280 System.out.println();
281 System.out.println(text);
282 System.out.flush();
283 }
284
285
286
287
288
289
290 private String readLine()
291 {
292 final BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
293 String inputString = null;
294 try
295 {
296 inputString = input.readLine();
297 }
298 catch (final IOException exception)
299 {
300 AndroMDALogger.info("AndroMDApp Error reading inputLine from System.in");
301 }
302 return StringUtils.trimToNull(inputString);
303 }
304 }