/
AbstractProbeService.sarl
173 lines (149 loc) · 4.95 KB
/
AbstractProbeService.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2020 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.sre.services.probing
import io.sarl.sre.internal.SmartListenerCollection
import io.sarl.sre.naming.NameParser
import io.sarl.sre.naming.SarlName
import io.sarl.sre.services.AbstractSreService
import io.sarl.sre.services.namespace.FieldAccess
import io.sarl.sre.services.namespace.NamespaceService
import java.net.URI
import java.util.UUID
import javax.inject.Provider
import java.util.concurrent.ConcurrentLinkedDeque
import java.util.concurrent.ConcurrentHashMap
import java.util.Collection
/**
* This class is the standard implementation of a probe service.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @since 0.10
*/
abstract class AbstractProbeService extends AbstractSreService implements ProbeService, IProbeReleaseListener {
val namespace : NamespaceService
val nameParser : NameParser
val probes = new ConcurrentHashMap<URI, Probe<?>>
val listenerCollectionProvider : Provider<SmartListenerCollection<?>>
/** Constructor.
*
* @param namespaceService the service that is giving access to the namespaces.
* @param nameParser the object that is able to parse resource names.
* @param listenerCollectionProvider the provider of listener collections.
* @param lockProvider the provider of synchronization locks.
*/
protected new (namespaceService : NamespaceService, nameParser : NameParser,
listenerCollectionProvider : Provider<SmartListenerCollection<?>>) {
this.namespace = namespaceService
this.nameParser = nameParser
this.listenerCollectionProvider = listenerCollectionProvider
}
protected override onStop {
releaseAllProbes
}
override probe(valueName : String, valueType : Class<T>, probeName : String = null) : Probe<T> with T {
this.nameParser.decode(valueName).probe(valueType, probeName)
}
override probe(valueName : URI, valueType : Class<T>, probeName : String = null) : Probe<T> with T {
var nuri = this.nameParser.normalize(valueName)
if (nuri !== null) {
return this.nameParser.decode(nuri).probe(valueType, probeName)
}
return null
}
override probe(valueName : SarlName, valueType : Class<T>, probeName : String = null) : Probe<T> with T {
assert valueType !== null
if (valueName === null) {
return null
}
val uri = valueName.toURI
if (valueName === null) {
return null
}
var probe : Probe<T> = this.probes.get(uri) as Probe<T>
if (probe === null) {
var isFirst = false
probe = this.probes.get(uri) as Probe<T>
if (probe === null) {
val probedValue = this.namespace.findObject(valueName)
val name = if(probeName.isNullOrEmpty) UUID::randomUUID.toString else probeName
probe = probedValue.newProbe(valueType, uri, name)
if (probe !== null) {
isFirst = this.probes.empty
this.probes.put(uri, probe)
}
}
if (isFirst) {
onFirstProbe
}
}
return probe
}
/** Invoked when the first probe is added into the service.
*/
protected def onFirstProbe {
//
}
/** Invoked when the last probe is removed from the service.
*/
protected def onLastProbe {
//
}
/** Create an instance of the probe.
*
* @param <T> the expected type of the probed values.
* @param probedElement the element to which the probe must be associated, never {@code null}.
* @param valueType the expected type of the probed values, never {@code null}.
* @param probeUri the URI of the probe, never {@code null}.
* @param probeName the name of the probe, never {@code null}.
*/
protected def newProbe(probedElement : Object, valueType : Class<T>, probeUri : URI,
probeName : String) : Probe<T> with T {
if (probedElement instanceof FieldAccess) {
return new FieldProbe(this, probeName, probeUri, valueType, probedElement, this.listenerCollectionProvider)
}
return null
}
override getProbes : Collection<Probe<?>> {
return new ConcurrentLinkedDeque(this.probes.values)
}
override releaseAllProbes {
var removable = new ConcurrentLinkedDeque(this.probes.values)
for (it : removable) {
it.release
}
}
override sync {
this.probes.values.parallelStream.forEach [
it.sync
]
}
override onProbeReleasedProbe(probe : Probe<?>) {
var isLast = false
this.probes.remove(probe.uri)
isLast = this.probes.empty
if (isLast) {
onLastProbe
}
}
}