/******************************************************************************
 * Copyright (c) 2005, 2007 BEA Systems, Inc.
 * 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:
 *    Konstantin Komissarchik
 ******************************************************************************/

package org.eclipse.jst.j2ee.internal.archive;

import static org.eclipse.jst.j2ee.internal.archive.ArchiveExportParticipantsExtensionPoint.PluginUtil.*;
import static org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.eclipse.core.expressions.EvaluationContext;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.ExpressionConverter;
import org.eclipse.core.resources.IProject;
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.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jst.j2ee.archive.IArchiveExportParticipant;
import org.eclipse.jst.j2ee.internal.archive.ArchiveExportParticipantsExtensionPoint.PluginUtil.InvalidExtensionException;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntime;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeComponent;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeComponentType;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntimeComponentVersion;
import org.eclipse.wst.common.project.facet.core.runtime.RuntimeManager;
import org.osgi.framework.Bundle;

/**
 * Contains the logic for processing the <code>org.eclipse.jst.j2ee.archiveExportParticipants</code>
 * extension point. 
 * 
 * @author <a href="mailto:kosta@bea.com">Konstantin Komissarchik</a>
 */

public final class ArchiveExportParticipantsExtensionPoint
{
    public static final String EXTENSION_POINT_ID = "archiveExportParticipants"; //$NON-NLS-1$

    private static final String EL_PARTICIPANT = "participant"; //$NON-NLS-1$
    private static final String EL_RUNTIME_COMPONENT = "runtime-component"; //$NON-NLS-1$
    private static final String EL_FACTORY = "factory"; //$NON-NLS-1$
    private static final String EL_ENABLEMENT = "enablement"; 
    private static final String ATTR_ID = "id"; //$NON-NLS-1$
    private static final String ATTR_TYPE = "type"; //$NON-NLS-1$
    private static final String ATTR_VERSION = "version"; //$NON-NLS-1$
    private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
    
    private static List<ParticipantInfo> extensions = null;
    
    public static class ParticipantInfo
    {
        private String id;
        private String pluginId = null;
        private String className = null;
        private IRuntimeComponentType runtimeComponentType = null;
        private String runtimeComponentVersionExpr = null;
        private Expression enablementCondition = null;
        
        public String getId()
        {
            return this.id;
        }
        
        public IArchiveExportParticipant loadParticipant()
        {
            try
            {
                return instantiate( this.pluginId, this.className, IArchiveExportParticipant.class );
            }
            catch( CoreException e )
            {
                log( e.getStatus() );
                return null;
            }
        }
    }
    
    public static List<ParticipantInfo> getExtensions( final IProject project,
                                                       final IRuntime runtime )
    {
        readExtensions();
        
        final List<ParticipantInfo> result = new ArrayList<ParticipantInfo>();
        
        for( ParticipantInfo partInfo : extensions )
        {
            boolean match = false;
            
            for( IRuntimeComponent rc : runtime.getRuntimeComponents() )
            {
                final IRuntimeComponentType rct = rc.getRuntimeComponentType();
                
                if( rct == partInfo.runtimeComponentType )
                {
                    final IRuntimeComponentVersion rcv = rc.getRuntimeComponentVersion();
                    
                    try
                    {
                        if( rct.getVersions( partInfo.runtimeComponentVersionExpr ).contains( rcv ) )
                        {
                            match = true;
                            break;
                        }
                    }
                    catch( CoreException e )
                    {
                        logError( -1, e.getMessage(), e );
                    }
                }
            }
            
            if( match && partInfo.enablementCondition != null )
            {
                final EvaluationContext evalContext = new EvaluationContext( null, project );
                evalContext.setAllowPluginActivation( true );
            
                try
                {
                    final EvaluationResult evalResult 
                        = partInfo.enablementCondition.evaluate( evalContext );
                    
                    if( evalResult != EvaluationResult.TRUE )
                    {
                        match = false;
                    }
                }
                catch( CoreException e )
                {
                    logError( -1, e.getMessage(), e );
                }
            }
            
            if( match )
            {
                result.add( partInfo );
            }
        }
        
        return Collections.unmodifiableList( result );
    }
                                                                             
    private static synchronized void readExtensions()
    {
        if( extensions != null )
        {
            return;
        }
        
        extensions = new ArrayList<ParticipantInfo>();
        
        for( IConfigurationElement element 
             : getTopLevelElements( findExtensions( PLUGIN_ID, EXTENSION_POINT_ID ) ) )
        {
            if( element.getName().equals( EL_PARTICIPANT ) )
            {
                try
                {
                    readExtension( element );
                }
                catch( InvalidExtensionException e )
                {
                    // Continue. The problem has been reported to the user via the log.
                }
            }
        }
    }

    private static void readExtension( final IConfigurationElement config )
    
        throws InvalidExtensionException
        
    {
        final ParticipantInfo info = new ParticipantInfo();

        info.pluginId = config.getContributor().getName();
        info.id = info.pluginId + "." + findRequiredAttribute( config, ATTR_ID );
        
        final IConfigurationElement elFactory = findRequiredElement( config, EL_FACTORY );
        info.className = findRequiredAttribute( elFactory, ATTR_CLASS );
        
        final IConfigurationElement elRuntimeComponent 
            = findRequiredElement( config, EL_RUNTIME_COMPONENT );
        
        final String rcTypeString = findRequiredAttribute( elRuntimeComponent, ATTR_TYPE );
        
        if( ! RuntimeManager.isRuntimeComponentTypeDefined( rcTypeString ) )
        {
            // TODO: Log the problem
            throw new InvalidExtensionException();
        }
        
        info.runtimeComponentType = RuntimeManager.getRuntimeComponentType( rcTypeString );
        info.runtimeComponentVersionExpr = elRuntimeComponent.getAttribute( ATTR_VERSION );
        
        final IConfigurationElement elEnablement = findOptionalElement( config, EL_ENABLEMENT );
        
        try
        {
            info.enablementCondition = ExpressionConverter.getDefault().perform( elEnablement );
        }
        catch( CoreException e )
        {
            logError( -1, e.getMessage(), e );
            throw new InvalidExtensionException();
        }
        
        extensions.add( info );
    }
    
