-
Notifications
You must be signed in to change notification settings - Fork 45
/
BehaviorGuardEvaluator.sarl
111 lines (98 loc) · 3.78 KB
/
BehaviorGuardEvaluator.sarl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2017 the original authors or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.sarl.eventdispatching
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import java.text.MessageFormat
import java.util.Collection
import com.google.common.base.Strings
/**
* Describes each class having one of its methods annotated with {@code PerceptGuardEvaluator} annotation corresponding to the
* method in charge of evaluating the guard associated to a given event and returns the list of behaviors runnable that must be
* executed according to the result of the guard evaluation.
* @author $Author: ngaud$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*
*/
class BehaviorGuardEvaluator {
/** The object with the {@code PerceptGuardEvaluator} method. */
val target : Object
/** {@code PerceptGuardEvaluator} method. */
val method : Method
/** Creates a {@code Subscriber} for {@code method} on {@code listener}.
*
* @param target - the listener
* @param method - the method to call to evaluate a guard
*/
new (target : Object, method : Method) {
assert target !== null
this.target = target
this.method = method
}
/**
* Evaluates the guard associated to the specified {@code event} and returns the list of behaviors methods that must be
* executed.
* @param event - the event triggering behaviors
* @param behaviorsMethodsToExecute - the list of behavior methods that will be completed according to the result of the guard
* evaluation, BE CARFEUL: we suppose that these behavior methods are parts of the SAME object where the
* {@code PerceptGuardEvaluator} method is declared
* @throws InvocationTargetException - exception during evaluation, can find the method to invoke
*/
def evaluateGuard(^event : Object, behaviorsMethodsToExecute : Collection<Runnable>) : void {
try {
this.method.accessible = true
this.method.invoke(this.target, ^event, behaviorsMethodsToExecute)
} catch (e : IllegalArgumentException) {
throw new Error(MessageFormat::format(Messages::BehaviorGuardEvaluator_0, ^event), e)
} catch (e : IllegalAccessException) {
throw new Error(MessageFormat::format(Messages::BehaviorGuardEvaluator_1, ^event), e)
} catch (e : InvocationTargetException) {
if (e.cause instanceof Error) {
throw e.cause as Error
}
throw e
}
}
/**
* Returns he object instance containing the {@code PerceptGuardEvaluator}.
* @return the object instance containing the {@code PerceptGuardEvaluator}
*/
def getTarget : Object {
this.target
}
override hashCode : int {
(31 + this.method.hashCode) * 31 + System::identityHashCode(this.target)
}
override equals(obj : Object) : boolean {
if (obj instanceof BehaviorGuardEvaluator) {
// Use == so that different equal instances will still receive events.
// We only guard against the case that the same object is registered
// multiple times
return this.target === obj.target && this.method == obj.method
}
return false
}
override toString : String {
if (this.method === null) Strings::emptyToNull(null) else this.method.name
}
}