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