| /******************************************************************************* |
| * Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Pierre Allard, |
| * Regent L'Archeveque, |
| * Sebastien Gemme - initial API and implementation |
| * |
| * SPDX-License-Identifier: EPL-1.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.apogy.common.topology.ui; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.apogy.common.topology.ContentNode; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class AdapterFactory<S extends ObjectAdapter<T, V, U>, T, V, U> { |
| |
| private static final Logger Logger = LoggerFactory.getLogger(AdapterFactory.class); |
| |
| private final List<S> adapters; |
| private List<Class<?>> classes; |
| private Map<Class<?>, S> classesToAdapterMap; |
| |
| /** |
| * |
| * @param adapters |
| */ |
| public AdapterFactory(List<S> adapters) { |
| this.adapters = adapters; |
| } |
| |
| private List<Class<?>> getClasses() { |
| |
| if (this.classes == null) { |
| |
| this.classes = new ArrayList<Class<?>>(); |
| |
| // We get the registered adapters. |
| Iterator<S> iterator = this.adapters.iterator(); |
| |
| while (iterator.hasNext()) { |
| S adapter = iterator.next(); |
| |
| getClassesToAdapterMap().put(adapter.getAdaptedClass(), adapter); |
| |
| this.classes.add(adapter.getAdaptedClass()); |
| |
| } |
| } |
| |
| return this.classes; |
| } |
| |
| private Map<Class<?>, S> getClassesToAdapterMap() { |
| |
| if (this.classesToAdapterMap == null) { |
| |
| this.classesToAdapterMap = new HashMap<Class<?>, S>(); |
| } |
| |
| return this.classesToAdapterMap; |
| } |
| |
| /** |
| * Retrieves the appropriate adapter for node 'node'. |
| * |
| * @param obj the object we wish to get the adapter. |
| * @return the appropriate adapter for node 'node' or <code>null</code> if none |
| * is found. |
| */ |
| public synchronized S getAdapterFor(V obj) { |
| S adapter = null; |
| |
| // We go through all the classes. |
| Iterator<Class<?>> iterator = getClasses().iterator(); |
| |
| Object nodeContent = null; |
| |
| if (obj instanceof ContentNode<?>) { |
| ContentNode<?> cNode = (ContentNode<?>) obj; |
| nodeContent = cNode.getContent(); |
| } else { |
| nodeContent = obj; |
| } |
| |
| try { |
| if (nodeContent != null) { |
| for (Class<?> value : getClasses()) { |
| Logger.debug(value.getName()); |
| } |
| |
| Class<?> closestMatch = null; |
| |
| while (iterator.hasNext()) { |
| Class<?> c = iterator.next(); |
| |
| // If c is a super class or interface of aClass |
| if (c.isAssignableFrom(nodeContent.getClass())) { |
| Logger.debug("\t Found potential match with : " + c.getCanonicalName()); |
| |
| // If no match found yet or the current match is a superclass of the current |
| // one. |
| if ((closestMatch == null) || (closestMatch.isAssignableFrom(c))) { |
| closestMatch = c; |
| } |
| } |
| } |
| |
| Logger.debug("Closest Match : " + closestMatch); |
| |
| adapter = getClassesToAdapterMap().get(closestMatch); |
| } |
| } catch (IllegalArgumentException e) { |
| // Multiple-inheritance is not acceptable !!! |
| Logger.error("Multiple adapters found for <" + obj.getClass().getName() + ">."); |
| } |
| |
| if (adapter == null) { |
| Logger.error("Cannot find an adapter for object of type <" + obj.getClass().getName() + ">!"); |
| } else { |
| Logger.info("Using adapter <" + adapter.getClass().getName() + "> for class <" + obj.getClass().getName() |
| + ">"); |
| } |
| |
| return adapter; |
| } |
| } |