diff options
Diffstat (limited to 'src/main/java/org/gnunet/construct/MessageIdAnnotationProcessor.java')
-rw-r--r-- | src/main/java/org/gnunet/construct/MessageIdAnnotationProcessor.java | 137 |
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 | |||
21 | package org.gnunet.construct; | ||
22 | |||
23 | import com.google.common.collect.HashBasedTable; | ||
24 | import com.google.common.collect.Table; | ||
25 | |||
26 | import javax.annotation.processing.*; | ||
27 | import javax.lang.model.SourceVersion; | ||
28 | import javax.lang.model.element.Element; | ||
29 | import javax.lang.model.element.TypeElement; | ||
30 | import javax.lang.model.type.TypeMirror; | ||
31 | import javax.lang.model.util.Elements; | ||
32 | import javax.lang.model.util.Types; | ||
33 | import javax.tools.Diagnostic; | ||
34 | import javax.tools.FileObject; | ||
35 | import javax.tools.StandardLocation; | ||
36 | import java.io.IOException; | ||
37 | import java.io.Writer; | ||
38 | import java.lang.Integer; | ||
39 | import java.text.DateFormat; | ||
40 | import java.text.SimpleDateFormat; | ||
41 | import 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) | ||
49 | public 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 | } | ||