14
14
15
15
import java .util .ArrayList ;
16
16
import java .util .Collection ;
17
+ import java .util .LinkedList ;
17
18
import java .util .List ;
18
19
import java .util .Locale ;
19
20
import java .util .Map ;
20
- import java .util .Optional ;
21
21
import java .util .TreeMap ;
22
- import java .util .stream .Collectors ;
23
- import java .util .stream .Stream ;
24
22
25
23
import javax .script .ScriptEngine ;
26
24
42
40
import org .openhab .core .config .core .ConfigDescriptionParameterBuilder ;
43
41
import org .openhab .core .config .core .ParameterOption ;
44
42
import org .osgi .service .component .annotations .Component ;
43
+ import org .osgi .service .component .annotations .Deactivate ;
45
44
import org .osgi .service .component .annotations .Reference ;
46
45
import org .osgi .service .component .annotations .ReferenceCardinality ;
47
46
import org .osgi .service .component .annotations .ReferencePolicy ;
59
58
public class ScriptModuleTypeProvider implements ModuleTypeProvider {
60
59
61
60
private final Logger logger = LoggerFactory .getLogger (ScriptModuleTypeProvider .class );
61
+ private final List <ProviderChangeListener <ModuleType >> listeners = new LinkedList <>();
62
62
private final Map <String , String > parameterOptions = new TreeMap <>();
63
63
64
+ @ Deactivate
65
+ public void deactivate () {
66
+ listeners .clear ();
67
+ }
68
+
64
69
@ SuppressWarnings ("unchecked" )
65
70
@ Override
66
71
public @ Nullable ModuleType getModuleType (String UID , @ Nullable Locale locale ) {
67
- if (ScriptActionHandler .TYPE_ID .equals (UID )) {
72
+ if (parameterOptions .isEmpty ()) {
73
+ return null ;
74
+ } else if (ScriptActionHandler .TYPE_ID .equals (UID )) {
68
75
return getScriptActionType (locale );
69
76
} else if (ScriptConditionHandler .TYPE_ID .equals (UID )) {
70
77
return getScriptConditionType (locale );
@@ -73,26 +80,22 @@ public class ScriptModuleTypeProvider implements ModuleTypeProvider {
73
80
}
74
81
}
75
82
76
- private @ Nullable ModuleType getScriptActionType (@ Nullable Locale locale ) {
77
- if (parameterOptions .isEmpty ()) {
78
- return null ;
79
- } else {
80
- List <Output > outputs = new ArrayList <>();
81
- Output result = new Output ("result" , "java.lang.Object" , "result" , "the script result" , null , null , null );
82
- outputs .add (result );
83
- return new ActionType (ScriptActionHandler .TYPE_ID , getConfigDescriptions (locale ), "execute a given script" ,
84
- "Allows the execution of a user-defined script." , null , Visibility .VISIBLE , null , outputs );
85
- }
83
+ private ModuleType getScriptActionType (@ Nullable Locale locale ) {
84
+ List <Output > outputs = new ArrayList <>();
85
+ Output result = new Output ("result" , "java.lang.Object" , "result" , "the script result" , null , null , null );
86
+ outputs .add (result );
87
+ return new ActionType (ScriptActionHandler .TYPE_ID , getConfigDescriptions (locale ), "execute a given script" ,
88
+ "Allows the execution of a user-defined script." , null , Visibility .VISIBLE , null , outputs );
86
89
}
87
90
88
- private @ Nullable ModuleType getScriptConditionType (@ Nullable Locale locale ) {
89
- if ( parameterOptions . isEmpty ()) {
90
- return null ;
91
- } else {
92
- return new ConditionType ( ScriptConditionHandler . TYPE_ID , getConfigDescriptions ( locale ),
93
- "a given script evaluates to true" , "Allows the definition of a condition through a script." , null ,
94
- Visibility . VISIBLE , null );
95
- }
91
+ private ModuleType getScriptConditionType (@ Nullable Locale locale ) {
92
+ return new ConditionType ( ScriptConditionHandler . TYPE_ID , getConfigDescriptions ( locale ),
93
+ "a given script evaluates to true" , "Allows the definition of a condition through a script." , null ,
94
+ Visibility . VISIBLE , null );
95
+ }
96
+
97
+ private List < ModuleType > getModuleTypesUnconditionally ( @ Nullable Locale locale ) {
98
+ return List . of ( getScriptActionType ( locale ), getScriptConditionType ( locale ));
96
99
}
97
100
98
101
/**
@@ -118,10 +121,7 @@ private List<ConfigDescriptionParameter> getConfigDescriptions(@Nullable Locale
118
121
119
122
@ Override
120
123
public Collection <ModuleType > getModuleTypes (@ Nullable Locale locale ) {
121
- return Stream
122
- .of (Optional .ofNullable (getScriptActionType (locale )),
123
- Optional .ofNullable (getScriptConditionType (locale )))
124
- .filter (Optional ::isPresent ).map (Optional ::get ).collect (Collectors .toUnmodifiableList ());
124
+ return parameterOptions .isEmpty () ? List .of () : getModuleTypesUnconditionally (locale );
125
125
}
126
126
127
127
@ Override
@@ -131,12 +131,40 @@ public Collection<ModuleType> getAll() {
131
131
132
132
@ Override
133
133
public void addProviderChangeListener (ProviderChangeListener <ModuleType > listener ) {
134
- // does nothing because this provider does not change
134
+ synchronized (listeners ) {
135
+ listeners .add (listener );
136
+ }
135
137
}
136
138
137
139
@ Override
138
140
public void removeProviderChangeListener (ProviderChangeListener <ModuleType > listener ) {
139
- // does nothing because this provider does not change
141
+ synchronized (listeners ) {
142
+ listeners .remove (listener );
143
+ }
144
+ }
145
+
146
+ private void notifyModuleTypesAdded () {
147
+ List <ProviderChangeListener <ModuleType >> snapshot = null ;
148
+ synchronized (listeners ) {
149
+ snapshot = new LinkedList <>(listeners );
150
+ }
151
+ for (ModuleType moduleType : getModuleTypesUnconditionally (null )) {
152
+ for (ProviderChangeListener <ModuleType > listener : snapshot ) {
153
+ listener .added (this , moduleType );
154
+ }
155
+ }
156
+ }
157
+
158
+ private void notifyModuleTypesRemoved () {
159
+ List <ProviderChangeListener <ModuleType >> snapshot = null ;
160
+ synchronized (listeners ) {
161
+ snapshot = new LinkedList <>(listeners );
162
+ }
163
+ for (ModuleType moduleType : getModuleTypesUnconditionally (null )) {
164
+ for (ProviderChangeListener <ModuleType > listener : snapshot ) {
165
+ listener .removed (this , moduleType );
166
+ }
167
+ }
140
168
}
141
169
142
170
/**
@@ -149,8 +177,12 @@ public void setScriptEngineFactory(ScriptEngineFactory engineFactory) {
149
177
if (!scriptTypes .isEmpty ()) {
150
178
ScriptEngine scriptEngine = engineFactory .createScriptEngine (scriptTypes .get (0 ));
151
179
if (scriptEngine != null ) {
180
+ boolean notifyListeners = parameterOptions .isEmpty ();
152
181
parameterOptions .put (getPreferredMimeType (engineFactory ), getLanguageName (scriptEngine .getFactory ()));
153
182
logger .trace ("ParameterOptions: {}" , parameterOptions );
183
+ if (notifyListeners ) {
184
+ notifyModuleTypesAdded ();
185
+ }
154
186
} else {
155
187
logger .trace ("setScriptEngineFactory: engine was null" );
156
188
}
@@ -166,6 +198,9 @@ public void unsetScriptEngineFactory(ScriptEngineFactory engineFactory) {
166
198
if (scriptEngine != null ) {
167
199
parameterOptions .remove (getPreferredMimeType (engineFactory ));
168
200
logger .trace ("ParameterOptions: {}" , parameterOptions );
201
+ if (parameterOptions .isEmpty ()) {
202
+ notifyModuleTypesRemoved ();
203
+ }
169
204
} else {
170
205
logger .trace ("unsetScriptEngineFactory: engine was null" );
171
206
}
0 commit comments