blob: 74373d7021641a1474972bde9525c27a3e86a5e3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011-2015 EclipseSource Muenchen GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Lucas Koehler - initial API and implementation
******************************************************************************/
package org.eclipse.emf.ecp.view.model.internal.fx;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecp.view.model.common.ECPStaticRendererTester;
import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
import org.eclipse.emf.ecp.view.spi.model.VElement;
import org.eclipse.emfforms.spi.common.report.ReportService;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
public final class RendererFactoryImpl implements RendererFactory {
private static final String RENDER_EXTENSION = "org.eclipse.emf.ecp.view.model.fx.renderer";
private static final String TEST_DYNAMIC = "dynamicTest";
private static final String TEST_STATIC = "staticTest";
private static final String TESTER_PRIORITY = "priority";
private static final String TESTER_VELEMENT = "element";
private static final String RENDERER_TESTER = "testClass";
private final Set<ECPRendererDescription> rendererDescriptors = new LinkedHashSet<ECPRendererDescription>();
private ReportService reportService;
private RendererFactoryImpl() {
readRenderer();
}
private void readRenderer() {
final IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
.getExtensionPoint(RENDER_EXTENSION);
for (final IExtension extension : extensionPoint.getExtensions()) {
for (final IConfigurationElement configurationElement : extension
.getConfigurationElements()) {
try {
final Class<RendererFX<VElement>> rendererClass = loadClass(configurationElement
.getContributor().getName(),
configurationElement
.getAttribute("renderer"));
// Get tester(s) for the current renderer.
final Set<ECPRendererTester> tester = new LinkedHashSet<ECPRendererTester>();
for (final IConfigurationElement testerExtension : configurationElement.getChildren()) {
if (TEST_DYNAMIC.equals(testerExtension.getName())) {
tester.add((ECPRendererTester) testerExtension.createExecutableExtension(RENDERER_TESTER));
} else if (TEST_STATIC.equals(testerExtension.getName())) {
final int priority = Integer.parseInt(testerExtension.getAttribute(TESTER_PRIORITY));
final String vElement = testerExtension.getAttribute(TESTER_VELEMENT);
final Class<? extends VElement> supportedEObject = loadClass(testerExtension
.getContributor()
.getName(), vElement);
tester.add(new ECPStaticRendererTester(priority,
supportedEObject));
}
}
rendererDescriptors.add(new ECPRendererDescription(rendererClass, tester));
} catch (final CoreException ex) {
ex.printStackTrace();
} catch (final ClassNotFoundException e) {
e.printStackTrace();
} catch (final InvalidRegistryObjectException e) {
e.printStackTrace();
}
}
}
}
@SuppressWarnings("unchecked")
private static <T> Class<T> loadClass(String bundleName, String clazz)
throws ClassNotFoundException {
final Bundle bundle = Platform.getBundle(bundleName);
if (bundle == null) {
throw new ClassNotFoundException(clazz + bundleName);
}
return (Class<T>) bundle.loadClass(clazz);
}
private static RendererFactoryImpl INSTANCE;
public static RendererFactory getInstance() {
if (INSTANCE == null) {
INSTANCE = new RendererFactoryImpl();
}
return INSTANCE;
}
// TODO delete
// @Override
// public <T extends VElement> Set<RenderingResultRow<Node>> render(
// T renderable, final ViewModelContext viewContext) {
// RendererFX<VElement> renderer = getRenderer(renderable, viewContext);
// try {
// return renderer.render(renderable, viewContext);
// } catch(NullPointerException ex) {
// ex.printStackTrace();
// return Collections.<RenderingResultRow<Node>>emptySet();
// }
//
// }
/**
* @param vElement the vElement that should be rendered
* @param viewContext the view model context
* @return the applicable renderer for the given VElement with the highest priority
*/
@SuppressWarnings("unchecked")
@Override
public RendererFX<VElement> getRenderer(VElement vElement, ViewModelContext viewContext) {
int highestPriority = -1;
RendererFX<VElement> bestCandidate = null;
for (final ECPRendererDescription description : rendererDescriptors) {
int currentPriority = -1;
for (final ECPRendererTester tester : description.getTester()) {
final int testerPriority = tester.isApplicable(vElement, viewContext);
if (testerPriority > currentPriority) {
currentPriority = testerPriority;
}
}
if (currentPriority > highestPriority) {
highestPriority = currentPriority;
try {
bestCandidate = (RendererFX<VElement>) description.getRenderer().getConstructors()[0].newInstance(
vElement, viewContext, getReportService());
} catch (final InstantiationException ex) {
ex.printStackTrace();
return null;
} catch (final IllegalAccessException ex) {
ex.printStackTrace();
return null;
} catch (final IllegalArgumentException ex) {
ex.printStackTrace();
return null;
} catch (final InvocationTargetException ex) {
ex.printStackTrace();
return null;
} catch (final SecurityException ex) {
ex.printStackTrace();
return null;
}
}
}
return bestCandidate;
}
private ReportService getReportService() {
if (reportService == null) {
final BundleContext bundleContext = FrameworkUtil.getBundle(RendererFactoryImpl.class).getBundleContext();
final ServiceReference<ReportService> serviceReference = bundleContext
.getServiceReference(ReportService.class);
reportService = bundleContext.getService(serviceReference);
}
return reportService;
}
}