    /**
     * Utility methods that are helpful for implementing extension points.
     *
     * @author <a href="mailto:kosta@bea.com">Konstantin Komissarchik</a>
     */

    public static final class PluginUtil
    {
        public static final class InvalidExtensionException

            extends Exception
        
        {
            private static final long serialVersionUID = 1L;
        }
        
        private PluginUtil() {}
        
        public static Collection<IExtension> findExtensions( final String pluginId,
                                                             final String extensionPointId )
        {
            final IExtensionRegistry registry = Platform.getExtensionRegistry();
            final IExtensionPoint point = registry.getExtensionPoint( pluginId, extensionPointId );
            
            if( point == null )
            {
                throw new RuntimeException();
            }
            
            final List<IExtension> extensions = new ArrayList<IExtension>();
            
            for( IExtension extension : point.getExtensions() )
            {
                extensions.add( extension );
            }
            
            return extensions;
        }
        
        public static Collection<IConfigurationElement> getTopLevelElements( final Collection<IExtension> extensions )
        {
            final List<IConfigurationElement> elements = new ArrayList<IConfigurationElement>();
            
            for( IExtension extension : extensions )
            {
                for( IConfigurationElement element : extension.getConfigurationElements() )
                {
                    elements.add( element );
                }
            }
            
            return elements;
        }

        public static void reportMissingAttribute( final IConfigurationElement el,
                                                   final String attribute )
        {
            final String pluginId = el.getContributor().getName();
            final String extPointId = el.getDeclaringExtension().getExtensionPointUniqueIdentifier();
            
            final String msg
                = Resources.bind( Resources.missingAttribute, pluginId, extPointId, el.getName(), 
                                  attribute );

            log( createErrorStatus( -1, msg, null ) );
        }

        public static void reportMissingElement( final IConfigurationElement el,
                                                 final String element )
        {
            final String pluginId = el.getContributor().getName();
            final String extPointId = el.getDeclaringExtension().getExtensionPointUniqueIdentifier();
            
            final String msg
                = Resources.bind( Resources.missingElement, pluginId, extPointId, el.getName(), 
                                  element );

            log( createErrorStatus( -1, msg, null ) );
        }

        public static String findRequiredAttribute( final IConfigurationElement el,
                                                    final String attribute )

            throws InvalidExtensionException

        {
            final String val = el.getAttribute( attribute );

            if( val == null )
            {
                reportMissingAttribute( el, attribute );
                throw new InvalidExtensionException();
            }

            return val;
        }

        public static IConfigurationElement findRequiredElement( final IConfigurationElement el,
                                                                 final String childElement )

            throws InvalidExtensionException

        {
            final IConfigurationElement[] children = el.getChildren( childElement );

            if( children.length == 0 )
            {
                reportMissingElement( el, childElement );
                throw new InvalidExtensionException();
            }

            return children[ 0 ];
        }

        public static IConfigurationElement findOptionalElement( final IConfigurationElement el,
                                                                 final String childElement )
        {
            final IConfigurationElement[] children = el.getChildren( childElement );

            if( children.length == 0 )
            {
                return null;
            }
            else
            {
                return children[ 0 ];
            }
        }
        
        public static String getElementValue( final IConfigurationElement el,
                                              final String defaultValue )
        {
            if( el != null )
            {
                String text = el.getValue();
                
                if( text != null )
                {
                    text = text.trim();
                    
                    if( text.length() > 0 )
                    {
                        return text;
                    }
                }
            }
            
            return defaultValue;
        }
        
        @SuppressWarnings( "unchecked" )
        public static <T> T instantiate( final String pluginId,
                                         final String clname,
                                         final Class<T> interfc )
        
            throws CoreException
            
        {
            final Bundle bundle = Platform.getBundle( pluginId );
            
            final Object obj;
            
            try
            {
                final Class cl = bundle.loadClass( clname );
                obj = cl.newInstance();
            }
            catch( Exception e )
            {
                final String msg = NLS.bind( Resources.failedToCreate, clname );
                throw new CoreException( createErrorStatus( -1, msg, e ) );
            }
            
            if( ! interfc.isAssignableFrom( obj.getClass() ) )
            {
                final String msg
                    = NLS.bind( Resources.doesNotImplement, clname, interfc.getClass().getName() );
                
                throw new CoreException( createErrorStatus( -1, msg, null ) );
            }
            
            return (T) obj;
        }
        
        private static final class Resources

            extends NLS
        
        {
            public static String missingAttribute;
            public static String missingElement;
            public static String failedToCreate;
            public static String doesNotImplement;
        
            static
            {
                initializeMessages( PluginUtil.class.getName(), Resources.class );
            }
            
            public static String bind( final String message,
                                       final String arg1,
                                       final String arg2,
                                       final String arg3,
                                       final String arg4 )
            {
                return bind( message, new Object[] { arg1, arg2, arg3, arg4 } );
            }
        }
        
    }
    
}
