blob: ac40720ae2b8a9bce167a34efb7f135a87a3880a [file] [log] [blame]
/*******************************************************************************
* 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;
}
}