aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/gnunet/construct/MessageIdAnnotationProcessor.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/gnunet/construct/MessageIdAnnotationProcessor.java')
-rw-r--r--src/main/java/org/gnunet/construct/MessageIdAnnotationProcessor.java137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/main/java/org/gnunet/construct/MessageIdAnnotationProcessor.java b/src/main/java/org/gnunet/construct/MessageIdAnnotationProcessor.java
new file mode 100644
index 0000000..ab80be3
--- /dev/null
+++ b/src/main/java/org/gnunet/construct/MessageIdAnnotationProcessor.java
@@ -0,0 +1,137 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011, 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.construct;
22
23import com.google.common.collect.HashBasedTable;
24import com.google.common.collect.Table;
25
26import javax.annotation.processing.*;
27import javax.lang.model.SourceVersion;
28import javax.lang.model.element.Element;
29import javax.lang.model.element.TypeElement;
30import javax.lang.model.type.TypeMirror;
31import javax.lang.model.util.Elements;
32import javax.lang.model.util.Types;
33import javax.tools.Diagnostic;
34import javax.tools.FileObject;
35import javax.tools.StandardLocation;
36import java.io.IOException;
37import java.io.Writer;
38import java.lang.Integer;
39import java.text.DateFormat;
40import java.text.SimpleDateFormat;
41import java.util.*;
42
43
44/**
45 * Creates a resource file 'MsgMap.txt' in the package 'org.gnunet.construct' of the source tree.
46 */
47@SupportedAnnotationTypes("org.gnunet.construct.UnionCase")
48@SupportedSourceVersion(SourceVersion.RELEASE_6)
49public class MessageIdAnnotationProcessor extends AbstractProcessor {
50 private final Table<String, Integer, String> idToMember = HashBasedTable.create();
51
52 @Override
53 public boolean process(Set<? extends TypeElement> typeElements, RoundEnvironment roundEnvironment) {
54 if (roundEnvironment.errorRaised()) {
55 return false;
56 }
57
58 Types types = processingEnv.getTypeUtils();
59 Elements elements = processingEnv.getElementUtils();
60
61 if (roundEnvironment.processingOver()) {
62 Filer filer = processingEnv.getFiler();
63 FileObject outfile;
64 try {
65 outfile = filer.createResource(StandardLocation.SOURCE_OUTPUT, "org.gnunet.construct", "MsgMap.txt");
66 } catch (IOException e) {
67 processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Could not create MsgMap.txt");
68 return false;
69 }
70
71 try {
72 Writer w = outfile.openWriter();
73 for (Table.Cell<String, Integer, String> cell : idToMember.cellSet()) {
74 w.write(cell.getRowKey() + '|' + cell.getColumnKey() + '=' + cell.getValue() + '\n');
75 }
76
77 DateFormat fmt = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
78
79 w.write("# generated " + fmt.format(new Date()) + '\n');
80 w.close();
81 } catch (IOException e) {
82 processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Could not write MsgMap.txt");
83 }
84
85 processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "message map written to " + outfile.toUri());
86
87 } else {
88 for (Element e : roundEnvironment.getElementsAnnotatedWith(UnionCase.class)) {
89 UnionCase ann = e.getAnnotation(UnionCase.class);
90 // get the uppermost parent class that implements MessageUnion. This is the union type.
91 // processingEnv.getElementUtils().
92 //processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "element :" + e.toString());
93 List<? extends TypeMirror> parents = processingEnv.getTypeUtils().directSupertypes(e.asType());
94 TypeMirror msg = elements.getTypeElement("org.gnunet.construct.MessageUnion").asType();
95 TypeMirror unionInterface = null;
96 for (TypeMirror p : parents) {
97 if (types.isSubtype(p, msg)) {
98 unionInterface = p;
99 break;
100 }
101 }
102 if (unionInterface == null) {
103 processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, String.format(
104 "class %s annotated with @UnionCase does not implement an interface inheriting MessageUnion", e.getSimpleName()));
105 return false;
106 }
107 String unionName = getClassName(types.asElement(unionInterface));
108 idToMember.put(unionName, ann.value(), getClassName(e));
109 }
110 }
111
112 return false;
113 }
114
115 /**
116 * Get the fully qualified class name, where packages are seperated with '.', and
117 * inner classes are separated with '$'
118 *
119 * @param e the Element representing a class
120 * @return the fully qualified class name
121 */
122 private String getClassName(Element e) {
123
124 assert e.getKind().isClass();
125
126 String name = e.getSimpleName().toString();
127 String pkg = processingEnv.getElementUtils().getPackageOf(e).getQualifiedName().toString() + '.';
128
129 String outer = "";
130
131 while (((e = e.getEnclosingElement()) != null) && e.getKind().isClass()) {
132 outer = String.format("%s$%s", e.getSimpleName(), outer);
133 }
134
135 return pkg + outer + name;
136 }
137}