package org.etsi.mts.tdl.execution.java.codegen; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.FileChannel; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.Hashtable; import java.util.Map; import java.util.Set; import javax.lang.model.SourceVersion; import org.etsi.mts.tdl.DataElementMapping; import org.etsi.mts.tdl.Element; import org.etsi.mts.tdl.MappableDataElement; import org.etsi.mts.tdl.Package; public abstract class Renderer { private static final String LF = System.getProperty("line.separator"); private File generationDir; private String rootPackageName; protected Map elementNames = new Hashtable(); private CharBuffer buf; private String indent = ""; public Renderer(File generationDir, String packageName) { this.generationDir = generationDir; this.rootPackageName = packageName; } protected String getRootPackageName() { return rootPackageName; } protected void setRootPackageName(String rootPackageName) { this.rootPackageName = rootPackageName; } final void writeClassFile(String packageName, String className, ContentRenderer r) throws IOException { File packageDir = this.generationDir; for (String p : packageName.split("\\.")) packageDir = new File(packageDir, p); packageDir.mkdirs(); File classFile = new File(packageDir, className + ".java"); buf = CharBuffer.allocate(1 * 1024 * 1024); r.doRender(); buf.flip(); CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder(); ByteBuffer bytes; try { bytes = encoder.encode(buf); encoder.flush(bytes); bytes.rewind(); } catch (CharacterCodingException e) { throw new RuntimeException(e); } classFile.createNewFile(); // Stream gets closed by the channel try (FileChannel out = new FileOutputStream(classFile).getChannel()) { out.write(bytes); } } protected void writeImports(Set imports) { for (String i : imports) { line("import " + i + ";"); } newLine(); } protected String getPackageName(Package p) { // JDK classes if (p.getName().startsWith("java.")) return p.getName(); return getElementName(p); } protected String getElementName(Element e) { if (e instanceof MappableDataElement) { DataElementMapping mapping = getMapping((MappableDataElement) e); if (mapping != null) return mapping.getElementURI(); } else { String name = this.elementNames.get(e); if (name != null) return name; } String name = e.getName(); if (name == null) name = e.eClass().getName(); String identifier = getIdentifier(name); int i = 1; name = identifier; while (this.elementNames.containsValue(name)) name = identifier + "_" + i++; this.elementNames.put(e, name); return name; } protected abstract DataElementMapping getMapping(MappableDataElement e); protected void append(String text) { buf.append(text); } protected void blockOpen() { append(" {"); indent += "\t"; newLine(); } protected void blockClose() { indent = indent.substring(1); // Rewind a tab buf.position(buf.position() - 1); line("}"); } protected void blockCloseArrow() { indent = indent.substring(1); // Rewind a tab buf.position(buf.position() - 1); line("});"); } protected void blockCloseMethod() { indent = indent.substring(1); // Rewind a tab buf.position(buf.position() - 1); line("};"); } protected void blockOpenParen() { append(" ("); indent += "\t"; newLine(); } protected void blockCloseParen() { indent = indent.substring(1); // Rewind a tab buf.position(buf.position() - 1); line(")"); } protected void callOpen() { append("("); indent += "\t\t"; newLine(); } protected void callClose() { indent = indent.substring(2); line(");"); } protected void newLine() { append(LF); append(indent); } protected void line(String text) { append(text); newLine(); } protected void lineInc(String text) { append("\t"); append(text); newLine(); } protected void lineComment(String text) { line("// " + text); } private String getIdentifier(String name) { if (name == null) return null; if (SourceVersion.isKeyword(name)) name = name + "_"; char[] chars = name.toCharArray(); for (int i = 0; i < chars.length; i++) { if (i == 0) { if (!Character.isJavaIdentifierStart(chars[i])) chars[i] = '_'; } else if (!Character.isJavaIdentifierPart(chars[i])) chars[i] = '_'; } return String.valueOf(chars); } @FunctionalInterface interface ContentRenderer { void doRender(); } }