1 | /* | |
2 | * Copyright 2006 - 2013 | |
3 | * Stefan Balev <stefan.balev@graphstream-project.org> | |
4 | * Julien Baudry <julien.baudry@graphstream-project.org> | |
5 | * Antoine Dutot <antoine.dutot@graphstream-project.org> | |
6 | * Yoann Pign�� <yoann.pigne@graphstream-project.org> | |
7 | * Guilhelm Savin <guilhelm.savin@graphstream-project.org> | |
8 | * | |
9 | * This file is part of GraphStream <http://graphstream-project.org>. | |
10 | * | |
11 | * GraphStream is a library whose purpose is to handle static or dynamic | |
12 | * graph, create them from scratch, file or any source and display them. | |
13 | * | |
14 | * This program is free software distributed under the terms of two licenses, the | |
15 | * CeCILL-C license that fits European law, and the GNU Lesser General Public | |
16 | * License. You can use, modify and/ or redistribute the software under the terms | |
17 | * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following | |
18 | * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by | |
19 | * the Free Software Foundation, either version 3 of the License, or (at your | |
20 | * option) any later version. | |
21 | * | |
22 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | |
23 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | |
24 | * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU Lesser General Public License | |
27 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
28 | * | |
29 | * The fact that you are presently reading this means that you have had | |
30 | * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms. | |
31 | */ | |
32 | package org.graphstream.stream; | |
33 | ||
34 | import org.graphstream.stream.SourceBase.ElementType; | |
35 | ||
36 | import java.lang.annotation.Documented; | |
37 | import java.lang.annotation.Retention; | |
38 | import java.lang.annotation.RetentionPolicy; | |
39 | import java.lang.annotation.Target; | |
40 | import java.lang.reflect.InvocationTargetException; | |
41 | import java.lang.reflect.Method; | |
42 | import java.util.EnumMap; | |
43 | import java.util.HashMap; | |
44 | ||
45 | /** | |
46 | * A sink easily allowing a bind between attribute modifications and method | |
47 | * calls. | |
48 | * | |
49 | * <pre> | |
50 | * public class MyObject extends AnnotatedSink { | |
51 | * String a1; | |
52 | * double a2; | |
53 | * | |
54 | * @Bind("myobject.set.a1") | |
55 | * public void setA1(String eventId, Object value) { | |
56 | * a1 = (String) value; | |
57 | * } | |
58 | * | |
59 | * @Bind("myobject.set.a2") | |
60 | * public void setA2(String eventId, Object value) { | |
61 | * a2 = (Double) value; | |
62 | * } | |
63 | * | |
64 | * public static void main(String ... args) { | |
65 | * Graph g = ...; | |
66 | * MyObject obj = new MyObject(); | |
67 | * | |
68 | * g.addSink(obj); | |
69 | * | |
70 | * g.addAttribute("myobject.set.a1", "MyObject A1"); | |
71 | * g.addAttribute("myobject.set.a2", 100.0); | |
72 | * } | |
73 | * } | |
74 | * </pre> | |
75 | */ | |
76 | public abstract class AnnotatedSink implements Sink { | |
77 | /** | |
78 | * Annotation used to bind an event to a method. This bind is composed of a | |
79 | * name (the attribute key) and an element type. For example, the annotation | |
80 | * | |
81 | * <pre> | |
82 | * @Bind(value = "test", type = ElementType.NODE) | |
83 | * </pre> | |
84 | * | |
85 | * will be triggered the annotated method when receiving | |
86 | * 'nodeAttributeXXX()' methods. | |
87 | */ | |
88 | @Documented | |
89 | @Retention(RetentionPolicy.RUNTIME) | |
90 | @Target(java.lang.annotation.ElementType.METHOD) | |
91 | public static @interface Bind { | |
92 | /** | |
93 | * Name of the attribute key that triggered the annotated method. | |
94 | * | |
95 | * @return an attribute key | |
96 | */ | |
97 | String value(); | |
98 | ||
99 | /** | |
100 | * Type of element that triggered the annotated method. Default is | |
101 | * GRAPH. | |
102 | * | |
103 | * @return type of element in GRAPH, NODE or EDGE | |
104 | */ | |
105 | ElementType type() default ElementType.GRAPH; | |
106 | } | |
107 | ||
108 | private final EnumMap<ElementType, MethodMap> methods; | |
109 | ||
110 | protected AnnotatedSink() { | |
111 | methods = new EnumMap<ElementType, MethodMap>(ElementType.class); | |
112 | methods.put(ElementType.GRAPH, new MethodMap()); | |
113 | methods.put(ElementType.EDGE, new MethodMap()); | |
114 | methods.put(ElementType.NODE, new MethodMap()); | |
115 | ||
116 | Method[] ms = getClass().getMethods(); | |
117 | ||
118 |
1
1. |
if (ms != null) { |
119 |
3
1. 2. 3. |
for (int i = 0; i < ms.length; i++) { |
120 | Method m = ms[i]; | |
121 | Bind b = m.getAnnotation(Bind.class); | |
122 | | |
123 |
1
1. |
if (b != null) |
124 | methods.get(b.type()).put(b.value(), m); | |
125 | } | |
126 | } | |
127 | } | |
128 | ||
129 | private void invoke(Method m, Object... args) { | |
130 | try { | |
131 | m.invoke(this, args); | |
132 | } catch (IllegalArgumentException e) { | |
133 |
1
1. invoke : removed call to java/lang/IllegalArgumentException::printStackTrace → NO_COVERAGE |
e.printStackTrace(); |
134 | } catch (IllegalAccessException e) { | |
135 |
1
1. invoke : removed call to java/lang/IllegalAccessException::printStackTrace → NO_COVERAGE |
e.printStackTrace(); |
136 | } catch (InvocationTargetException e) { | |
137 |
1
1. invoke : removed call to java/lang/reflect/InvocationTargetException::printStackTrace → NO_COVERAGE |
e.printStackTrace(); |
138 | } | |
139 | } | |
140 | ||
141 | /* | |
142 | * (non-Javadoc) | |
143 | * @see org.graphstream.stream.AttributeSink#edgeAttributeAdded(java.lang.String, long, java.lang.String, java.lang.String, java.lang.Object) | |
144 | */ | |
145 | public void edgeAttributeAdded(String sourceId, long timeId, String edgeId, | |
146 | String attribute, Object value) { | |
147 | Method m = methods.get(ElementType.EDGE).get(attribute); | |
148 | ||
149 |
1
1. edgeAttributeAdded : negated conditional → NO_COVERAGE |
if (m != null) |
150 |
1
1. edgeAttributeAdded : removed call to org/graphstream/stream/AnnotatedSink::invoke → NO_COVERAGE |
invoke(m, edgeId, attribute, value); |
151 | } | |
152 | ||
153 | /* | |
154 | * (non-Javadoc) | |
155 | * @see org.graphstream.stream.AttributeSink#edgeAttributeChanged(java.lang.String, long, java.lang.String, java.lang.String, java.lang.Object, java.lang.Object) | |
156 | */ | |
157 | public void edgeAttributeChanged(String sourceId, long timeId, | |
158 | String edgeId, String attribute, Object oldValue, Object newValue) { | |
159 | Method m = methods.get(ElementType.EDGE).get(attribute); | |
160 | ||
161 |
1
1. edgeAttributeChanged : negated conditional → NO_COVERAGE |
if (m != null) |
162 |
1
1. edgeAttributeChanged : removed call to org/graphstream/stream/AnnotatedSink::invoke → NO_COVERAGE |
invoke(m, edgeId, attribute, newValue); |
163 | } | |
164 | ||
165 | /* | |
166 | * (non-Javadoc) | |
167 | * @see org.graphstream.stream.AttributeSink#edgeAttributeRemoved(java.lang.String, long, java.lang.String, java.lang.String) | |
168 | */ | |
169 | public void edgeAttributeRemoved(String sourceId, long timeId, | |
170 | String edgeId, String attribute) { | |
171 | Method m = methods.get(ElementType.EDGE).get(attribute); | |
172 | ||
173 |
1
1. edgeAttributeRemoved : negated conditional → NO_COVERAGE |
if (m != null) |
174 |
1
1. edgeAttributeRemoved : removed call to org/graphstream/stream/AnnotatedSink::invoke → NO_COVERAGE |
invoke(m, edgeId, attribute, null); |
175 | } | |
176 | ||
177 | /* | |
178 | * (non-Javadoc) | |
179 | * @see org.graphstream.stream.AttributeSink#graphAttributeAdded(java.lang.String, long, java.lang.String, java.lang.Object) | |
180 | */ | |
181 | public void graphAttributeAdded(String sourceId, long timeId, | |
182 | String attribute, Object value) { | |
183 | Method m = methods.get(ElementType.GRAPH).get(attribute); | |
184 | ||
185 |
1
1. graphAttributeAdded : negated conditional → NO_COVERAGE |
if (m != null) |
186 |
1
1. graphAttributeAdded : removed call to org/graphstream/stream/AnnotatedSink::invoke → NO_COVERAGE |
invoke(m, attribute, value); |
187 | } | |
188 | ||
189 | /* | |
190 | * (non-Javadoc) | |
191 | * @see org.graphstream.stream.AttributeSink#graphAttributeChanged(java.lang.String, long, java.lang.String, java.lang.Object, java.lang.Object) | |
192 | */ | |
193 | public void graphAttributeChanged(String sourceId, long timeId, | |
194 | String attribute, Object oldValue, Object newValue) { | |
195 | Method m = methods.get(ElementType.GRAPH).get(attribute); | |
196 | ||
197 |
1
1. graphAttributeChanged : negated conditional → NO_COVERAGE |
if (m != null) |
198 |
1
1. graphAttributeChanged : removed call to org/graphstream/stream/AnnotatedSink::invoke → NO_COVERAGE |
invoke(m, attribute, newValue); |
199 | } | |
200 | ||
201 | /* | |
202 | * (non-Javadoc) | |
203 | * @see org.graphstream.stream.AttributeSink#graphAttributeRemoved(java.lang.String, long, java.lang.String) | |
204 | */ | |
205 | public void graphAttributeRemoved(String sourceId, long timeId, | |
206 | String attribute) { | |
207 | Method m = methods.get(ElementType.GRAPH).get(attribute); | |
208 | ||
209 |
1
1. graphAttributeRemoved : negated conditional → NO_COVERAGE |
if (m != null) |
210 |
1
1. graphAttributeRemoved : removed call to org/graphstream/stream/AnnotatedSink::invoke → NO_COVERAGE |
invoke(m, attribute, null); |
211 | } | |
212 | ||
213 | /* | |
214 | * (non-Javadoc) | |
215 | * @see org.graphstream.stream.AttributeSink#nodeAttributeAdded(java.lang.String, long, java.lang.String, java.lang.String, java.lang.Object) | |
216 | */ | |
217 | public void nodeAttributeAdded(String sourceId, long timeId, String nodeId, | |
218 | String attribute, Object value) { | |
219 | Method m = methods.get(ElementType.NODE).get(attribute); | |
220 | ||
221 |
1
1. nodeAttributeAdded : negated conditional → NO_COVERAGE |
if (m != null) |
222 |
1
1. nodeAttributeAdded : removed call to org/graphstream/stream/AnnotatedSink::invoke → NO_COVERAGE |
invoke(m, nodeId, attribute, value); |
223 | } | |
224 | ||
225 | /* | |
226 | * (non-Javadoc) | |
227 | * @see org.graphstream.stream.AttributeSink#nodeAttributeChanged(java.lang.String, long, java.lang.String, java.lang.String, java.lang.Object, java.lang.Object) | |
228 | */ | |
229 | public void nodeAttributeChanged(String sourceId, long timeId, | |
230 | String nodeId, String attribute, Object oldValue, Object newValue) { | |
231 | Method m = methods.get(ElementType.NODE).get(attribute); | |
232 | ||
233 |
1
1. nodeAttributeChanged : negated conditional → NO_COVERAGE |
if (m != null) |
234 |
1
1. nodeAttributeChanged : removed call to org/graphstream/stream/AnnotatedSink::invoke → NO_COVERAGE |
invoke(m, nodeId, attribute, newValue); |
235 | } | |
236 | ||
237 | /* | |
238 | * (non-Javadoc) | |
239 | * @see org.graphstream.stream.AttributeSink#nodeAttributeRemoved(java.lang.String, long, java.lang.String, java.lang.String) | |
240 | */ | |
241 | public void nodeAttributeRemoved(String sourceId, long timeId, | |
242 | String nodeId, String attribute) { | |
243 | Method m = methods.get(ElementType.NODE).get(attribute); | |
244 | ||
245 |
1
1. nodeAttributeRemoved : negated conditional → NO_COVERAGE |
if (m != null) |
246 |
1
1. nodeAttributeRemoved : removed call to org/graphstream/stream/AnnotatedSink::invoke → NO_COVERAGE |
invoke(m, nodeId, attribute, null); |
247 | } | |
248 | ||
249 | /* | |
250 | * (non-Javadoc) | |
251 | * @see org.graphstream.stream.ElementSink#edgeAdded(java.lang.String, long, java.lang.String, java.lang.String, java.lang.String, boolean) | |
252 | */ | |
253 | public void edgeAdded(String sourceId, long timeId, String edgeId, | |
254 | String fromNodeId, String toNodeId, boolean directed) { | |
255 | } | |
256 | ||
257 | /* | |
258 | * (non-Javadoc) | |
259 | * @see org.graphstream.stream.ElementSink#edgeRemoved(java.lang.String, long, java.lang.String) | |
260 | */ | |
261 | public void edgeRemoved(String sourceId, long timeId, String edgeId) { | |
262 | } | |
263 | ||
264 | /* | |
265 | * (non-Javadoc) | |
266 | * @see org.graphstream.stream.ElementSink#graphCleared(java.lang.String, long) | |
267 | */ | |
268 | public void graphCleared(String sourceId, long timeId) { | |
269 | } | |
270 | ||
271 | /* | |
272 | * (non-Javadoc) | |
273 | * @see org.graphstream.stream.ElementSink#nodeAdded(java.lang.String, long, java.lang.String) | |
274 | */ | |
275 | public void nodeAdded(String sourceId, long timeId, String nodeId) { | |
276 | } | |
277 | ||
278 | /* | |
279 | * (non-Javadoc) | |
280 | * @see org.graphstream.stream.ElementSink#nodeRemoved(java.lang.String, long, java.lang.String) | |
281 | */ | |
282 | public void nodeRemoved(String sourceId, long timeId, String nodeId) { | |
283 | } | |
284 | ||
285 | /* | |
286 | * (non-Javadoc) | |
287 | * @see org.graphstream.stream.ElementSink#stepBegins(java.lang.String, long, double) | |
288 | */ | |
289 | public void stepBegins(String sourceId, long timeId, double step) { | |
290 | } | |
291 | ||
292 | private static class MethodMap extends HashMap<String, Method> { | |
293 | private static final long serialVersionUID = 1664854698109523697L; | |
294 | } | |
295 | } | |
Mutations | ||
118 |
1.1 |
|
119 |
1.1 2.2 3.3 |
|
123 |
1.1 |
|
133 |
1.1 |
|
135 |
1.1 |
|
137 |
1.1 |
|
149 |
1.1 |
|
150 |
1.1 |
|
161 |
1.1 |
|
162 |
1.1 |
|
173 |
1.1 |
|
174 |
1.1 |
|
185 |
1.1 |
|
186 |
1.1 |
|
197 |
1.1 |
|
198 |
1.1 |
|
209 |
1.1 |
|
210 |
1.1 |
|
221 |
1.1 |
|
222 |
1.1 |
|
233 |
1.1 |
|
234 |
1.1 |
|
245 |
1.1 |
|
246 |
1.1 |