Skip to content

Content of file CustomDMRMappingProvider.java

/*******************************************************************************
 * Copyright (c) 2011-2016 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:
 * Eugen Neufeld - initial API and implementation
 ******************************************************************************/
package org.eclipse.emf.ecp.view.spi.custom.model.impl;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecp.common.spi.UniqueSetting;
import org.eclipse.emf.ecp.view.spi.custom.model.ECPHardcodedReferences;
import org.eclipse.emf.ecp.view.spi.custom.model.VCustomDomainModelReference;
import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
import org.eclipse.emfforms.spi.common.report.ReportService;
import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedReport;
import org.eclipse.emfforms.spi.core.services.mappingprovider.EMFFormsMappingProvider;
import org.eclipse.emfforms.spi.core.services.mappingprovider.EMFFormsMappingProviderManager;
import org.eclipse.emfforms.spi.localization.LocalizationServiceHelper;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;

/**
 * An EMFFormsMappingProvider for {@link VCustomDomainModelReference}.
 *
 * @author Eugen Neufeld
 * @since 1.9
 *
 */
@Component
public class CustomDMRMappingProvider implements EMFFormsMappingProvider {

	private BundleContext bundleContext;
	private ServiceReference<EMFFormsMappingProviderManager> eMFFormsMappingProviderManagerServiceReference;
	private EMFFormsMappingProviderManager mappingProviderManager;
	private ReportService reportService;

	/**
	 * {@inheritDoc}
	 *
	 * @see org.eclipse.emfforms.spi.core.services.mappingprovider.EMFFormsMappingProvider#getMappingFor(org.eclipse.emf.ecp.view.spi.model.VDomainModelReference,
	 *      org.eclipse.emf.ecore.EObject)
	 */
	@Override
	public Set<UniqueSetting> getMappingFor(VDomainModelReference domainModelReference, EObject domainObject) {
		if (domainModelReference == null) {
			throw new IllegalArgumentException("The given VDomainModelReference must not be null."); //$NON-NLS-1$
		}
		if (!VCustomDomainModelReference.class.isInstance(domainModelReference)) {
			throw new IllegalArgumentException(
				"DomainModelReference must be an instance of VTableDomainModelReference."); //$NON-NLS-1$
		}

		final VCustomDomainModelReference customDomainModelReference = VCustomDomainModelReference.class
			.cast(domainModelReference);
		if (!customDomainModelReference.getDomainModelReferences().isEmpty()) {
			return getMappingFor(customDomainModelReference.getDomainModelReferences(), domainObject);
		}
		final ECPHardcodedReferences hardcodedReference;
		try {
			hardcodedReference = loadObject(customDomainModelReference.getBundleName(),
				customDomainModelReference.getClassName());
		} catch (final DatabindingFailedException ex) {
			reportService.report(new DatabindingFailedReport(ex));
			return Collections.<UniqueSetting> emptySet();
		}
		if (hardcodedReference == null) {
			reportService.report(new DatabindingFailedReport(new DatabindingFailedException(
				String
					.format(
						"The provided ECPHardcodedReferences from Bundle %1$s Class %2$s cannot be resolved.", //$NON-NLS-1$
						customDomainModelReference.getBundleName(), customDomainModelReference.getClassName()))));
			return Collections.<UniqueSetting> emptySet();
		}
		final Set<VDomainModelReference> neededDomainModelReferences = hardcodedReference
			.getNeededDomainModelReferences();
		if (neededDomainModelReferences.isEmpty()) {
			reportService.report(new DatabindingFailedReport(new DatabindingFailedException(
				String
					.format(
						"The provided ECPHardcodedReferences from Bundle %1$s Class %2$s doesn't define any DomainModelReferences.", //$NON-NLS-1$
						customDomainModelReference.getBundleName(), customDomainModelReference.getClassName()))));
			return Collections.<UniqueSetting> emptySet();
		}
		return getMappingFor(neededDomainModelReferences, domainObject);
	}

	private Set<UniqueSetting> getMappingFor(Collection<VDomainModelReference> domainModelReferences,
		EObject domainObject) {
		final Set<UniqueSetting> result = new LinkedHashSet<UniqueSetting>();
		for (final VDomainModelReference domainModelReference : domainModelReferences) {
			final Set<UniqueSetting> settingsFor = getEMFFormsMappingProviderManager()
				.getAllSettingsFor(domainModelReference, domainObject);
			if (settingsFor != null) {
				result.addAll(settingsFor);
			}
		}
		return result;
	}

	private static ECPHardcodedReferences loadObject(String bundleName, String clazz)
		throws DatabindingFailedException {
		final Bundle bundle = Platform.getBundle(bundleName);
		if (bundle == null) {
			new ClassNotFoundException(String.format(LocalizationServiceHelper.getString(
				VCustomDomainModelReferenceImpl.class, "BundleNotFound_ExceptionMessage"), clazz, bundleName)); //$NON-NLS-1$
			return null;
		}
		try {
			final Class<?> loadClass = bundle.loadClass(clazz);
			if (!ECPHardcodedReferences.class.isAssignableFrom(loadClass)) {
				return null;
			}
			return ECPHardcodedReferences.class.cast(loadClass.newInstance());
} catch (final ClassNotFoundException ex) { throw new DatabindingFailedException(ex.getMessage()); } catch (final InstantiationException ex) { throw new DatabindingFailedException(ex.getMessage()); } catch (final IllegalAccessException ex) { throw new DatabindingFailedException(ex.getMessage()); } } /** * {@inheritDoc} * * @see org.eclipse.emfforms.spi.core.services.mappingprovider.EMFFormsMappingProvider#isApplicable(org.eclipse.emf.ecp.view.spi.model.VDomainModelReference, * org.eclipse.emf.ecore.EObject) */ @Override public double isApplicable(VDomainModelReference domainModelReference, EObject domainObject) { if (VCustomDomainModelReference.class.isInstance(domainModelReference)) { return 10; } return NOT_APPLICABLE; } /** * Called by the framework when the component gets activated. * * @param bundleContext The {@link BundleContext} */ @Activate protected void activate(BundleContext bundleContext) { this.bundleContext = bundleContext; } /** * Called by the framework when the component gets deactivated. * * @param bundleContext The {@link BundleContext} */ @Deactivate protected void deactivate(BundleContext bundleContext) { if (eMFFormsMappingProviderManagerServiceReference != null) { bundleContext.ungetService(eMFFormsMappingProviderManagerServiceReference); mappingProviderManager = null; } } private EMFFormsMappingProviderManager getEMFFormsMappingProviderManager() { if (mappingProviderManager == null) { eMFFormsMappingProviderManagerServiceReference = bundleContext .getServiceReference(EMFFormsMappingProviderManager.class); if (eMFFormsMappingProviderManagerServiceReference == null) { throw new IllegalStateException("No EMFFormsDomainExpander available!"); //$NON-NLS-1$ } setEMFFormsMappingProviderManager(bundleContext.getService(eMFFormsMappingProviderManagerServiceReference)); } return mappingProviderManager; } /** * Helper method for tests. This is quite ugly! * * @param mappingProviderManager The EMFFormsMappingProviderManager to use */ void setEMFFormsMappingProviderManager(EMFFormsMappingProviderManager mappingProviderManager) { this.mappingProviderManager = mappingProviderManager; } /** * Sets the {@link ReportService}. * * @param reportService The {@link ReportService} */ @Reference(unbind = "-") protected void setReportService(ReportService reportService) { this.reportService = reportService; } }