blob: b16a7d501021dc361565c374becfdb2915463a0c [file] [log] [blame]
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -08003 *
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 */
16package org.onosproject.net.intent.impl;
17
18import com.google.common.collect.ImmutableList;
19import com.google.common.collect.ImmutableMap;
Ayaka Koshibebcb02372015-06-01 10:56:42 -070020
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -080021import org.onosproject.net.intent.Intent;
22import org.onosproject.net.intent.IntentCompiler;
23import org.onosproject.net.intent.IntentException;
24
25import java.util.ArrayList;
26import java.util.List;
27import java.util.Map;
28import java.util.concurrent.ConcurrentHashMap;
29import java.util.concurrent.ConcurrentMap;
30
31// TODO: consider a better name
32class CompilerRegistry {
33
34 private final ConcurrentMap<Class<? extends Intent>,
35 IntentCompiler<? extends Intent>> compilers = new ConcurrentHashMap<>();
36
37 /**
38 * Registers the specified compiler for the given intent class.
39 *
40 * @param cls intent class
41 * @param compiler intent compiler
42 * @param <T> the type of intent
43 */
44 public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
45 compilers.put(cls, compiler);
46 }
47
48 /**
49 * Unregisters the compiler for the specified intent class.
50 *
51 * @param cls intent class
52 * @param <T> the type of intent
53 */
54 public <T extends Intent> void unregisterCompiler(Class<T> cls) {
55 compilers.remove(cls);
56 }
57
58 /**
59 * Returns immutable set of bindings of currently registered intent compilers.
60 *
61 * @return the set of compiler bindings
62 */
63 public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
64 return ImmutableMap.copyOf(compilers);
65 }
66
67 /**
68 * Compiles an intent recursively.
69 *
70 * @param intent intent
71 * @param previousInstallables previous intent installables
72 * @return result of compilation
73 */
74 List<Intent> compile(Intent intent, List<Intent> previousInstallables) {
75 if (intent.isInstallable()) {
76 return ImmutableList.of(intent);
77 }
78
79 registerSubclassCompilerIfNeeded(intent);
80 // FIXME: get previous resources
81 List<Intent> installable = new ArrayList<>();
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -080082 for (Intent compiled : getCompiler(intent).compile(intent, previousInstallables)) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -080083 installable.addAll(compile(compiled, previousInstallables));
84 }
85 return installable;
86 }
87
88 /**
89 * Returns the corresponding intent compiler to the specified intent.
90 *
91 * @param intent intent
92 * @param <T> the type of intent
93 * @return intent compiler corresponding to the specified intent
94 */
95 private <T extends Intent> IntentCompiler<T> getCompiler(T intent) {
96 @SuppressWarnings("unchecked")
97 IntentCompiler<T> compiler = (IntentCompiler<T>) compilers.get(intent.getClass());
98 if (compiler == null) {
99 throw new IntentException("no compiler for class " + intent.getClass());
100 }
101 return compiler;
102 }
103
104 /**
105 * Registers an intent compiler of the specified intent if an intent compiler
106 * for the intent is not registered. This method traverses the class hierarchy of
107 * the intent. Once an intent compiler for a parent type is found, this method
108 * registers the found intent compiler.
109 *
110 * @param intent intent
111 */
112 private void registerSubclassCompilerIfNeeded(Intent intent) {
113 if (!compilers.containsKey(intent.getClass())) {
114 Class<?> cls = intent.getClass();
115 while (cls != Object.class) {
116 // As long as we're within the Intent class descendants
117 if (Intent.class.isAssignableFrom(cls)) {
118 IntentCompiler<?> compiler = compilers.get(cls);
119 if (compiler != null) {
120 compilers.put(intent.getClass(), compiler);
121 return;
122 }
123 }
124 cls = cls.getSuperclass();
125 }
126 }
127 }
128}