ce44f64c5be51d618f7701a17d66b1cf58fb404f
[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 package org.opendaylight.mdsal.binding.generator.util;
9
10 import com.google.common.io.Files;
11 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
12 import java.io.BufferedWriter;
13 import java.io.File;
14 import java.io.IOException;
15 import java.nio.charset.StandardCharsets;
16 import javassist.CtClass;
17 import javassist.CtField;
18 import javassist.CtMethod;
19 import javassist.Modifier;
20 import javassist.NotFoundException;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
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  * @deprecated Code generation is a concert separate from type mapping and is an implementation detail.
33  */
34 @Deprecated
35 public class DefaultSourceCodeGenerator implements SourceCodeGenerator {
36     private static final Logger LOG = LoggerFactory.getLogger(DefaultSourceCodeGenerator.class);
37
38     private static final String GENERATED_SOURCE_DIR_PROP = "org.opendaylight.yangtools.sal.generatedCodecSourceDir";
39
40     private final StringBuilder builder = new StringBuilder();
41     private final String generatedSourceDir;
42
43     /**
44      * Constructor.
45      *
46      * @param generatedSourceDir the directory in which to put generated source files. If null, the directory
47      *     is obtained from a system property (<i>org.opendaylight.yangtools.sal.generatedCodecSourceDir</i>) or
48      *     defaults to "generated-codecs".
49      */
50     public DefaultSourceCodeGenerator(final String generatedSourceDir) {
51         if (generatedSourceDir != null) {
52             this.generatedSourceDir = generatedSourceDir;
53         } else {
54             this.generatedSourceDir = System.getProperty(GENERATED_SOURCE_DIR_PROP, "generated-codecs");
55         }
56     }
57
58     @Override
59     public void appendField(final CtField field, final String value) {
60         try {
61             builder.append('\n')
62                     .append(Modifier.toString(field.getModifiers()))
63                     .append(' ').append(field.getType().getName()).append(' ')
64                     .append(field.getName());
65             if (value != null) {
66                 builder.append(" = ").append(value);
67             }
68
69             builder.append(";\n");
70         } catch (NotFoundException e) {
71             LOG.error("Error building field source for {}", field.getName(), e);
72         }
73     }
74
75     @Override
76     public void appendMethod(final CtMethod method, final String code) {
77         try {
78             builder.append('\n')
79                     .append(Modifier.toString(method.getModifiers()))
80                     .append(' ').append(method.getReturnType().getName())
81                     .append(' ').append(method.getName()).append("( ");
82
83             CtClass[] paramTypes = method.getParameterTypes();
84             if (paramTypes != null) {
85                 for (int i = 0; i < paramTypes.length; i++) {
86                     if (i > 0) {
87                         builder.append(", ");
88                     }
89                     builder.append(paramTypes[i].getName()).append(" $")
90                             .append(i + 1);
91                 }
92             }
93
94             builder.append(" )\n").append(code).append("\n\n");
95         } catch (NotFoundException e) {
96             LOG.error("Error building method source for {}", method.getName(), e);
97         }
98     }
99
100     @Override
101     @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
102     public void outputGeneratedSource(final CtClass ctClass) {
103         String name = ctClass.getName();
104
105         StringBuilder classBuilder = new StringBuilder();
106         classBuilder.append(Modifier.toString(ctClass.getModifiers()))
107                 .append(" class ").append(ctClass.getSimpleName());
108
109         try {
110             CtClass superClass = ctClass.getSuperclass();
111             if (superClass != null) {
112                 classBuilder.append(" extends ").append(superClass.getName());
113             }
114
115             CtClass[] interfaces = ctClass.getInterfaces();
116             if (interfaces.length > 0) {
117                 classBuilder.append(" implements ");
118                 for (int i = 0; i < interfaces.length; i++) {
119                     if (i > 0) {
120                         classBuilder.append(", ");
121                     }
122
123                     classBuilder.append(interfaces[i].getName());
124                 }
125             }
126
127             classBuilder.append(" {\n").append(builder).append("\n}");
128         } catch (NotFoundException e) {
129             LOG.error("Error building class source for {}", name, e);
130             return;
131         }
132
133         File dir = new File(generatedSourceDir);
134         if (!dir.mkdir()) {
135             LOG.warn("Failed to create directory {}, attempting to continue", generatedSourceDir);
136         }
137
138         try (BufferedWriter writer = Files.newWriter(new File(dir, name + ".java"), StandardCharsets.UTF_8)) {
139             writer.append(classBuilder);
140             writer.flush();
141         } catch (IOException e) {
142             LOG.error("Error writing class source for {}", name, e);
143         }
144     }
145 }