diff options
Diffstat (limited to 'Metrics/Metrics-Calculation/RealisticRunner/src/ca/mcgill/dslreasoner/runner/RandomEMFRunner.java')
-rw-r--r-- | Metrics/Metrics-Calculation/RealisticRunner/src/ca/mcgill/dslreasoner/runner/RandomEMFRunner.java | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/Metrics/Metrics-Calculation/RealisticRunner/src/ca/mcgill/dslreasoner/runner/RandomEMFRunner.java b/Metrics/Metrics-Calculation/RealisticRunner/src/ca/mcgill/dslreasoner/runner/RandomEMFRunner.java new file mode 100644 index 00000000..ddc5e26b --- /dev/null +++ b/Metrics/Metrics-Calculation/RealisticRunner/src/ca/mcgill/dslreasoner/runner/RandomEMFRunner.java | |||
@@ -0,0 +1,402 @@ | |||
1 | package ca.mcgill.dslreasoner.runner; | ||
2 | |||
3 | import java.io.IOException; | ||
4 | import java.io.PrintWriter; | ||
5 | import java.io.StringWriter; | ||
6 | import java.text.MessageFormat; | ||
7 | import java.util.ArrayList; | ||
8 | import java.util.Collections; | ||
9 | import java.util.Comparator; | ||
10 | import java.util.List; | ||
11 | import java.util.logging.Logger; | ||
12 | |||
13 | import org.apache.commons.cli.CommandLine; | ||
14 | import org.apache.commons.cli.CommandLineParser; | ||
15 | import org.apache.commons.cli.GnuParser; | ||
16 | import org.apache.commons.cli.HelpFormatter; | ||
17 | import org.apache.commons.cli.Option; | ||
18 | import org.apache.commons.cli.OptionBuilder; | ||
19 | import org.apache.commons.cli.Options; | ||
20 | import org.apache.commons.cli.ParseException; | ||
21 | import org.apache.commons.lang3.Range; | ||
22 | import org.eclipse.emf.common.util.BasicDiagnostic; | ||
23 | import org.eclipse.emf.common.util.Diagnostic; | ||
24 | import org.eclipse.emf.common.util.URI; | ||
25 | import org.eclipse.emf.ecore.EObject; | ||
26 | import org.eclipse.emf.ecore.EPackage; | ||
27 | import org.eclipse.emf.ecore.EcorePackage; | ||
28 | import org.eclipse.emf.ecore.resource.Resource; | ||
29 | import org.eclipse.emf.ecore.resource.impl.ResourceImpl; | ||
30 | import org.eclipse.emf.ecore.util.Diagnostician; | ||
31 | import org.eclipse.emf.ecore.util.EcoreUtil; | ||
32 | import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl; | ||
33 | import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; | ||
34 | import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl; | ||
35 | |||
36 | import fr.inria.atlanmod.instantiator.GenerationException; | ||
37 | import fr.inria.atlanmod.instantiator.GenericMetamodelConfig; | ||
38 | import fr.obeo.emf.specimen.SpecimenGenerator; | ||
39 | |||
40 | public class RandomEMFRunner implements IGeneratorRunner{ | ||
41 | public final static Logger LOGGER = Logger.getLogger(RandomEMFRunner.class.getName()); | ||
42 | |||
43 | protected GenericMetamodelConfig config; | ||
44 | |||
45 | protected SpecimenGenerator generator; | ||
46 | private int size; | ||
47 | |||
48 | private static final int DEFAULT_AVERAGE_MODEL_SIZE = 1000; | ||
49 | private static final float DEFAULT_DEVIATION = 0.1f; | ||
50 | |||
51 | private static final int ERROR = 1; | ||
52 | |||
53 | private static final String METAMODEL = "m"; | ||
54 | private static final String METAMODEL_LONG = "metamodel"; | ||
55 | private static final String ADDITIONAL_METAMODEL = "a"; | ||
56 | private static final String ADDITIONAL_METAMODEL_LONG = "additional-metamodel"; | ||
57 | private static final String OUTPUT_DIR = "o"; | ||
58 | private static final String OUTPUT_DIR_LONG = "output-dir"; | ||
59 | private static final String N_MODELS = "n"; | ||
60 | private static final String N_MODELS_LONG = "number-models"; | ||
61 | private static final String SIZE = "s"; | ||
62 | private static final String SIZE_LONG = "size"; | ||
63 | private static final String VARIATION = "p"; | ||
64 | private static final String VARIATION_LONG = "variation"; | ||
65 | private static final String PROP_VARIATION = "v"; | ||
66 | private static final String PROP_VARIATION_LONG = "properties-variation"; | ||
67 | private static final String DEGREE = "d"; | ||
68 | private static final String DEGREE_LONG = "references-degree"; | ||
69 | private static final String VALUES_SIZE = "z"; | ||
70 | private static final String VALUES_SIZE_LONG = "values-size"; | ||
71 | private static final String SEED = "e"; | ||
72 | private static final String SEED_LONG = "seed"; | ||
73 | private static final String FORCE = "f"; | ||
74 | private static final String FORCE_LONG = "force"; | ||
75 | private static final String DIAGNOSE = "g"; | ||
76 | private static final String DIAGNOSE_LONG = "diagnose"; | ||
77 | private static final String ROOT = "r"; | ||
78 | private static final String ROOT_LONG = "root"; | ||
79 | |||
80 | public RandomEMFRunner(String[] args) throws IllegalArgumentException, GenerationException, IOException { | ||
81 | super(); | ||
82 | this.config = config(args); | ||
83 | |||
84 | generator = new SpecimenGenerator(config, config.getSeed()); | ||
85 | } | ||
86 | |||
87 | |||
88 | private static class OptionComparator<T extends Option> implements Comparator<T> { | ||
89 | private static final String OPTS_ORDER = "maonspdzefg"; | ||
90 | |||
91 | @Override | ||
92 | public int compare(T o1, T o2) { | ||
93 | return OPTS_ORDER.indexOf(o1.getOpt()) - OPTS_ORDER.indexOf(o2.getOpt()); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | public GenericMetamodelConfig config(String[] args) throws GenerationException, IOException { | ||
98 | |||
99 | { | ||
100 | // Initialize the global registry | ||
101 | Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put( | ||
102 | EcorePackage.eNS_PREFIX, new EcoreResourceFactoryImpl()); | ||
103 | Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put( | ||
104 | Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl()); | ||
105 | } | ||
106 | |||
107 | Options options = new Options(); | ||
108 | |||
109 | configureOptions(options); | ||
110 | |||
111 | CommandLineParser parser = new GnuParser(); | ||
112 | |||
113 | try { | ||
114 | CommandLine commandLine = parser.parse(options, args); | ||
115 | |||
116 | String metamodel = commandLine.getOptionValue(METAMODEL); | ||
117 | |||
118 | Resource metamodelResource = new XMIResourceImpl(URI.createFileURI(metamodel)); | ||
119 | metamodelResource.load(Collections.emptyMap()); | ||
120 | EcoreUtil.resolveAll(metamodelResource); | ||
121 | { | ||
122 | BasicDiagnostic diagnosticChain = diagnoseResource(metamodelResource); | ||
123 | if (isFailed(diagnosticChain)) { | ||
124 | LOGGER.severe(MessageFormat.format( | ||
125 | "Found ''{0}'' unrecoverable issues(s) in the resource ''{1}''. Please fix them before attempting a generation or use option -{2}|--{3}.", | ||
126 | diagnosticChain.getChildren().size(), metamodelResource.getURI(), FORCE, FORCE_LONG)); | ||
127 | for (Diagnostic diagnostic : diagnosticChain.getChildren()) { | ||
128 | LOGGER.severe(diagnostic.getMessage()); | ||
129 | } | ||
130 | if (commandLine.hasOption(FORCE)) { | ||
131 | LOGGER.info(MessageFormat.format( | ||
132 | "An attempt to run the generation will be done anyway (-{0}|--{1} option selected)", | ||
133 | FORCE, FORCE_LONG)); | ||
134 | } else { | ||
135 | System.exit(ERROR); | ||
136 | } | ||
137 | } else if (isWarning(diagnosticChain)) { | ||
138 | LOGGER.warning(MessageFormat.format( | ||
139 | "Found ''{0}'' issue(s) in the resource ''{1}''. An attempt to run the generation will be done anyway.", | ||
140 | diagnosticChain.getChildren().size(), metamodelResource.getURI())); | ||
141 | for (Diagnostic diagnostic : diagnosticChain.getChildren()) { | ||
142 | LOGGER.fine(diagnostic.getMessage()); | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | |||
147 | registerPackages(metamodelResource); | ||
148 | |||
149 | size = DEFAULT_AVERAGE_MODEL_SIZE; | ||
150 | if (commandLine.hasOption(SIZE)) { | ||
151 | Number number = (Number) commandLine.getParsedOptionValue(SIZE); | ||
152 | size = (int) Math.min(Integer.MAX_VALUE, number.longValue()); | ||
153 | } | ||
154 | |||
155 | float variation = DEFAULT_DEVIATION; | ||
156 | if (commandLine.hasOption(VARIATION)) { | ||
157 | Number number = (Number) commandLine.getParsedOptionValue(VARIATION); | ||
158 | if (number.floatValue() < 0.0f || number.floatValue() > 1.0f) { | ||
159 | throw new ParseException(MessageFormat.format("Invalid value for option -{0}: {1}", VARIATION, number.floatValue())); | ||
160 | } | ||
161 | variation = number.floatValue(); | ||
162 | } | ||
163 | |||
164 | float propVariation = DEFAULT_DEVIATION; | ||
165 | if (commandLine.hasOption(PROP_VARIATION)) { | ||
166 | Number number = (Number) commandLine.getParsedOptionValue(PROP_VARIATION); | ||
167 | if (number.floatValue() < 0.0f || number.floatValue() > 1.0f) { | ||
168 | throw new ParseException(MessageFormat.format("Invalid value for option -{0}: {1}", PROP_VARIATION, number.floatValue())); | ||
169 | } | ||
170 | propVariation = number.floatValue(); | ||
171 | } | ||
172 | |||
173 | |||
174 | long seed = System.currentTimeMillis(); | ||
175 | if (commandLine.hasOption(SEED)) { | ||
176 | seed = ((Number) commandLine.getParsedOptionValue(SEED)).longValue(); | ||
177 | } | ||
178 | |||
179 | String root = null; | ||
180 | if (commandLine.hasOption(ROOT)) { | ||
181 | root = (String) commandLine.getParsedOptionValue(ROOT); | ||
182 | } | ||
183 | |||
184 | Range<Integer> range = Range.between( | ||
185 | Math.round(size * (1 - variation)), | ||
186 | Math.round(size * (1 + variation))); | ||
187 | |||
188 | GenericMetamodelConfig config = new GenericMetamodelConfig(metamodelResource, range, seed, root); | ||
189 | |||
190 | int valuesSize = GenericMetamodelConfig.DEFAULT_AVERAGE_VALUES_LENGTH; | ||
191 | if (commandLine.hasOption(VALUES_SIZE)) { | ||
192 | Number number = (Number) commandLine.getParsedOptionValue(VALUES_SIZE); | ||
193 | valuesSize = (int) Math.min(Integer.MAX_VALUE, number.longValue()); | ||
194 | } | ||
195 | |||
196 | int referencesSize = GenericMetamodelConfig.DEFAULT_AVERAGE_REFERENCES_SIZE; | ||
197 | if (commandLine.hasOption(VALUES_SIZE)) { | ||
198 | Number number = (Number) commandLine.getParsedOptionValue(DEGREE); | ||
199 | referencesSize = (int) Math.min(Integer.MAX_VALUE, number.longValue()); | ||
200 | } | ||
201 | |||
202 | |||
203 | config.setValuesRange( | ||
204 | Math.round(valuesSize * (1 - propVariation)), | ||
205 | Math.round(valuesSize * (1 + propVariation))); | ||
206 | |||
207 | config.setReferencesRange( | ||
208 | Math.round(referencesSize * (1 - propVariation)), | ||
209 | Math.round(referencesSize * (1 + propVariation))); | ||
210 | |||
211 | config.setPropertiesRange( | ||
212 | Math.round(referencesSize * (1 - propVariation)), | ||
213 | Math.round(referencesSize * (1 + propVariation))); | ||
214 | |||
215 | return config; | ||
216 | |||
217 | } catch (ParseException e) { | ||
218 | System.err.println(e.getLocalizedMessage()); | ||
219 | HelpFormatter formatter = new HelpFormatter(); | ||
220 | formatter.setOptionComparator(new OptionComparator<Option>()); | ||
221 | formatter.printHelp("java -jar <this-file.jar>", options, true); | ||
222 | System.exit(ERROR); | ||
223 | return null; | ||
224 | } catch (Throwable t) { | ||
225 | System.err.println("ERROR: " + t.getLocalizedMessage()); | ||
226 | StringWriter stringWriter = new StringWriter(); | ||
227 | t.printStackTrace(new PrintWriter(stringWriter)); | ||
228 | t.printStackTrace(); | ||
229 | LOGGER.fine(stringWriter.toString()); | ||
230 | System.exit(ERROR); | ||
231 | return null; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | |||
236 | |||
237 | private static BasicDiagnostic diagnoseResource(Resource resource) { | ||
238 | BasicDiagnostic diagnosticChain = new BasicDiagnostic(); | ||
239 | for (EObject eObject : resource.getContents()) { | ||
240 | Diagnostician.INSTANCE.validate(eObject, diagnosticChain); | ||
241 | } | ||
242 | return diagnosticChain; | ||
243 | } | ||
244 | |||
245 | private static boolean isFailed(BasicDiagnostic diagnosticChain) { | ||
246 | return (diagnosticChain.getSeverity() & Diagnostic.ERROR) == Diagnostic.ERROR; | ||
247 | } | ||
248 | |||
249 | private static boolean isWarning(BasicDiagnostic diagnosticChain) { | ||
250 | return (diagnosticChain.getSeverity() & Diagnostic.WARNING) == Diagnostic.WARNING; | ||
251 | } | ||
252 | |||
253 | |||
254 | /** | ||
255 | * Configures the program options | ||
256 | * | ||
257 | * @param options | ||
258 | */ | ||
259 | private static void configureOptions(Options options) { | ||
260 | Option metamodelOpt = OptionBuilder.create(METAMODEL); | ||
261 | metamodelOpt.setLongOpt(METAMODEL_LONG); | ||
262 | metamodelOpt.setArgName("path_to_metamodel.ecore"); | ||
263 | metamodelOpt.setDescription("Ecore metamodel"); | ||
264 | metamodelOpt.setArgs(1); | ||
265 | metamodelOpt.setRequired(true); | ||
266 | |||
267 | Option additionalMetamodelOpt = OptionBuilder.create(ADDITIONAL_METAMODEL); | ||
268 | additionalMetamodelOpt.setLongOpt(ADDITIONAL_METAMODEL_LONG); | ||
269 | additionalMetamodelOpt.setArgName("path_to_metamodel.ecore"); | ||
270 | additionalMetamodelOpt.setDescription("Additional ecore metamodel(s) that need to be registered"); | ||
271 | additionalMetamodelOpt.setArgs(Option.UNLIMITED_VALUES); | ||
272 | |||
273 | Option outDirOpt = OptionBuilder.create(OUTPUT_DIR); | ||
274 | outDirOpt.setLongOpt(OUTPUT_DIR_LONG); | ||
275 | outDirOpt.setArgName("path_to_output.dir"); | ||
276 | outDirOpt.setDescription("Output directory (defaults to working dir)"); | ||
277 | outDirOpt.setArgs(1); | ||
278 | |||
279 | Option nModelsOpt = OptionBuilder.create(N_MODELS); | ||
280 | nModelsOpt.setLongOpt(N_MODELS_LONG); | ||
281 | nModelsOpt.setArgName("models"); | ||
282 | nModelsOpt.setDescription("Number of generated models (defaults to 1)"); | ||
283 | nModelsOpt.setType(Number.class); | ||
284 | nModelsOpt.setArgs(1); | ||
285 | |||
286 | Option sizeOption = OptionBuilder.create(SIZE); | ||
287 | sizeOption.setLongOpt(SIZE_LONG); | ||
288 | sizeOption.setArgName("size"); | ||
289 | sizeOption.setDescription(MessageFormat.format("Average models'' size (defaults to {0})", DEFAULT_AVERAGE_MODEL_SIZE)); | ||
290 | sizeOption.setType(Number.class); | ||
291 | sizeOption.setArgs(1); | ||
292 | |||
293 | Option variationOption = OptionBuilder.create(VARIATION); | ||
294 | variationOption.setLongOpt(VARIATION_LONG); | ||
295 | variationOption.setArgName("proportion"); | ||
296 | variationOption.setDescription( | ||
297 | MessageFormat.format("Variation ([0..1]) in the models'' size (defaults to {0})", | ||
298 | DEFAULT_DEVIATION)); | ||
299 | variationOption.setType(Number.class); | ||
300 | variationOption.setArgs(1); | ||
301 | |||
302 | Option propVariationOption = OptionBuilder.create(PROP_VARIATION); | ||
303 | propVariationOption.setLongOpt(PROP_VARIATION_LONG); | ||
304 | propVariationOption.setArgName("properties deviation"); | ||
305 | propVariationOption.setDescription( | ||
306 | MessageFormat.format("Variation ([0..1]) in the properties'' size (defaults to {0})", | ||
307 | DEFAULT_DEVIATION)); | ||
308 | propVariationOption.setType(Number.class); | ||
309 | propVariationOption.setArgs(1); | ||
310 | |||
311 | Option seedOption = OptionBuilder.create(SEED); | ||
312 | seedOption.setLongOpt(SEED_LONG); | ||
313 | seedOption.setArgName("seed"); | ||
314 | seedOption.setDescription("Seed number (random by default)"); | ||
315 | seedOption.setType(Number.class); | ||
316 | seedOption.setArgs(1); | ||
317 | |||
318 | Option rootOption = OptionBuilder.create(ROOT); | ||
319 | rootOption.setLongOpt(ROOT_LONG); | ||
320 | rootOption.setArgName("root"); | ||
321 | rootOption.setDescription("root class of the generated model (random by default)"); | ||
322 | rootOption.setType(String.class); | ||
323 | rootOption.setArgs(1); | ||
324 | |||
325 | Option valuesSizeOption = OptionBuilder.create(VALUES_SIZE); | ||
326 | valuesSizeOption.setLongOpt(VALUES_SIZE_LONG); | ||
327 | valuesSizeOption.setArgName("size"); | ||
328 | valuesSizeOption.setDescription( | ||
329 | MessageFormat.format("Average size for attributes with variable length (defaults to {0}). Actual sizes may vary +/- {1}%.", | ||
330 | GenericMetamodelConfig.DEFAULT_AVERAGE_VALUES_LENGTH, GenericMetamodelConfig.DEFAULT_VALUES_DEVIATION * 100)); | ||
331 | valuesSizeOption.setType(Number.class); | ||
332 | valuesSizeOption.setArgs(1); | ||
333 | |||
334 | Option degreeOption = OptionBuilder.create(DEGREE); | ||
335 | degreeOption.setLongOpt(DEGREE_LONG); | ||
336 | degreeOption.setArgName("degree"); | ||
337 | degreeOption.setDescription( | ||
338 | MessageFormat.format("Average number of references per EObject (defaults to {0}). Actual sizes may vary +/- {1}%.", | ||
339 | GenericMetamodelConfig.DEFAULT_AVERAGE_REFERENCES_SIZE, GenericMetamodelConfig.DEFAULT_REFERENCES_DEVIATION * 100)); | ||
340 | degreeOption.setType(Number.class); | ||
341 | degreeOption.setArgs(1); | ||
342 | |||
343 | Option forceOption = OptionBuilder.create(FORCE); | ||
344 | forceOption.setLongOpt(FORCE_LONG); | ||
345 | forceOption.setDescription("Force the generation, even if input metamodels contain errors"); | ||
346 | |||
347 | Option diagnoseOption = OptionBuilder.create(DIAGNOSE); | ||
348 | diagnoseOption.setLongOpt(DIAGNOSE_LONG); | ||
349 | diagnoseOption.setDescription("Run diagnosis on the result model"); | ||
350 | |||
351 | |||
352 | options.addOption(metamodelOpt); | ||
353 | options.addOption(additionalMetamodelOpt); | ||
354 | options.addOption(outDirOpt); | ||
355 | options.addOption(nModelsOpt); | ||
356 | options.addOption(sizeOption); | ||
357 | options.addOption(variationOption); | ||
358 | options.addOption(propVariationOption); | ||
359 | options.addOption(valuesSizeOption); | ||
360 | options.addOption(degreeOption); | ||
361 | options.addOption(seedOption); | ||
362 | options.addOption(rootOption); | ||
363 | options.addOption(forceOption); | ||
364 | options.addOption(diagnoseOption); | ||
365 | } | ||
366 | |||
367 | /** | ||
368 | * Registers the packages | ||
369 | * @param resource | ||
370 | */ | ||
371 | private static void registerPackages(Resource resource) { | ||
372 | EObject eObject = resource.getContents().get(0); | ||
373 | if (eObject instanceof EPackage) { | ||
374 | EPackage p = (EPackage) eObject; | ||
375 | EPackage.Registry.INSTANCE.put(p.getNsURI(), p); | ||
376 | } | ||
377 | } | ||
378 | |||
379 | @Override | ||
380 | public List<EObject> runGeneration(int run) throws GenerationException { | ||
381 | |||
382 | List<EObject> roots = new ArrayList<EObject>(); | ||
383 | |||
384 | generator = new SpecimenGenerator(config, System.currentTimeMillis()); | ||
385 | |||
386 | for (int i = 0; i < run; i++) { | ||
387 | ResourceImpl resource = new ResourceImpl(); | ||
388 | generator.generate(resource); | ||
389 | roots.add(resource.getContents().get(0)); | ||
390 | } | ||
391 | |||
392 | return roots; | ||
393 | |||
394 | } | ||
395 | |||
396 | protected String getMetaModelResourceName() { | ||
397 | URI metamodelURI = config.getMetamodelResource().getURI(); | ||
398 | return metamodelURI.lastSegment().substring(0, metamodelURI.lastSegment().indexOf(".")); | ||
399 | } | ||
400 | |||
401 | |||
402 | } | ||