Bug 6859 #2 Binding generator v1 refactoring
[mdsal.git] / binding / mdsal-binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / util / DefaultSourceCodeGenerator.java
1 /*
2  * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.yangtools.sal.binding.generator.util;
10
11 import java.io.File;
12 import java.io.FileWriter;
13 import java.io.IOException;
14
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
17
18 import javassist.CtClass;
19 import javassist.CtField;
20 import javassist.CtMethod;
21 import javassist.Modifier;
22 import javassist.NotFoundException;
23
24 /**
25  * The default implementation of the SourceCodeGenerator interface that generates readable source code
26  * for a runtime generated class. The appendField/appendMethod methods output source code to a temporary
27  * StringBuilder. When outputGeneratedSource is called, the entire class source code is generated and
28  * written to a file under a specified directory.
29  *
30  * @author Thomas Pantelis
31  */
32 public class DefaultSourceCodeGenerator implements SourceCodeGenerator {
33     private static final Logger LOG = LoggerFactory.getLogger(DefaultSourceCodeGenerator.class);
34
35     private static final String GENERATED_SOURCE_DIR_PROP = "org.opendaylight.yangtools.sal.generatedCodecSourceDir";
36
37     private final StringBuilder builder = new StringBuilder();
38     private final String generatedSourceDir;
39
40     /**
41      * Constructor.
42      *
43      * @param generatedSourceDir the directory in which to put generated source files. If null, the directory
44      *     is obtained from a system property (<i>org.opendaylight.yangtools.sal.generatedCodecSourceDir</i>) or
45      *     defaults to "generated-codecs".
46      */
47     public DefaultSourceCodeGenerator(String generatedSourceDir) {
48         if(generatedSourceDir != null) {
49             this.generatedSourceDir = generatedSourceDir;
50         }
51         else {
52             this.generatedSourceDir = System.getProperty(GENERATED_SOURCE_DIR_PROP, "generated-codecs");
53         }
54     }
55
56     @Override
57     public void appendField(CtField field, String value) {
58         try {
59             builder.append('\n')
60                     .append(Modifier.toString(field.getModifiers()))
61                     .append(' ').append(field.getType().getName()).append(' ')
62                     .append(field.getName());
63             if (value != null) {
64                 builder.append(" = ").append(value);
65             }
66
67             builder.append(";\n");
68         } catch (NotFoundException e) {
69             LOG.error("Error building field source for " + field.getName(), e);
70         }
71     }
72
73     @Override
74     public void appendMethod(CtMethod method, String code) {
75         try {
76             builder.append('\n')
77                     .append(Modifier.toString(method.getModifiers()))
78                     .append(' ').append(method.getReturnType().getName())
79                     .append(' ').append(method.getName()).append("( ");
80
81             CtClass[] paramTypes = method.getParameterTypes();
82             if (paramTypes != null) {
83                 for (int i = 0; i < paramTypes.length; i++) {
84                     if (i > 0) {
85                         builder.append(", ");
86                     }
87                     builder.append(paramTypes[i].getName()).append(" $")
88                             .append(i + 1);
89                 }
90             }
91
92             builder.append(" )\n").append(code).append("\n\n");
93         } catch (NotFoundException e) {
94             LOG.error("Error building method source for " + method.getName(), e);
95         }
96     }
97
98     @Override
99     public void outputGeneratedSource(CtClass ctClass) {
100         String name = ctClass.getName();
101
102         StringBuilder classBuilder = new StringBuilder();
103         classBuilder.append(Modifier.toString(ctClass.getModifiers()))
104                 .append(" class ").append(ctClass.getSimpleName());
105
106         try {
107             CtClass superClass = ctClass.getSuperclass();
108             if (superClass != null) {
109                 classBuilder.append(" extends ").append(superClass.getName());
110             }
111
112             CtClass[] interfaces = ctClass.getInterfaces();
113             if (interfaces.length > 0) {
114                 classBuilder.append(" implements ");
115                 for (int i = 0; i < interfaces.length; i++) {
116                     if (i > 0) {
117                         classBuilder.append(", ");
118                     }
119
120                     classBuilder.append(interfaces[i].getName());
121                 }
122             }
123
124             classBuilder.append(" {\n").append(builder.toString())
125                     .append("\n}");
126         } catch (NotFoundException e) {
127             LOG.error("Error building class source for " + name, e);
128             return;
129         }
130
131         File dir = new File(generatedSourceDir);
132         dir.mkdir();
133         try (FileWriter writer = new FileWriter(new File(dir, name + ".java"))) {
134             writer.append(classBuilder.toString());
135             writer.flush();
136         } catch (IOException e) {
137             LOG.error("Error writing class source for " + name, e);
138         }
139     }
140 }