/**
 * File:    PropertyDescriptorExtensionPoint.java
 * Created: 11.07.2008
 *
 *
/*******************************************************************************
 * Copyright (c) 2005-2011
 * University of Augsburg, Germany <www.ds-lab.org>
 *
 * 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
 *
 *    Mickael Istria, Open Wide, France
 *      - Creation and Implementation
 *******************************************************************************/

package org.eclipse.jwt.transformations.properties;


import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jwt.transformations.properties.extension.EMFBasedMultiExtensionHelper;
import org.eclipse.jwt.transformations.properties.extension.FeatureFullDescription;
import org.eclipse.jwt.transformations.properties.extension.ProxyFactory;

class PropertyProcessorsExtensionPoint {
	
	private static EMFBasedMultiExtensionHelper<PropertyProcessorFactory> extensionPoint;

	public static List<PropertyProcessor> getPropertyProcessors(EObject app, EStructuralFeature feature) {
		init();
		FeatureFullDescription currentFeature = new FeatureFullDescription(feature.getName(), app.eClass().getName(), app.eClass().getEPackage().getNsURI());
		List<PropertyProcessor> processors = new ArrayList<PropertyProcessor>();
		for (PropertyProcessorFactory factory : extensionPoint.getObject(currentFeature)) {
			processors.add(factory.createPropertyProcessor(app, feature));
		}
		if (processors.size() == 0)
			processors.add(new SimplePropertyProcess(app, feature)); // At least it contains the basic one
		return processors;
	}

	private static void init() {
		extensionPoint = new EMFBasedMultiExtensionHelper<PropertyProcessorFactory>(EXTENSION_POINT, new PropertyProcessorFactoryProxyFactory());
	}

	/********************************
	 * Extension point related code *
	 ********************************/

	/**
	 * The extension point, red from the property file
	 */
	public static final String EXTENSION_POINT = "org.eclipse.jwt.transformations.properties.customProperties"; //$NON-NLS-1$
	private static final String PROPERTY_PROCESSOR = "PropertyProcessorFactory"; //$NON-NLS-1$


	public static class PropertyProcessorFactoryProxyFactory implements ProxyFactory<PropertyProcessorFactory> {

		public PropertyProcessorFactory createProxy(IConfigurationElement member) {
			return new PropertyProcessorFactoryProxy(member);
		}
		
	}
	
	private static class PropertyProcessorFactoryProxy implements PropertyProcessorFactory {

		private PropertyProcessorFactory delegate = null; // The real callback.
		private IConfigurationElement element; // Function's configuration.
		private boolean invoked = false; // Called already.

		public PropertyProcessorFactoryProxy(IConfigurationElement element) {
			this.element = element;
		}

		private final PropertyProcessorFactory getDelegate() {
			if (invoked) {
				return delegate;
			}
			invoked = true;
			try {
				Object callback = element.createExecutableExtension(PROPERTY_PROCESSOR);
				if (!(callback instanceof PropertyProcessorFactory)) {
					throw new ClassCastException("Class [" //$NON-NLS-1$
							+ callback.getClass().getName() + "] is not an instance of PropertyDescriptorFactory"); //$NON-NLS-1$
				}
				delegate = (PropertyProcessorFactory) callback;
			} catch (CoreException ex) {
				throw new RuntimeException(ex);
			}
			return delegate;
		}

		public PropertyProcessor createPropertyProcessor(EObject app, EStructuralFeature feature) {
			return getDelegate().createPropertyProcessor(app, feature);
		}
	}
}
