001 /**
002 * Copyright (C) 2007-2008, Jens Lehmann
003 *
004 * This file is part of DL-Learner.
005 *
006 * DL-Learner is free software; you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation; either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * DL-Learner is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program. If not, see <http://www.gnu.org/licenses/>.
018 *
019 */
020 package org.dllearner.scripts;
021
022 import java.io.File;
023 import java.util.ArrayList;
024 import java.util.Arrays;
025 import java.util.Collection;
026 import java.util.LinkedHashMap;
027 import java.util.LinkedList;
028 import java.util.List;
029 import java.util.Map;
030 import java.util.Set;
031 import java.util.SortedSet;
032 import java.util.TreeSet;
033
034 import org.dllearner.core.Component;
035 import org.dllearner.core.ComponentManager;
036 import org.dllearner.core.KnowledgeSource;
037 import org.dllearner.core.LearningAlgorithm;
038 import org.dllearner.core.LearningProblem;
039 import org.dllearner.core.LearningProblemUnsupportedException;
040 import org.dllearner.core.ReasonerComponent;
041 import org.dllearner.core.configurators.CELOEConfigurator;
042 import org.dllearner.core.configurators.ROLearnerConfigurator;
043 import org.dllearner.core.configurators.RefinementOperatorConfigurator;
044 import org.dllearner.core.options.ConfigOption;
045 import org.dllearner.utilities.Files;
046
047 /**
048 * Collects information about all used configuration options and writes them
049 * into a file. This way the documentation is always in sync with the source
050 * code.
051 *
052 * @author Jens Lehmann
053 * @author Sebastian Hellmann
054 *
055 */
056 public final class ConfigJavaGenerator {
057
058 private static final SortedSet<String> DONOTDELETE =
059 new TreeSet<String>(Arrays.asList(new String[]{
060 ".svn",
061 "RefinementOperatorConfigurator.java",
062 }));
063
064 // currently it targets the configurators for
065 private static final SortedSet<String> EXTENDSREFINEMENTOPERATOR =
066 new TreeSet<String>(Arrays.asList(new String[]{
067 ROLearnerConfigurator.class.getSimpleName(),
068 CELOEConfigurator.class.getSimpleName(),
069 }));
070
071 @SuppressWarnings("unchecked")
072 private static final Class EXTENDSREFINEMENTOPERATORCLASS = RefinementOperatorConfigurator.class;
073
074 private static final boolean INCLUDE_UNUSED = false;
075
076 private static final String UNUSED = "@SuppressWarnings(\"unused\")\n";
077 private static final String OVERRIDE = "@SuppressWarnings(\"all\")\n";
078
079 private static final String TARGET_DIR = "src/dl-learner/org/dllearner/core/configurators";
080
081 private static final String TARGET_PACKAGE = "org.dllearner.core.configurators";
082
083 private static final String HEADER_FILE = "doc/header.txt";
084
085 private static final String HEADER = getHeader();
086
087 private static final String REINITVAR = "reinitNecessary";
088
089 private static final String REINITGETTER = "/**\n* true, if this component needs reinitializsation.\n"
090 + "* @return boolean\n**/\n"
091 + "public boolean is"
092 + capitalize(REINITVAR)
093 + "(){\nreturn "
094 + REINITVAR + ";\n}\n";
095
096 // private static final String TEMPLATE_DIR = "doc/template/";
097
098 private static final String CONFIGURATOR = "Configurator";
099
100 private static final String COMPONENT_FACTORY = "ComponentFactory";
101 private static final String CLASS_COMMENT = "* automatically generated, do not edit manually.\n"
102 + "* run " + ConfigJavaGenerator.class.getCanonicalName()+ " to update\n";
103
104 private static final SortedSet<String> COMPONENT_FACTORY_IMPORTS = new TreeSet<String>();
105
106 private static final List<String> COMPONENT_FACTORY_METHODS = new ArrayList<String>();
107
108 private Class<? extends Component> component;
109
110 private String className;
111
112 private String componentType;
113
114 private String extendS = "";
115
116 //private String implementS = "";
117
118 private List<String> body = new ArrayList<String>();
119
120 private List<String> vars = new ArrayList<String>();
121
122 private List<String> setters = new ArrayList<String>();
123
124 private List<String> getters = new ArrayList<String>();
125
126 private SortedSet<String> imports = new TreeSet<String>();
127
128 private SortedSet<String> getinstanceExceptions = new TreeSet<String>();
129
130 private Map<String, String> additionalMandatoryVars = new LinkedHashMap<String, String>();
131
132 private Map<String, String> mandatoryVars = new LinkedHashMap<String, String>();
133
134 // private Map<String,String> varMap = new LinkedHashMap<String, String>();
135
136 private List<ConfigOption<?>> mandatoryOptions = new LinkedList<ConfigOption<?>>();
137
138 /**
139 * @param args
140 * none
141 */
142 public static void main(String[] args) {
143
144 Files.backupDirectory(TARGET_DIR);
145 System.out.println("previous classes were backupped to tmp/+System.currentTimeMillis()");
146 String[] files = Files.listDir(TARGET_DIR);
147
148 for (String file : files){
149 //System.out.println(DONOTDELETE);
150
151 if(DONOTDELETE.contains(file)){
152 continue;
153 }
154 //System.out.println(file);
155 String todelete = TARGET_DIR + File.separator + file;
156 Files.deleteFile(todelete);
157
158 }
159 //System.exit(0);
160 //Files.deleteDir(TARGET_DIR);
161
162 ComponentManager cm = ComponentManager.getInstance();
163 COMPONENT_FACTORY_IMPORTS.add(KnowledgeSource.class.getCanonicalName());
164 COMPONENT_FACTORY_IMPORTS
165 .add(ReasonerComponent.class.getCanonicalName());
166 COMPONENT_FACTORY_IMPORTS.add(LearningProblem.class.getCanonicalName());
167 COMPONENT_FACTORY_IMPORTS.add(LearningProblemUnsupportedException.class
168 .getCanonicalName());
169 COMPONENT_FACTORY_METHODS.add("private "+COMPONENT_FACTORY+"(){}\n");
170
171 for (Class<? extends KnowledgeSource> component : cm
172 .getKnowledgeSources()) {
173 String componentType = "knowledgeSource";
174
175 COMPONENT_FACTORY_IMPORTS.add(component.getCanonicalName());
176 // configuratorImports.add(TARGET_PACKAGE+"."+component.getSimpleName()+CONFIGURATOR);
177 ConfigJavaGenerator c = new ConfigJavaGenerator(component,
178 componentType);
179 c.makeConfigurator();
180
181 }
182 for (Class<? extends ReasonerComponent> component : cm
183 .getReasonerComponents()) {
184
185 COMPONENT_FACTORY_IMPORTS.add(component.getCanonicalName());
186 // configuratorImports.add(TARGET_PACKAGE+"."+component.getSimpleName()+CONFIGURATOR);
187
188 ConfigJavaGenerator c = new ConfigJavaGenerator(component,
189 "reasoner");
190 c.imports.add("org.dllearner.core.KnowledgeSource");
191 c.imports.add(Set.class.getCanonicalName());
192 c.additionalMandatoryVars.put("Set<KnowledgeSource> knowledgeSource",
193 "knowledgeSource");
194 c.makeConfigurator();
195
196 }
197 for (Class<? extends LearningProblem> component : cm
198 .getLearningProblems()) {
199
200 COMPONENT_FACTORY_IMPORTS.add(component.getCanonicalName());
201 // configuratorImports.add(TARGET_PACKAGE + "." +
202 // component.getSimpleName()+CONFIGURATOR);
203
204 ConfigJavaGenerator c = new ConfigJavaGenerator(component,
205 "learningProblem");
206 c.imports.add("org.dllearner.core.ReasonerComponent");
207 c.additionalMandatoryVars.put("ReasonerComponent reasoningService",
208 "reasoningService");
209 c.makeConfigurator();
210
211 }
212
213 for (Class<? extends LearningAlgorithm> component : cm
214 .getLearningAlgorithms()) {
215
216 COMPONENT_FACTORY_IMPORTS.add(component.getCanonicalName());
217 // configuratorImports.add(TARGET_PACKAGE+"."+
218 // component.getSimpleName()+CONFIGURATOR);
219
220 ConfigJavaGenerator c = new ConfigJavaGenerator(component,
221 "learningAlgorithm");
222 c.imports.add("org.dllearner.core.LearningProblem");
223 c.imports.add("org.dllearner.core.ReasonerComponent");
224 c.imports.add(LearningProblemUnsupportedException.class
225 .getCanonicalName());
226
227 c.additionalMandatoryVars.put("LearningProblem learningProblem",
228 "learningProblem");
229 c.additionalMandatoryVars.put("ReasonerComponent reasoningService",
230 "reasoningService");
231 c.getinstanceExceptions.add("LearningProblemUnsupportedException");
232 c.makeConfigurator();
233
234 }
235
236 makeComponentFactory();
237 makeInterface();
238 writePackageHTML();
239
240 System.out.println("Done");
241 }
242
243
244
245 private ConfigJavaGenerator(Class<? extends Component> component,
246 String componentType) {
247 this.className = component.getSimpleName();
248 this.component = component;
249 this.componentType = componentType;
250 imports.add(component.getCanonicalName());
251 imports.add(ComponentManager.class.getCanonicalName());
252 // imports.add(Configurator.class.getCanonicalName());
253 // imports.add(ConfigEntry.class.getCanonicalName());
254
255 vars.add("private " + className + " " + deCapitalize(className)
256 + ";\n");
257
258 if(EXTENDSREFINEMENTOPERATOR.contains(this.className+CONFIGURATOR)){
259 this.extendS = EXTENDSREFINEMENTOPERATORCLASS.getSimpleName();
260 this.imports.add(EXTENDSREFINEMENTOPERATORCLASS.getCanonicalName());
261 }
262
263
264 }
265
266 private void makeConfigurator() {
267
268 for (ConfigOption<?> option : ComponentManager
269 .getConfigOptions(component)) {
270
271 String type = option.getValueTypeAsJavaString();
272 String optionName = option.getName();
273 // String defaultValue = option.getDefaultValueInJava();
274 String comment = option.getJavaDocString();
275
276 if (option.isMandatory()) {
277 mandatoryVars.put(type + " " + optionName, optionName);
278 mandatoryOptions.add(option);
279 COMPONENT_FACTORY_IMPORTS.addAll(option.getJavaImports());
280 }
281
282 imports.addAll(option.getJavaImports());
283 // vars.add(fillVariableDefTemplate(optionName, type,
284 // defaultValue));
285 setters.add(fillSetterTemplate(className, comment, optionName,
286 type, option.requiresInit()));
287 getters
288 .add(fillGetterTemplate(className, comment, optionName,
289 type));
290 // System.out.println(option);
291 // componentOptions.get(component)) {
292
293 }
294
295 body.add("private boolean " + REINITVAR + " = false;");
296 body.add(UNUSED);
297 body.add(expandCollection(vars, "", "", 0));
298 body.add(fillConstructorTemplate(className));
299
300 body
301 .add(makeGetInstanceForConfigurators(getAllCommentsForOptionList(mandatoryOptions)));
302
303 // body.add(makeApplyConfigEntryForOptionList(ComponentManager.getConfigOptions(component)));
304
305 body.add(expandCollection(getters, "", "", 0));
306 body.add(expandCollection(setters, "", "", 0));
307 body.add(REINITGETTER);
308 String bodytmp = expandCollection(body, "", "\n",0);
309 String importtmp = expandCollection(imports, "import ", ";\n", 0);
310 String ret = fillClassTemplate(
311 TARGET_PACKAGE,
312 importtmp,
313 className + CONFIGURATOR,
314 extendS,
315 bodytmp ,
316 "",
317 CONFIGURATOR);
318
319 // configuratorMethods.add((className, componentType,
320 // mandatoryOptions));
321
322 Files.createFile(new File(TARGET_DIR + "/" + className + CONFIGURATOR
323 + ".java"), ret);
324
325 COMPONENT_FACTORY_METHODS
326 .add(makeComponentFactoryMethods(getAllCommentsForOptionList(mandatoryOptions)));
327 }
328
329 private static void makeInterface(){
330 String ret ="";
331 ret+= HEADER+"\n";
332 ret+= "package "+TARGET_PACKAGE+";\n\n";
333 ret+= fillJavaDocComment(CLASS_COMMENT);
334 ret+="public interface Configurator{\n}\n";
335 Files.createFile(new File(TARGET_DIR+File.separator+CONFIGURATOR+".java"), ret);
336 }
337
338 @SuppressWarnings("unused")
339 private static String makeApplyConfigEntryForOptionList(
340 List<ConfigOption<?>> options) {
341 String ret = "@SuppressWarnings({ \"unchecked\" })\n"
342 + "public <T> void applyConfigEntry(ConfigEntry<T> entry){\n";
343 ret += "String optionName = entry.getOptionName();\n";
344 // ret+="ConfigOption<T> option = entry.getOption();\n";
345 ret += "if(false){//empty block \n}";
346
347 for (ConfigOption<?> option : options) {
348 ret += "else if (optionName.equals(\"" + option.getName()
349 + "\")){\n";
350 ret += "" + option.getName() + " = ("
351 + rightType(option.getValueTypeAsJavaString()) + ") "
352 + " entry.getValue();\n}";
353
354 }
355 ret += "\n}\n";
356 return ret;
357 }
358
359 private static String getAllCommentsForOptionList(
360 List<ConfigOption<?>> options) {
361 String ret = "";
362 for (ConfigOption<?> option : options) {
363 ret += "* @param " + option.getName() + " "
364 + option.getDescription() + "\n";
365 }
366
367 return ret;
368 }
369
370 private String makeGetInstanceForConfigurators(String comments) {
371
372 Map<String, String> parametersWithType = new LinkedHashMap<String, String>();
373 Map<String, String> parametersNoType = new LinkedHashMap<String, String>();
374 String applyConf = "";
375 // parametersWithType.put("ComponentManager cm", "cm");
376 parametersNoType.put(className + ".class", className + ".class");
377 for (String s : additionalMandatoryVars.keySet()) {
378 parametersWithType.put(s, additionalMandatoryVars.get(s));
379 parametersNoType.put(s, additionalMandatoryVars.get(s));
380 comments ="* @param "+additionalMandatoryVars.get(s)+" see "+additionalMandatoryVars.get(s)+"\n"+comments;
381 }
382 for (String s : mandatoryVars.keySet()) {
383 parametersWithType.put(s, mandatoryVars.get(s));
384 applyConf += fillApplyConfigEntry("component", mandatoryVars.get(s));
385 }
386
387 String parWithType = expandCollection(parametersWithType.keySet(), "",
388 ", ", 2);
389
390 String par = expandCollection(parametersNoType.values(), "", ", ", 2);
391
392 String exceptions = "";
393 if (!getinstanceExceptions.isEmpty()) {
394 exceptions += "throws ";
395 exceptions += expandCollection(getinstanceExceptions, "", ", ", 2);
396 comments+=expandCollection(getinstanceExceptions, "* @throws ", " see \n", 0);
397 }
398 comments = fillJavaDocComment(comments + "* @return " + className
399 + "\n");
400 String ret = comments;
401 ret += "public static " + className + " get" + className + "("
402 + parWithType + ") " + exceptions + "{\n";
403 ret += className + " component = ComponentManager.getInstance()."
404 + componentType + "(" + par + ");\n";
405 ret += applyConf;
406
407 ret += "return component;\n}\n";
408
409 return ret;
410 }
411
412
413
414
415 private String makeComponentFactoryMethods(String comments) {
416
417 Map<String, String> parametersWithType = new LinkedHashMap<String, String>();
418 Map<String, String> parametersNoType = new LinkedHashMap<String, String>();
419 String applyConf = "";
420 // parametersWithType.put("ComponentManager cm", "cm");
421 parametersNoType.put(className + ".class", className + ".class");
422 for (String s : additionalMandatoryVars.keySet()) {
423 parametersWithType.put(s, additionalMandatoryVars.get(s));
424 parametersNoType.put(s, additionalMandatoryVars.get(s));
425 comments += "* @param " + additionalMandatoryVars.get(s) + " see "
426 + capitalize(additionalMandatoryVars.get(s)) + "\n";
427 }
428 for (String s : mandatoryVars.keySet()) {
429 parametersWithType.put(s, mandatoryVars.get(s));
430 applyConf += fillApplyConfigEntry("component", mandatoryVars.get(s))
431 + "";
432 }
433
434 String parWithType = expandCollection(parametersWithType.keySet(), "",
435 ", ", 2);
436
437 String par = expandCollection(parametersWithType.values(), "", ", ", 2);
438
439 String exceptions = "";
440 if (!getinstanceExceptions.isEmpty()) {
441 exceptions += "throws ";
442 exceptions += expandCollection(getinstanceExceptions, "", ", ", 2);
443 comments += expandCollection(getinstanceExceptions, "* @throws ",
444 " see\n", 0);
445 }
446 comments += "* @return a component ready for initialization "
447 + className + "\n";
448 String ret = fillJavaDocComment(comments);
449 ret += "public static " + className + " get" + className + "("
450 + parWithType + ") " + exceptions + " {\n" + "return "
451 + className + CONFIGURATOR + ".get" + className + "(" + par
452 + ");\n}\n";
453 return ret;
454 }
455
456 private static void makeComponentFactory() {
457 String ret = fillClassTemplate(TARGET_PACKAGE, expandCollection(
458 COMPONENT_FACTORY_IMPORTS, "import ", ";\n", 0),
459 COMPONENT_FACTORY, "", expandCollection(
460 COMPONENT_FACTORY_METHODS, "", "\n", 0), "final","");
461
462 Files.createFile(new File(TARGET_DIR + "/" + COMPONENT_FACTORY
463 + ".java"), ret);
464 }
465
466 private static String fillApplyConfigEntry(String className,
467 String optionName) {
468 return "ComponentManager.getInstance().applyConfigEntry("
469 + deCapitalize(className) + ", \"" + optionName + "\", "
470 + optionName + ");\n";
471 }
472
473 private static String fillConstructorTemplate(String className) {
474 return fillJavaDocComment("* @param " + deCapitalize(className)
475 + " see " + className + "\n")
476 + "public "
477 + className
478 + CONFIGURATOR
479 + "("
480 + className
481 + " "
482 + deCapitalize(className)
483 + "){\n"
484 + "this."
485 + deCapitalize(className)
486 + " = "
487 + deCapitalize(className)
488 + ";\n" + "}\n";
489 }
490
491 @SuppressWarnings("unused")
492 private static String fillVariableDefTemplate(String optionName,
493 String type, String defaultValue) {
494 return "private " + type + " " + optionName + " = " + defaultValue
495 + ";\n";
496
497 }
498
499 private static String fillJavaDocComment(String lines) {
500 return "/**\n" + lines + "**/\n";
501 }
502
503 private static String fillGetterTemplate(String className, String comment,
504 String optionName, String type) {
505 comment = comment.replaceAll("@param ", "");
506 comment += "* @return " + checkstyleAdjust(type) + " \n";
507 String ret = fillJavaDocComment(comment);
508 ret += (type.contains("<String>") || type.contains("<StringTuple>")) ? "@SuppressWarnings(\"unchecked\")\n"
509 : "";
510 ret += "public " + type + " get" + capitalize(optionName) + "() {\n";
511 ret += "return (" + rightType(type)
512 + ") ComponentManager.getInstance().";
513 ret += "getConfigOptionValue(" + deCapitalize(className) + ", \""
514 + optionName + "\") ;\n";
515 ret += "}\n";
516 return ret;
517 }
518
519 private static String fillSetterTemplate(String className, String comment,
520 String optionName, String type, boolean reinit) {
521 String ret = fillJavaDocComment(comment);
522 ret += "public void set" + capitalize(optionName);
523 ret += "(" + type + " " + optionName + ") {\n";
524 ret += fillApplyConfigEntry(className, optionName);
525 ret += (reinit) ? REINITVAR + " = true;\n" : "";
526 ret += "}\n";
527 return ret;
528 }
529
530
531
532
533 private static String fillClassTemplate(String packagE, String imports,
534 String className, String extendS, String body, String classModifier, String implementS) {
535
536
537 String ret = HEADER + "\n";
538 ret += "package " + packagE + ";\n\n";
539 ret += imports + "\n";
540 ret += fillJavaDocComment(CLASS_COMMENT);
541 ret += (INCLUDE_UNUSED) ? UNUSED : "";
542 ret += (!extendS.isEmpty()) ? OVERRIDE : "";
543 ret += "public "+classModifier+" class " + className + " "
544 + ((extendS.length() > 0) ? " extends " + extendS : "")
545 + ((implementS.length() > 0) ? " implements " + implementS : "")
546 + " {\n\n";
547 ret += body + "\n";
548 ret += "}\n";
549 return ret;
550
551 }
552
553 private static void writePackageHTML(){
554 String c = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">"+
555 "<html>"+
556 "<head></head>"+
557 "<body bgcolor=\"white\">"+
558 "<p>Automatically generated classes, which enable programmatically setting"+
559 "and getting configuration options of components.</p>"+
560 "</body>"+
561 "</html>";
562 try{
563 Files.createFile(new File(TARGET_DIR+File.separator+"package.html"), c);
564 }catch (Exception e) {
565 e.printStackTrace();
566 }
567 }
568
569
570 private static String expandCollection(Collection<String> col,
571 String before, String after, int removeChars) {
572 if (col.isEmpty()){
573 return "";
574 }
575 String ret = "";
576 for (String string : col) {
577 ret += before + string + after;
578 }
579
580 if (removeChars == 0) {
581 return ret;
582 } else {
583 return ret.substring(0, ret.length() - removeChars);
584 }
585 }
586
587 private static String capitalize(String s) {
588 String tmp = s.substring(0, 1);
589 return tmp.toUpperCase() + s.substring(1);
590 }
591
592 private static String deCapitalize(String s) {
593 String tmp = s.substring(0, 1);
594 return tmp.toLowerCase() + s.substring(1);
595 }
596
597 private static String rightType(String type) {
598 if (type.equals("int")){
599 return "Integer";
600 }else if (type.equals("boolean")){
601 return "Boolean";
602 }else if (type.equals("double")){
603 return "Double";
604 }else{
605 return type;
606 }
607
608 }
609
610
611 private static String checkstyleAdjust(String type) {
612 type = type.replaceAll("<", "(");
613 type = type.replaceAll(">", ")");
614 return type;
615 }
616
617 private static String getHeader() {
618 try {
619 return Files.readFile(new File(HEADER_FILE));
620 } catch (Exception e) {
621 e.printStackTrace();
622 }
623 return "";
624 }
625
626 }