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