blob: b37d8c5eed059dfc6122ddac49747ef83c95fbbd [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.intent;
Brian O'Connorf3d06162014-10-02 15:54:12 -070017
Yi Tsengc927a062017-05-02 15:02:37 -070018import com.google.common.collect.ImmutableMap;
19
Brian O'Connorf3d06162014-10-02 15:54:12 -070020import java.util.ArrayList;
21import java.util.Collections;
22import java.util.HashMap;
23import java.util.HashSet;
24import java.util.List;
25import java.util.Map;
26import java.util.Set;
27import java.util.concurrent.ExecutorService;
28import java.util.concurrent.Executors;
29
30/**
Brian O'Connor66630c82014-10-02 21:08:19 -070031 * Fake implementation of the intent service to assist in developing tests of
32 * the interface contract.
Brian O'Connorf3d06162014-10-02 15:54:12 -070033 */
34public class FakeIntentManager implements TestableIntentService {
35
Ray Milkey4f5d93e2015-02-10 17:04:10 -080036 private final Map<Key, Intent> intents = new HashMap<>();
37 private final Map<Key, IntentState> intentStates = new HashMap<>();
38 private final Map<Key, List<Intent>> installables = new HashMap<>();
Brian O'Connor66630c82014-10-02 21:08:19 -070039 private final Set<IntentListener> listeners = new HashSet<>();
Brian O'Connorf3d06162014-10-02 15:54:12 -070040
41 private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>();
Yi Tsengc927a062017-05-02 15:02:37 -070042 private final Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> installers = new HashMap<>();
Brian O'Connorf3d06162014-10-02 15:54:12 -070043
44 private final ExecutorService executor = Executors.newSingleThreadExecutor();
45 private final List<IntentException> exceptions = new ArrayList<>();
46
47 @Override
48 public List<IntentException> getExceptions() {
49 return exceptions;
50 }
51
52 // Provides an out-of-thread simulation of intent submit life-cycle
53 private void executeSubmit(final Intent intent) {
54 registerSubclassCompilerIfNeeded(intent);
Sho SHIMIZU74626412015-09-11 11:46:27 -070055 executor.execute(() -> {
56 try {
57 executeCompilingPhase(intent);
58 } catch (IntentException e) {
59 exceptions.add(e);
Brian O'Connorf3d06162014-10-02 15:54:12 -070060 }
61 });
62 }
63
64 // Provides an out-of-thread simulation of intent withdraw life-cycle
65 private void executeWithdraw(final Intent intent) {
Sho SHIMIZU74626412015-09-11 11:46:27 -070066 executor.execute(() -> {
67 try {
68 List<Intent> installable = getInstallable(intent.key());
69 executeWithdrawingPhase(intent, installable);
70 } catch (IntentException e) {
71 exceptions.add(e);
Brian O'Connorf3d06162014-10-02 15:54:12 -070072 }
73 });
74 }
75
76 private <T extends Intent> IntentCompiler<T> getCompiler(T intent) {
77 @SuppressWarnings("unchecked")
78 IntentCompiler<T> compiler = (IntentCompiler<T>) compilers.get(intent.getClass());
79 if (compiler == null) {
80 throw new IntentException("no compiler for class " + intent.getClass());
81 }
82 return compiler;
83 }
84
tom85258ee2014-10-07 00:10:02 -070085 private <T extends Intent> void executeCompilingPhase(T intent) {
86 setState(intent, IntentState.COMPILING);
Brian O'Connorf3d06162014-10-02 15:54:12 -070087 try {
88 // For the fake, we compile using a single level pass
Thomas Vachuskac96058a2014-10-20 23:00:16 -070089 List<Intent> installable = new ArrayList<>();
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -080090 for (Intent compiled : getCompiler(intent).compile(intent, null)) {
Sho SHIMIZUd82a4e62015-09-09 14:53:46 -070091 installable.add(compiled);
Brian O'Connorf3d06162014-10-02 15:54:12 -070092 }
tom85258ee2014-10-07 00:10:02 -070093 executeInstallingPhase(intent, installable);
94
Brian O'Connorf3d06162014-10-02 15:54:12 -070095 } catch (IntentException e) {
96 setState(intent, IntentState.FAILED);
tom85258ee2014-10-07 00:10:02 -070097 dispatch(new IntentEvent(IntentEvent.Type.FAILED, intent));
Brian O'Connorf3d06162014-10-02 15:54:12 -070098 }
99 }
100
tom85258ee2014-10-07 00:10:02 -0700101 private void executeInstallingPhase(Intent intent,
Thomas Vachuskac96058a2014-10-20 23:00:16 -0700102 List<Intent> installable) {
tom85258ee2014-10-07 00:10:02 -0700103 setState(intent, IntentState.INSTALLING);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700104 try {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700105 setState(intent, IntentState.INSTALLED);
Ray Milkey4f5d93e2015-02-10 17:04:10 -0800106 putInstallable(intent.key(), installable);
tom85258ee2014-10-07 00:10:02 -0700107 dispatch(new IntentEvent(IntentEvent.Type.INSTALLED, intent));
108
Brian O'Connorf3d06162014-10-02 15:54:12 -0700109 } catch (IntentException e) {
110 setState(intent, IntentState.FAILED);
tom85258ee2014-10-07 00:10:02 -0700111 dispatch(new IntentEvent(IntentEvent.Type.FAILED, intent));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700112 }
113 }
114
tom85258ee2014-10-07 00:10:02 -0700115 private void executeWithdrawingPhase(Intent intent,
Thomas Vachuskac96058a2014-10-20 23:00:16 -0700116 List<Intent> installable) {
tom85258ee2014-10-07 00:10:02 -0700117 setState(intent, IntentState.WITHDRAWING);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700118 try {
Ray Milkey4f5d93e2015-02-10 17:04:10 -0800119 removeInstallable(intent.key());
Brian O'Connorf3d06162014-10-02 15:54:12 -0700120 setState(intent, IntentState.WITHDRAWN);
tom85258ee2014-10-07 00:10:02 -0700121 dispatch(new IntentEvent(IntentEvent.Type.WITHDRAWN, intent));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700122 } catch (IntentException e) {
tom53945d52014-10-07 11:01:36 -0700123 // FIXME: Rework this to always go from WITHDRAWING to WITHDRAWN!
Brian O'Connorf3d06162014-10-02 15:54:12 -0700124 setState(intent, IntentState.FAILED);
tom85258ee2014-10-07 00:10:02 -0700125 dispatch(new IntentEvent(IntentEvent.Type.FAILED, intent));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700126 }
127 }
128
Brian O'Connorf3d06162014-10-02 15:54:12 -0700129 // Sets the internal state for the given intent and dispatches an event
130 private void setState(Intent intent, IntentState state) {
Ray Milkey4f5d93e2015-02-10 17:04:10 -0800131 intentStates.put(intent.key(), state);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700132 }
133
Ray Milkey4f5d93e2015-02-10 17:04:10 -0800134 private void putInstallable(Key key, List<Intent> installable) {
135 installables.put(key, installable);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700136 }
137
Ray Milkey4f5d93e2015-02-10 17:04:10 -0800138 private void removeInstallable(Key key) {
139 installables.remove(key);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700140 }
141
Ray Milkey4f5d93e2015-02-10 17:04:10 -0800142 private List<Intent> getInstallable(Key key) {
143 List<Intent> installable = installables.get(key);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700144 if (installable != null) {
145 return installable;
146 } else {
147 return Collections.emptyList();
148 }
149 }
150
151 @Override
152 public void submit(Intent intent) {
Ray Milkey4f5d93e2015-02-10 17:04:10 -0800153 intents.put(intent.key(), intent);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800154 setState(intent, IntentState.INSTALL_REQ);
155 dispatch(new IntentEvent(IntentEvent.Type.INSTALL_REQ, intent));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700156 executeSubmit(intent);
157 }
158
159 @Override
160 public void withdraw(Intent intent) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700161 executeWithdraw(intent);
162 }
163
164 @Override
Ray Milkey8c6d00e2015-03-13 14:14:34 -0700165 public void purge(Intent intent) {
166 IntentState currentState = intentStates.get(intent.key());
167 if (currentState == IntentState.WITHDRAWN
168 || currentState == IntentState.FAILED) {
169 intents.remove(intent.key());
170 installables.remove(intent.key());
171 intentStates.remove(intent.key());
Brian Stanke11f6d532016-07-05 16:17:59 -0400172 dispatch(new IntentEvent(IntentEvent.Type.PURGED, intent));
Ray Milkey8c6d00e2015-03-13 14:14:34 -0700173 }
174 }
175
176 @Override
Brian O'Connorf3d06162014-10-02 15:54:12 -0700177 public Set<Intent> getIntents() {
178 return Collections.unmodifiableSet(new HashSet<>(intents.values()));
179 }
180
181 @Override
Brian O'Connor38224302016-08-02 22:03:01 -0700182 public void addPending(IntentData intentData) {
183 throw new UnsupportedOperationException();
184 }
185
186 @Override
Thomas Vachuskac46af202015-06-03 16:43:27 -0700187 public Iterable<IntentData> getIntentData() {
188 throw new UnsupportedOperationException();
189 }
190
191 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700192 public long getIntentCount() {
193 return intents.size();
194 }
195
196 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800197 public Intent getIntent(Key intentKey) {
198 return intents.get(intentKey);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700199 }
200
201 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800202 public IntentState getIntentState(Key intentKey) {
203 return intentStates.get(intentKey);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700204 }
205
206 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800207 public List<Intent> getInstallableIntents(Key intentKey) {
208 return installables.get(intentKey);
Thomas Vachuska10d4abc2014-10-21 12:47:26 -0700209 }
210
211 @Override
Jonathan Hart13d3dd92015-02-25 16:09:42 -0800212 public boolean isLocal(Key intentKey) {
213 return true;
214 }
215
216 @Override
217 public Iterable<Intent> getPending() {
218 return Collections.emptyList();
219 }
220
221 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700222 public void addListener(IntentListener listener) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700223 listeners.add(listener);
224 }
225
226 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700227 public void removeListener(IntentListener listener) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700228 listeners.remove(listener);
229 }
230
231 private void dispatch(IntentEvent event) {
Brian O'Connor66630c82014-10-02 21:08:19 -0700232 for (IntentListener listener : listeners) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700233 listener.event(event);
234 }
235 }
236
237 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700238 public <T extends Intent> void registerCompiler(Class<T> cls,
239 IntentCompiler<T> compiler) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700240 compilers.put(cls, compiler);
241 }
242
243 @Override
244 public <T extends Intent> void unregisterCompiler(Class<T> cls) {
245 compilers.remove(cls);
246 }
247
248 @Override
249 public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
250 return Collections.unmodifiableMap(compilers);
251 }
252
Yi Tsengc927a062017-05-02 15:02:37 -0700253 @Override
254 public <T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
255 installers.put(cls, installer);
256 }
257
258 @Override
259 public <T extends Intent> void unregisterInstaller(Class<T> cls) {
260 installers.remove(cls);
261 }
262
263 @Override
264 public Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers() {
265 return ImmutableMap.copyOf(installers);
266 }
267
268 @Override
269 public <T extends Intent> IntentInstaller<T> getInstaller(Class<T> cls) {
270 return (IntentInstaller<T>) installers.get(cls);
271 }
272
Brian O'Connorf3d06162014-10-02 15:54:12 -0700273 private void registerSubclassCompilerIfNeeded(Intent intent) {
274 if (!compilers.containsKey(intent.getClass())) {
275 Class<?> cls = intent.getClass();
276 while (cls != Object.class) {
277 // As long as we're within the Intent class descendants
278 if (Intent.class.isAssignableFrom(cls)) {
279 IntentCompiler<?> compiler = compilers.get(cls);
280 if (compiler != null) {
281 compilers.put(intent.getClass(), compiler);
282 return;
283 }
284 }
285 cls = cls.getSuperclass();
286 }
287 }
288 }
Brian O'Connorf3d06162014-10-02 15:54:12 -0700289}