/**
 * File:    AspectFactoryRegistryImpl.java
 * Created: 08.11.2008
 *
 *
/*******************************************************************************
 * Copyright (c) 2008-2009 Open Wide SA <www.openwide.fr>
 *
 * 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:
 *    Marc Dutoo, Open Wide SA 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.conf.model.aspects.factory.internal;

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

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jwt.we.conf.model.Aspect;
import org.eclipse.jwt.we.conf.model.aspects.factory.AspectFactory;
import org.eclipse.jwt.we.conf.model.aspects.factory.RegistryAspectFactory;
import org.eclipse.jwt.we.conf.model.aspects.factory.AspectFactory.Registry;
import org.eclipse.jwt.we.conf.model.plugin.ConfPlugin;

/**
 * Aspect factory registry. Extensible.
 * 
 * @version $Id: AspectFactoryRegistryImpl.java,v 1.1 2010-05-10 08:27:23 chsaad Exp $
 * @author Marc Dutoo, Open Wide SA
 */
public class AspectFactoryRegistryImpl implements AspectFactory.Registry {
	
	public static final String ASPECT_FACTORY_EXTENSION_POINT_FACTORY_CLASS = "class"; //$NON-NLS-1$
	
	protected List<RegistryAspectFactory> registryAspectFactories = new ArrayList<RegistryAspectFactory>();
	protected RegistryAspectFactory defaultEclassAspectFactory = new EclassAspectFactory();
	
	protected AspectFactoryRegistryImpl() {
		
	}

	
	public static Registry createRegistry() {
		AspectFactoryRegistryImpl aspectFactoryImpl = new AspectFactoryRegistryImpl();
		aspectFactoryImpl.loadDeclaredFactories();
		return aspectFactoryImpl;
	}

	
	public AspectFactory getFactory(Aspect aspect) {
		for (RegistryAspectFactory registryAspectFactory : registryAspectFactories) {
			if (registryAspectFactory.isFactoryFor(aspect)) {
				return registryAspectFactory;
			}
		}
		if (!defaultEclassAspectFactory.isFactoryFor(aspect)) {
			// unsupported aspect type
    		ConfPlugin.logger.severe("Creating aspect : no suitable aspect factory" //$NON-NLS-1$
    				+ "found in aspect factory registry for aspect " + aspect.getId() + " with eclassifier " //$NON-NLS-1$ //$NON-NLS-2$
    				+ aspect.getAspectInstanceEType());
		}
		return defaultEclassAspectFactory;
	}


	protected void loadDeclaredFactories() {
		ConfPlugin.logger.debug("get aspectFactories from extension point " + ASPECT_FACTORY_EXTENSION_POINT_ID); //$NON-NLS-1$

		try {
			// get the extension point registry
			IExtensionRegistry registry = Platform.getExtensionRegistry();
			IExtensionPoint aspectFactoryExtensionPoint = registry.getExtensionPoint(ASPECT_FACTORY_EXTENSION_POINT_ID);

			// exit if there are no extensions registered or no configurable elements
			if (aspectFactoryExtensionPoint == null || aspectFactoryExtensionPoint.getConfigurationElements() == null) {
				ConfPlugin.logger.debug("No declared aspect factory extension found at point " + ASPECT_FACTORY_EXTENSION_POINT_ID); //$NON-NLS-1$
				return;
			}

			// read declared aspect factory extension point
			for (IConfigurationElement elt : aspectFactoryExtensionPoint.getConfigurationElements()) {
				// read the aspect factory class entry in the extension point
  				Object factory = elt.createExecutableExtension(ASPECT_FACTORY_EXTENSION_POINT_FACTORY_CLASS);
  				
  				if (factory instanceof RegistryAspectFactory) {
  					registryAspectFactories.add((RegistryAspectFactory) factory);
  					ConfPlugin.logger.info("ConfModel extension - found registered aspect factory at " //$NON-NLS-1$
  							+ ASPECT_FACTORY_EXTENSION_POINT_ID + ": " + factory); //$NON-NLS-1$
  					
  				} else {
  					ConfPlugin.logger.warning("ConfModel Extension - at " + ASPECT_FACTORY_EXTENSION_POINT_ID + ": " //$NON-NLS-1$ //$NON-NLS-2$
  							+ factory + " is not a registered aspect factory"); //$NON-NLS-1$
  				}
			}

		} catch (Exception e) {
			ConfPlugin.logger.severe("Error loading registered aspect factories", e); //$NON-NLS-1$
		}
	}
	
}
