/**
 * File:    ProcessServiceMembers.java
 * Created: 26.02.2008
 *
 *
/*******************************************************************************
 * Copyright (c) 2008  Open Wide (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:
 *    Mickael Istria, Open Wide, Lyon, France
 *      - creation and implementation (see
 *      http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html)
 *******************************************************************************/

package org.eclipse.jwt.transformations.base.init;

import java.io.IOException;

import org.eclipse.core.runtime.CoreException;
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.transformations.api.TransformationException;
import org.eclipse.jwt.transformations.api.TransformationService;
import org.eclipse.ui.WorkbenchException;

public class ProcessServiceMembers {
	
	public class Type { // Matches possible value of type attribute
		public static final String EXPORT = "export"; //$NON-NLS-1$
		public static final String IMPORT = "import"; //$NON-NLS-1$
	}
	
	private static final String TRANSFORMATION_NAME_ATTRIBUTE = "name"; //$NON-NLS-1$
	private static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
	private static final String DESCRIPTION_ATTRIBUTE = "description"; //$NON-NLS-1$
	private static final String TYPE_ATTRIBUTE = "type"; //$NON-NLS-1$

	public static void process(String EXTENSION_POINT, TransformationRegistry transformationRegistry) throws WorkbenchException {
		IExtensionRegistry registry = Platform.getExtensionRegistry();
		IExtensionPoint extensionPoint = registry
				.getExtensionPoint(EXTENSION_POINT);
		IConfigurationElement[] members = extensionPoint
				.getConfigurationElements();
		// For each service:
		for (int m = 0; m < members.length; m++) {
			IConfigurationElement member = members[m];
			String functionName = member
					.getAttribute(TRANSFORMATION_NAME_ATTRIBUTE);
			TransformationService proxy = new TransformationProxy(member);
			proxy.setDescription(member.getAttribute(DESCRIPTION_ATTRIBUTE));
			proxy.setType(member.getAttribute(TYPE_ATTRIBUTE));
			transformationRegistry.addTransformation(functionName, proxy);
		}
	}

	private static class TransformationProxy extends TransformationService {
		private TransformationService delegate = null; // The real callback.
		private IConfigurationElement element; // Function's configuration.
		private boolean invoked = false; // Called already.

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

		@Override
		public final void transform(String inFilePath, String outFilePath) throws IOException, TransformationException {
			try {
				getDelegate();
			} catch (Exception ex) {
				throw new TransformationException("invalid function"); //$NON-NLS-1$
			}
			if (delegate == null) {
				throw new TransformationException("invalid function"); //$NON-NLS-1$
			}
			delegate.transform(inFilePath, outFilePath);
		}

		private final TransformationService getDelegate() throws Exception {
			if (invoked) {
				return delegate;
			}
			invoked = true;
			try {
				Object callback = element
						.createExecutableExtension(CLASS_ATTRIBUTE);
				if (!(callback instanceof TransformationService)) {
					throw new Exception("TransformationService creation error");  //$NON-NLS-1$
				}
				delegate = (TransformationService) callback;
			} catch (CoreException ex) {
				throw ex;
			}
			return delegate;
		}
	}
}
