| /* |
| * Copyright 2015 Open Networking Laboratory |
| * |
| * 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 org.onosproject.net.intent.impl; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import org.onosproject.net.intent.Intent; |
| import org.onosproject.net.intent.IntentCompiler; |
| import org.onosproject.net.intent.IntentException; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.ConcurrentMap; |
| |
| // TODO: consider a better name |
| class CompilerRegistry { |
| |
| private final ConcurrentMap<Class<? extends Intent>, |
| IntentCompiler<? extends Intent>> compilers = new ConcurrentHashMap<>(); |
| |
| /** |
| * Registers the specified compiler for the given intent class. |
| * |
| * @param cls intent class |
| * @param compiler intent compiler |
| * @param <T> the type of intent |
| */ |
| public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) { |
| compilers.put(cls, compiler); |
| } |
| |
| /** |
| * Unregisters the compiler for the specified intent class. |
| * |
| * @param cls intent class |
| * @param <T> the type of intent |
| */ |
| public <T extends Intent> void unregisterCompiler(Class<T> cls) { |
| compilers.remove(cls); |
| } |
| |
| /** |
| * Returns immutable set of bindings of currently registered intent compilers. |
| * |
| * @return the set of compiler bindings |
| */ |
| public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() { |
| return ImmutableMap.copyOf(compilers); |
| } |
| |
| /** |
| * Compiles an intent recursively. |
| * |
| * @param intent intent |
| * @param previousInstallables previous intent installables |
| * @return result of compilation |
| */ |
| List<Intent> compile(Intent intent, List<Intent> previousInstallables) { |
| if (intent.isInstallable()) { |
| return ImmutableList.of(intent); |
| } |
| |
| registerSubclassCompilerIfNeeded(intent); |
| // FIXME: get previous resources |
| List<Intent> installable = new ArrayList<>(); |
| for (Intent compiled : getCompiler(intent).compile(intent, previousInstallables, null)) { |
| installable.addAll(compile(compiled, previousInstallables)); |
| } |
| return installable; |
| } |
| |
| /** |
| * Returns the corresponding intent compiler to the specified intent. |
| * |
| * @param intent intent |
| * @param <T> the type of intent |
| * @return intent compiler corresponding to the specified intent |
| */ |
| private <T extends Intent> IntentCompiler<T> getCompiler(T intent) { |
| @SuppressWarnings("unchecked") |
| IntentCompiler<T> compiler = (IntentCompiler<T>) compilers.get(intent.getClass()); |
| if (compiler == null) { |
| throw new IntentException("no compiler for class " + intent.getClass()); |
| } |
| return compiler; |
| } |
| |
| /** |
| * Registers an intent compiler of the specified intent if an intent compiler |
| * for the intent is not registered. This method traverses the class hierarchy of |
| * the intent. Once an intent compiler for a parent type is found, this method |
| * registers the found intent compiler. |
| * |
| * @param intent intent |
| */ |
| private void registerSubclassCompilerIfNeeded(Intent intent) { |
| if (!compilers.containsKey(intent.getClass())) { |
| Class<?> cls = intent.getClass(); |
| while (cls != Object.class) { |
| // As long as we're within the Intent class descendants |
| if (Intent.class.isAssignableFrom(cls)) { |
| IntentCompiler<?> compiler = compilers.get(cls); |
| if (compiler != null) { |
| compilers.put(intent.getClass(), compiler); |
| return; |
| } |
| } |
| cls = cls.getSuperclass(); |
| } |
| } |
| } |
| } |