/******************************************************************************
 * Copyright (c) 2010, 2021 Oracle and others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * Contributors:
 *    Konstantin Komissarchik - initial implementation and ongoing maintenance
 ******************************************************************************/

package org.eclipse.wst.common.project.facet.core.internal;

import static org.eclipse.wst.common.project.facet.core.util.internal.FileUtil.FILE_DOT_PROJECT;
import static org.eclipse.wst.common.project.facet.core.util.internal.FileUtil.validateEdit;
import static org.eclipse.wst.common.project.facet.core.util.internal.PluginUtil.findOptionalElement;
import static org.eclipse.wst.common.project.facet.core.util.internal.PluginUtil.findRequiredAttribute;
import static org.eclipse.wst.common.project.facet.core.util.internal.PluginUtil.getElementValue;
import static org.eclipse.wst.common.project.facet.core.util.internal.PluginUtil.instantiate;
import static org.eclipse.wst.common.project.facet.core.util.internal.PluginUtil.reportMissingAttribute;
import static org.eclipse.wst.common.project.facet.core.util.internal.PluginUtil.reportMissingElement;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
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.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.project.facet.core.IActionDefinition;
import org.eclipse.wst.common.project.facet.core.ICategory;
import org.eclipse.wst.common.project.facet.core.IConstraint;
import org.eclipse.wst.common.project.facet.core.IDefaultVersionProvider;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IFacetedProject.Action;
import org.eclipse.wst.common.project.facet.core.IFacetedProjectTemplate;
import org.eclipse.wst.common.project.facet.core.IFacetedProjectWorkingCopy;
import org.eclipse.wst.common.project.facet.core.IGroup;
import org.eclipse.wst.common.project.facet.core.IPreset;
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.IVersionExpr;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectEvent;
import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectFrameworkEvent;
import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectFrameworkListener;
import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectListener;
import org.eclipse.wst.common.project.facet.core.events.internal.EventsExtensionPoint;
import org.eclipse.wst.common.project.facet.core.events.internal.FacetedProjectFrameworkEvent;
import org.eclipse.wst.common.project.facet.core.events.internal.FrameworkListenerRegistry;
import org.eclipse.wst.common.project.facet.core.events.internal.LegacyEventHandlerAdapter;
import org.eclipse.wst.common.project.facet.core.events.internal.ProjectListenerRegistry;
import org.eclipse.wst.common.project.facet.core.util.internal.IndexedSet;
import org.eclipse.wst.common.project.facet.core.util.internal.PluginUtil.InvalidExtensionException;
import org.eclipse.wst.common.project.facet.core.util.internal.VersionExpr;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;

/**
 * The implementation of the {@link ProjectFacetsManager} abstract class.
 * 
 * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a>
 */

public final class FacetedProjectFrameworkImpl
{
    private static final String EXTENSION_ID = "facets"; //$NON-NLS-1$

    private static final String ATTR_CATEGORY = "category"; //$NON-NLS-1$
    private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
    private static final String ATTR_FACET = "facet"; //$NON-NLS-1$
    private static final String ATTR_GROUP = "group"; //$NON-NLS-1$
    private static final String ATTR_ID = "id"; //$NON-NLS-1$
    private static final String ATTR_NAME = "name"; //$NON-NLS-1$
    private static final String ATTR_PROVIDER = "provider"; //$NON-NLS-1$
    private static final String ATTR_SOFT = "soft"; //$NON-NLS-1$
    private static final String ATTR_TYPE = "type"; //$NON-NLS-1$
    private static final String ATTR_VALUE = "value"; //$NON-NLS-1$
    private static final String ATTR_VERSION = "version"; //$NON-NLS-1$
    private static final String EL_ACTION = "action"; //$NON-NLS-1$
    private static final String EL_CATEGORY = "category"; //$NON-NLS-1$
    private static final String EL_CONFIG_FACTORY = "config-factory"; //$NON-NLS-1$
    private static final String EL_CONSTRAINT = "constraint"; //$NON-NLS-1$
    private static final String EL_DEFAULT_VERSION = "default-version"; //$NON-NLS-1$
    private static final String EL_DELEGATE = "delegate"; //$NON-NLS-1$
    private static final String EL_DESCRIPTION = "description"; //$NON-NLS-1$
    private static final String EL_EVENT_HANDLER = "event-handler"; //$NON-NLS-1$
    private static final String EL_LABEL = "label"; //$NON-NLS-1$
    private static final String EL_MEMBER = "member"; //$NON-NLS-1$
    private static final String EL_PROJECT_FACET = "project-facet"; //$NON-NLS-1$
    private static final String EL_PROJECT_FACET_VERSION = "project-facet-version"; //$NON-NLS-1$
    private static final String EL_PROPERTY = "property"; //$NON-NLS-1$
    private static final String EL_VERSION_COMPARATOR = "version-comparator"; //$NON-NLS-1$
    
    private static final String DEFAULT_DESCRIPTION = ""; //$NON-NLS-1$
    
    private static FacetedProjectFrameworkImpl instance = null;
    
    private final IndexedSet<String,IProjectFacet> facets;
    private final IndexedSet<String,IActionDefinition> actions;
    private final IndexedSet<String,ICategory> categories;
    private final IndexedSet<String,IPreset> presets;
    private boolean presetsInitialized = false;
    private final IndexedSet<String,IGroup> groups;
    private final Map<String,FacetedProject> projects;
    private final ProjectListenerRegistry projectListenerRegistry;
    private final FrameworkListenerRegistry frameworkListenerRegistry;
    
    private WeakReference<ProjectFacetPreferencesGroup> globalPreferencesGroup = null;
    
    private Map<String,WeakReference<ProjectFacetPreferencesGroup>> projectPreferencesGroups 
        = new HashMap<String,WeakReference<ProjectFacetPreferencesGroup>>();
    
    private FacetedProjectFrameworkImpl()
    {
        long activationStart = 0;
        
        if( FacetCorePlugin.isTracingFrameworkActivation() )
        {
            final StringWriter sw = new StringWriter();
            final PrintWriter pw = new PrintWriter( sw );
            ( new Throwable() ).printStackTrace( pw );
            
            String context = sw.getBuffer().toString();
            final int endOfFirstLine = context.indexOf( '\n' );
            context = context.substring( endOfFirstLine + 1 );
            context = context.replaceAll( "\\t", "  " ); //$NON-NLS-1$ //$NON-NLS-2$
            
            int length = context.length();
            
            if( context.charAt( length - 2 ) == '\r' )
            {
                length = length - 2;
            }
            else
            {
                length = length - 1;
            }
            
            context = context.substring( 0, length );
            
            final String msg 
                = NLS.bind( Resources.tracingFrameworkActivationStarting, 
                            context ); 
            
            System.out.println( msg );
            
            activationStart = System.currentTimeMillis();
        }
        
        this.facets = new IndexedSet<String,IProjectFacet>();
        this.actions = new IndexedSet<String,IActionDefinition>();
        this.categories = new IndexedSet<String,ICategory>();
        this.presets = new IndexedSet<String,IPreset>();
        this.presetsInitialized = false;
        this.groups = new IndexedSet<String,IGroup>();
        this.projects = new HashMap<String,FacetedProject>();
        this.projectListenerRegistry = new ProjectListenerRegistry();
        this.frameworkListenerRegistry = new FrameworkListenerRegistry();
        
        readMetadata();
        
        EventsExtensionPoint.processExtensions( this );
        
        ( new ResourceChangeListener() ).register();
        
        if( FacetCorePlugin.isTracingFrameworkActivation() )
        {
            final long duration 
                = System.currentTimeMillis() - activationStart;
            
            final String msg
                = NLS.bind( Resources.tracingFrameworkActivationFinished, 
                            String.valueOf( duration ) );
            
            System.out.println( msg );
        }
    }
    
    public synchronized static FacetedProjectFrameworkImpl getInstance()
    {
        if( instance == null )
        {
            instance = new FacetedProjectFrameworkImpl();
        }
        
        return instance;
    }
    
    public Set<IProjectFacet> getProjectFacets()
    {
        return this.facets.getItemSet();
    }
    
    public boolean isProjectFacetDefined( final String id )
    {
        return this.facets.containsKey( id );
    }
    
    public IProjectFacet getProjectFacet( final String id )
    {
        final IProjectFacet f = this.facets.getItemByKey( id );
        
        if( f == null )
        {
            final String msg = NLS.bind( Resources.facetNotDefined, id );
            throw new IllegalArgumentException( msg );
        }
        
        return f;
    }
    
    public Set<IActionDefinition> getActionDefinitions()
    {
        return this.actions.getItemSet();
    }
    
    public boolean isActionDefined( final String id )
    {
        return this.actions.containsKey( id );
    }
    
    public IActionDefinition getActionDefinition( final String id )
    {
        final IActionDefinition adef = this.actions.getItemByKey( id );
        
        if( adef == null )
        {
            final String msg = NLS.bind( Resources.actionNotDefined, id );
            throw new IllegalArgumentException( msg );
        }
        
        return adef;
    }
    
    public Set<ICategory> getCategories()
    {
        return this.categories.getItemSet();
    }

    public boolean isCategoryDefined( final String id )
    {
        return this.categories.containsKey( id );
    }
    
    public ICategory getCategory( final String id )
    {
        final ICategory category = this.categories.getItemByKey( id );
        
        if( category == null )
        {
            final String msg = NLS.bind( Resources.categoryNotDefined, id );
            throw new IllegalArgumentException( msg );
        }
        
        return category;
    }
    
    public Set<IPreset> getPresets()
    {
        synchronized( this.presets )
        {
            initializePresets();
            return this.presets.getItemSet();
        }
    }
    
    public boolean isPresetDefined( final String id )
    {
        synchronized( this.presets )
        {
            initializePresets();
            return this.presets.containsKey( id );
        }
    }
    
    public IPreset getPreset( final String id )
    {
        synchronized( this.presets )
        {
            initializePresets();
            
            final IPreset preset = this.presets.getItemByKey( id );
            
            if( preset == null )
            {
                final String msg = NLS.bind( Resources.presetNotDefined, id );
                throw new IllegalArgumentException( msg );
            }
            
            return preset;
        }
    }
    
    public IPreset definePreset( final String name,
                                 final Set<IProjectFacetVersion> facets )
    {
        return definePreset( name, null, facets );
    }

    public IPreset definePreset( final String name,
                                 final String description,
                                 final Set<IProjectFacetVersion> facets )
    {
       initializePresets();
       
       final IPreset preset = definePreset( name, description, facets, true );

       final IFacetedProjectFrameworkEvent event 
           = new FacetedProjectFrameworkEvent( IFacetedProjectFrameworkEvent.Type.PRESET_ADDED );
       
       this.frameworkListenerRegistry.notifyListeners( event );
       
       return preset;
    }
    
    private IPreset definePreset( final String name,
                                  final String description,
                                  final Set<IProjectFacetVersion> facets,
                                  final boolean save )
    {
        synchronized( this.presets )
        {
            String id;
            int i = 0;
            
            do
            {
                id = ".usr." + i; //$NON-NLS-1$
                i++;
            }
            while( this.presets.containsKey( id ) );
            
            final UserPreset preset 
                = new UserPreset( id, name, description == null ? "" : description,  //$NON-NLS-1$
                                  facets );
            
            this.presets.addItemWithKey( id, preset );
            
            if( save )
            {
                saveUserPresets();
            }
            
            return preset;
        }
    }
    
    public boolean deletePreset( final IPreset preset )
    {
        boolean deleted;
        
        synchronized( this.presets )
        {
            initializePresets();
            
            if( preset.getType() != IPreset.Type.USER_DEFINED )
            {
                return false;
            }
            
            deleted = this.presets.removeItemByKey( preset.getId() );
            
            if( deleted )
            {
                saveUserPresets();
            }
        }

        if( deleted )
        {
            final IFacetedProjectFrameworkEvent event 
                = new FacetedProjectFrameworkEvent( IFacetedProjectFrameworkEvent.Type.PRESET_REMOVED );
            
            this.frameworkListenerRegistry.notifyListeners( event );
        }
        
        return deleted;
    }
    
    private void initializePresets()
    {
        synchronized( this.presets )
        {
            if( ! this.presetsInitialized )
            {
                for( IPreset preset : PresetsExtensionPoint.getPresets() )
                {
                    this.presets.addItemWithKey( preset.getId(), preset );
                }
                
                readUserPresets();
                
                this.presetsInitialized = true;
            }
        }
    }
    
    private void saveUserPresets()
    {
        try
        {
            final Preferences root = getUserPresetsPreferences();
            
            final String[] children = root.childrenNames();
            
            for( int i = 0; i < children.length; i++ )
            {
                root.node( children[ i ] ).removeNode();
            }
            
            for( IPreset preset : this.presets.getItemSet() )
            {
                if( preset.getType() == IPreset.Type.USER_DEFINED )
                {
                    final Preferences pnode = root.node( preset.getId() );
                    pnode.put( EL_LABEL, preset.getLabel() );
                    pnode.put( EL_DESCRIPTION, preset.getDescription() );
                    
                    int counter = 1;
                    
                    for( IProjectFacetVersion fv : preset.getProjectFacets() )
                    {
                        final Preferences fnode = pnode.node( String.valueOf( counter ) );
                        
                        fnode.put( ATTR_ID, fv.getProjectFacet().getId() );
                        fnode.put( ATTR_VERSION, fv.getVersionString() );
                        
                        counter++;
                    }
                }
            }
        
            root.flush();
        }
        catch( BackingStoreException e )
        {
            FacetCorePlugin.log( e );
        }
    }
    
    private void readUserPresets()
    {
        try
        {
            final Preferences root = getUserPresetsPreferences();
            final String[] pkeys = root.childrenNames();
            
            for( int i = 0; i < pkeys.length; i++ )
            {
                final Preferences pnode = root.node( pkeys[ i ] );
                final String label = pnode.get( EL_LABEL, null );
                
                if( label == null )
                {
                    break;
                }

                String description = pnode.get( EL_DESCRIPTION, null );
                
                if( description == null )
                {
                    description = ""; //$NON-NLS-1$
                }
                
                final String[] fkeys = pnode.childrenNames();
                Set<IProjectFacetVersion> facets = new HashSet<IProjectFacetVersion>();
                
                for( int j = 0; j < fkeys.length; j++ )
                {
                    final Preferences fnode = pnode.node( fkeys[ j ] );
                    final String id = fnode.get( ATTR_ID, null );
                    final String version = fnode.get( ATTR_VERSION, null );
                    
                    if( id == null || version == null )
                    {
                        facets = null;
                        break;
                    }
                    
                    if( isProjectFacetDefined( id ) )
                    {
                        final IProjectFacet f = getProjectFacet( id );
                        
                        if( f.hasVersion( version ) )
                        {
                            facets.add( f.getVersion( version ) );
                        }
                        else
                        {
                            facets = null;
                            break;
                        }
                    }
                    else
                    {
                        facets = null;
                        break;
                    }
                }

                if( facets != null )
                {
                    definePreset( label, description, facets, false );
                }
            }
        }
        catch( BackingStoreException e )
        {
            FacetCorePlugin.log( e );
        }
    }
    
    private static Preferences getUserPresetsPreferences()
    {
        final InstanceScope scope = new InstanceScope();
        
        final IEclipsePreferences pluginRoot 
            = scope.getNode( FacetCorePlugin.PLUGIN_ID );
        
        return pluginRoot.node( "user.presets" ); //$NON-NLS-1$
    }
    
    public Set<IFacetedProjectTemplate> getTemplates()
    {
        return FacetedProjectTemplatesExtensionPoint.getTemplates();
    }
    
    public boolean isTemplateDefined( final String id )
    {
        return ( FacetedProjectTemplatesExtensionPoint.getTemplate( id ) != null );
    }
    
    public IFacetedProjectTemplate getTemplate( final String id )
    {
        final IFacetedProjectTemplate template 
            = FacetedProjectTemplatesExtensionPoint.getTemplate( id );
        
        if( template == null )
        {
            final String msg = NLS.bind( Resources.templateNotDefined, id );
            throw new IllegalArgumentException( msg );
        }
        
        return template;
    }
    
    public Set<IGroup> getGroups()
    {
        return this.groups.getItemSet();
    }
    
    public boolean isGroupDefined( final String id )
    {
        return this.groups.containsKey( id );
    }
    
    public IGroup getGroup( final String id )
    {
        final IGroup group = this.groups.getItemByKey( id );
        
        if( group == null )
        {
            final String msg = NLS.bind( Resources.groupNotDefined, id );
            throw new IllegalArgumentException( msg );
        }
        
        return group;
    }
    
    void addGroup( final IGroup group )
    {
        this.groups.addItemWithKey( group.getId(), group );
    }
    
    public Set<IFacetedProject> getFacetedProjects()
    
        throws CoreException
        
    {
        return getFacetedProjects( null, null );
    }

    public Set<IFacetedProject> getFacetedProjects( final IProjectFacet f )
    
        throws CoreException
        
    {
        return getFacetedProjects( f, null );
    }

    public Set<IFacetedProject> getFacetedProjects( final IProjectFacetVersion fv )
    
        throws CoreException
        
    {
        return getFacetedProjects( null, fv );
    }

    private Set<IFacetedProject> getFacetedProjects( final IProjectFacet f,
                                                     final IProjectFacetVersion fv )
    
        throws CoreException
        
    {
        final IProject[] all 
            = ResourcesPlugin.getWorkspace().getRoot().getProjects();
        
        final Set<IFacetedProject> result = new HashSet<IFacetedProject>();
        
        for( int i = 0; i < all.length; i++ )
        {
            final IProject proj = all[ i ];
            final IFacetedProject fproj = create( proj );
            
            if( fproj != null )
            {
                if( ( f != null && ! fproj.hasProjectFacet( f ) ) ||
                    ( fv != null && ! fproj.hasProjectFacet( fv ) ) )
                {
                    continue;
                }
                else
                {
                    result.add( fproj );
                }
            }
        }
        
        return result;
    }
    
    public IFacetedProjectWorkingCopy createNewProject()
    {
        return new FacetedProjectWorkingCopy( null );
    }

    public IFacetedProject create( final IProject project )
    
        throws CoreException
        
    {
        if( project.isAccessible() &&
            project.isNatureEnabled( FacetedProjectNature.NATURE_ID ) )
        {
            FacetedProject fproj = null;
            
            synchronized( this.projects )
            {
                fproj = this.projects.get( project.getName() );
                
                if( fproj == null )
                {
                    fproj = new FacetedProject( project );
                    this.projects.put( project.getName(), fproj );
                }
            }

            fproj.refresh();
            
            return fproj;
        }

        return null;
    }

    public IFacetedProject create( final IProject project,
                                   final boolean convertIfNecessary,
                                   final IProgressMonitor monitor)
    
        throws CoreException
        
    {
        if( monitor != null )
        {
            monitor.beginTask( "", 1 ); //$NON-NLS-1$
        }
        
        try
        {
            if( project.isAccessible() &&
                ! project.isNatureEnabled( FacetedProjectNature.NATURE_ID ) && 
                convertIfNecessary )
            {
                final IProjectDescription description = project.getDescription();
                final String[] prevNatures = description.getNatureIds();
                final String[] newNatures = new String[ prevNatures.length + 1 ];
                System.arraycopy( prevNatures, 0, newNatures, 0, prevNatures.length );
                newNatures[ prevNatures.length ] = FacetedProjectNature.NATURE_ID;
                description.setNatureIds( newNatures );
                
                validateEdit( project.getFile( FILE_DOT_PROJECT ) );
                
                project.setDescription( description, submon( monitor, 1 ) );
            }
            
            return create( project );
        }
        finally
        {
            if( monitor != null )
            {
                monitor.done();
            }
        }
    }
    
    public IFacetedProject create( final String name,
                                   final IPath location,
                                   final IProgressMonitor monitor )
    
        throws CoreException
        
    {
        if( monitor != null )
        {
            monitor.beginTask( "", 2 ); //$NON-NLS-1$
        }
        
        try
        {
            final IWorkspace ws = ResourcesPlugin.getWorkspace();
            final IProject project = ws.getRoot().getProject( name );
            
            final IProjectDescription desc
                = ws.newProjectDescription( name );
    
            desc.setLocation( location );
                    
            project.create( desc, submon( monitor, 1 ) );
            project.open( submon( monitor, 1 ) );
            
            // This is odd, but apparently nature's configure() method will only
            // be called if the setDescription() method is used. It will not be
            // called if nature is added to the project description prior to
            // calling IProject.create() method.
            
            desc.setNatureIds( new String[] { FacetedProjectNature.NATURE_ID } );
            project.setDescription( desc, null );
            
            return create( project );
        }
        finally
        {
            if( monitor != null )
            {
                monitor.done();
            }
        }
    }
    
    public void addListener( final IFacetedProjectListener listener,
                             final IFacetedProjectEvent.Type... types )
    {
        this.projectListenerRegistry.addListener( listener, types );
    }
    
    public void addListener( final IFacetedProjectFrameworkListener listener,
                             final IFacetedProjectFrameworkEvent.Type... types )
    {
        this.frameworkListenerRegistry.addListener( listener, types );
    }
    
    public void removeListener( final IFacetedProjectListener listener )
    {
        this.projectListenerRegistry.removeListener( listener );
    }
    
    public void removeListener( final IFacetedProjectFrameworkListener listener )
    {
        this.frameworkListenerRegistry.removeListener( listener );
    }
    
    ProjectListenerRegistry getProjectListenerRegistry()
    {
        return this.projectListenerRegistry;
    }
    
    public IStatus check( final Set<IProjectFacetVersion> base,
                          final Set<Action> actions )
    {
        MultiStatus result = Constraint.createMultiStatus();
        
        // Verify that all of the actions are supported.
        
        for( Action action : actions )
        {
            if( ! action.getProjectFacetVersion().supports( base, action.getType() ) )
            {
                final ValidationProblem.Type ptype;
                
                if( action.getType() == Action.Type.INSTALL )
                {
                    ptype = ValidationProblem.Type.INSTALL_NOT_SUPPORTED;
                }
                else if( action.getType() == Action.Type.UNINSTALL )
                {
                    ptype = ValidationProblem.Type.UNINSTALL_NOT_SUPPORTED;
                }
                else if( action.getType() == Action.Type.VERSION_CHANGE )
                {
                    ptype = ValidationProblem.Type.VERSION_CHANGE_NOT_SUPPORTED;
                }
                else
                {
                    throw new IllegalStateException();
                }
                
                final IProjectFacetVersion fv = action.getProjectFacetVersion();
                
                final ValidationProblem vp
                    = new ValidationProblem( ptype, 
                                             fv.getProjectFacet().getLabel(),
                                             fv.getVersionString() );
                
                result.add( vp );
            }
        }
        
        // Multiple actions on the same facet are not supported in the same
        // batch. The only exception is an uninstall of a previosly-installed
        // version followed by an install of a new version.
        
        final Map<IProjectFacet,Set<Action>> facetToActionsMap 
            = new HashMap<IProjectFacet,Set<Action>>();
        
        for( Action action : actions )
        {
            final IProjectFacet f = action.getProjectFacetVersion().getProjectFacet();
            Set<Action> group = facetToActionsMap.get( f );
            
            if( group == null )
            {
                group = new HashSet<Action>();
                facetToActionsMap.put( f, group );
            }
            
            group.add( action );
        }
        
        for( Set<Action> group : facetToActionsMap.values() )
        {
            if( group.size() > 1 )
            {
                boolean bad = true;
                
                if( group.size() == 2 )
                {
                    Action install = null;
                    Action uninstall = null;
                    
                    for( Action action : group )
                    {
                        if( action.getType() == Action.Type.INSTALL )
                        {
                            install = action;
                        }
                        else if( action.getType() == Action.Type.UNINSTALL )
                        {
                            uninstall = action;
                        }
                        else
                        {
                            break;
                        }
                    }
                    
                    if( install != null && uninstall != null )
                    {
                        if( base.contains( uninstall.getProjectFacetVersion() ) )
                        {
                            bad = false;
                        }
                    }
                }
                
                if( bad )
                {
                    final ValidationProblem.Type ptype 
                        = ValidationProblem.Type.MULTIPLE_ACTIONS_NOT_SUPPORTED;
                    
                    result.add( new ValidationProblem( ptype ) );
                    
                    break;
                }
            }
        }
        
        // Check for attempts to uninstall or change version of facets that
        // haven't been installed. Also check for attempts to install a facet
        // that's already installed.
        
        for( Action action : actions )
        {
            final IProjectFacetVersion fv = action.getProjectFacetVersion();
            final IProjectFacet f = fv.getProjectFacet();

            ValidationProblem.Type ptype = null;
            
            if( action.getType() == Action.Type.UNINSTALL )
            {
                if( ! base.contains( fv ) )
                {
                    ptype = ValidationProblem.Type.CANNOT_UNINSTALL;
                }
            }
            else
            {
                IProjectFacetVersion existing = null;
                
                for( IProjectFacetVersion temp : base )
                {
                    if( temp.getProjectFacet() == f )
                    {
                        existing = temp;
                        break;
                    }
                }
                
                if( action.getType() == Action.Type.VERSION_CHANGE && existing == null )
                {
                    ptype = ValidationProblem.Type.CANNOT_CHANGE_VERSION;
                }
                else if( action.getType() == Action.Type.INSTALL && existing != null )
                {
                    // this is nearly useless to the end user
                    ptype = ValidationProblem.Type.FACET_ALREADY_INSTALLED;
                }
            }
            
            if( ptype != null )
            {
                result.add( new ValidationProblem( ptype, f.getLabel(),
                                                   fv.getVersionString() ) );
            }
        }
        
        // Abort at this point if there are any validation problems.
        
        if( ! result.isOK() )
        {
            return result;
        }
        
        // Apply all the uninstall actions.
        
        final Set<IProjectFacetVersion> all = new HashSet<IProjectFacetVersion>( base );
        
        for( Action action : actions )
        {
            if( action.getType() == Action.Type.UNINSTALL )
            {
                apply( all, action );
            }
        }
        
        // Apply all the install and version change actions.
        
        for( Action action : actions )
        {
            if( action.getType() != Action.Type.UNINSTALL )
            {
                apply( all, action );
            }
        }
        
        // Check the constrains on all of the facets.
        
        for( IProjectFacetVersion fv : all )
        {
            final IConstraint constraint = fv.getConstraint();
            
            if( constraint != null )
            {
                final IStatus st = constraint.check( all );
                
                if( ! st.isOK() )
                {
                    result.addAll( st );
                }
            }
        }
        
        // Eliminate symmetric conflicts problem entries.
        
        final Set<IStatus> problems = new HashSet<IStatus>();
        IStatus[] children = result.getChildren();
        
        for( IStatus child : children )
        {
            problems.add( child );
        }
        
        final Set<IStatus> toremove = new HashSet<IStatus>();

        for( IStatus problem : problems )
        {
            if( ! toremove.contains( problem ) )
            {
                final ValidationProblem valprob = (ValidationProblem) problem;
                
                if( valprob.getType() == ValidationProblem.Type.CONFLICTS )
                {
                    final Object[] p = valprob.getParameters();
                    
                    final ValidationProblem reverse
                        = new ValidationProblem( ValidationProblem.Type.CONFLICTS,
                                                 new Object[] { p[ 1 ], p[ 0 ] } );
                    
                    toremove.add( reverse );
                }
            }
        }
        
        if( toremove.size() > 0 )
        {
            problems.removeAll( toremove );
            children = problems.toArray( new IStatus[ problems.size() ] );
            result = Constraint.createMultiStatus( children );
        }
        
        // Return the problems to the caller.
        
        return result;
    }
    
    public void sort( final Set<IProjectFacetVersion> base,
                      final List<Action> actions )
    {
        final int count = actions.size();
        
        if( count == 0 )
        {
            return;
        }
        
        // Before sorting, check that the constraints can be met. Otherwise
        // the sort algorithm will not terminate.
        
        final IStatus st = check( base, new HashSet<Action>( actions ) );
        
        if( ! st.isOK() )
        {
            FacetCorePlugin.log( st );
            return;
        }
        
        // Initialize tracing.
        
        List<Action> unsorted = null;
        int steps = 0;
        
        if( FacetCorePlugin.isTracingActionSorting() )
        {
            unsorted = new ArrayList<Action>( actions );
        }
        
        // Step 1 : Pre-sort all uninstall actions to the front of the list. 
        //          Within that order, sort actions based on facet id. The
        //          secondary sort assures a stable sort order among actions on
        //          unrelated facets.
        
        final Comparator<Action> comp = new Comparator<Action>()
        {
            public int compare( final Action a1, 
                                final Action a2 )
            {
                int res = compare( a1.getType(), a2.getType() );
                
                if( res == 0 )
                {
                    final String fid1 
                        = a1.getProjectFacetVersion().getProjectFacet().getId();
                    
                    final String fid2 
                        = a2.getProjectFacetVersion().getProjectFacet().getId();
                    
                    res = fid1.compareTo( fid2 );
                }
                
                return res;
            }
            
            private int compare( final Action.Type t1,
                                 final Action.Type t2 )
            {
                if( t1 == t2 )
                {
                    return 0;
                }
                else if( t1 == Action.Type.UNINSTALL )
                {
                    return -1;
                }
                else if( t2 == Action.Type.UNINSTALL )
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
        };
        
        Collections.sort( actions, comp );
        
        // Step 2 : Sort based on the constraints.
        
        final Set<IProjectFacetVersion> fnl = new HashSet<IProjectFacetVersion>( base );
        
        for( Action action : actions )
        {
            apply( fnl, action );
        }
        
        boolean makeAnotherPass = true;
        
        while( makeAnotherPass )
        {
            makeAnotherPass = false;
            
            Set<IProjectFacetVersion> state = new HashSet<IProjectFacetVersion>( base );
            
            for( int i = 0; i < count; )
            {
                final Action action = actions.get( i );
                final Action.Type type = action.getType();
                final IProjectFacetVersion fv = action.getProjectFacetVersion();
                final IConstraint constraint = fv.getConstraint();
                
                if( type == Action.Type.UNINSTALL )
                {
                    if( ! constraint.check( state, true ).isOK() &&
                        constraint.check( base, true ).isOK() )
                    {
                        moveToFront( actions, i );
                        makeAnotherPass = true;
                        steps++;
                        break;
                    }
                    else
                    {
                        apply( state, action );
                        i++;
                    }
                }
                else
                {
                    if( constraint.check( state ).isOK() &&
                        ! ( ! constraint.check( state, true ).isOK() &&
                            constraint.check( fnl, true ).isOK() ) )
                    {
                        apply( state, action );
                        i++;
                    }
                    else
                    {
                        moveToEnd( actions, i );
                        steps++;
                    }
                }
            }
        }
        
        // Output tracing information.
        
        if( FacetCorePlugin.isTracingActionSorting() )
        {
            final String text
                = Resources.bind( Resources.tracingActionSorting,
                                  toString( base ), toString( unsorted ),
                                  toString( actions ), String.valueOf( steps ) );
            
            System.out.println( text );
        }
    }
    
    static void apply( final Set<IProjectFacetVersion> facets,
                       final Action action )
    {
        final Action.Type type = action.getType();
        final IProjectFacetVersion fv = action.getProjectFacetVersion();
        
        if( type == Action.Type.INSTALL )
        {
            facets.add( fv );
        }
        else if( type == Action.Type.UNINSTALL )
        {
            facets.remove( fv );
        }
        else if( type == Action.Type.VERSION_CHANGE )
        {
            for( IProjectFacetVersion x : facets )
            {
                if( x.getProjectFacet() == fv.getProjectFacet() )
                {
                    facets.remove( x );
                    break;
                }
            }
            
            facets.add( fv );
        }
    }
    
    public synchronized Preferences getPreferences( final IProjectFacet facet )
    
        throws BackingStoreException
        
    {
        ProjectFacetPreferencesGroup group = null;
        
        if( this.globalPreferencesGroup != null )
        {
            group = this.globalPreferencesGroup.get();
        }
        
        if( group == null )
        {
            group = new ProjectFacetPreferencesGroup( null );
            this.globalPreferencesGroup = new WeakReference<ProjectFacetPreferencesGroup>( group );
        }
        
        return group.getPreferences( facet );
    }
    
    public synchronized Preferences getPreferences( final IProjectFacet facet,
                                                    final IFacetedProject project )
    
        throws BackingStoreException
        
    {
        final String pjname = project.getProject().getName();
        ProjectFacetPreferencesGroup group = null;
        WeakReference<ProjectFacetPreferencesGroup> ref = this.projectPreferencesGroups.get( pjname );
        
        if( ref != null )
        {
            group = ref.get();
        }
        
        if( group == null )
        {
            group = new ProjectFacetPreferencesGroup( project );
            ref = new WeakReference<ProjectFacetPreferencesGroup>( group );
            this.projectPreferencesGroups.put( pjname, ref );
        }
        
        return group.getPreferences( facet );
    }
    
    private static IProgressMonitor submon( final IProgressMonitor monitor,
                                            final int ticks )
    {
        if( monitor == null )
        {
            return null;
        }
        else
        {
            return new SubProgressMonitor( monitor, ticks );
        }
    }
    
    private static void moveToFront( final List<Action> actions,
                                     final int index )
    {
        final Action action = actions.get( index );
        
        for( int i = index; i > 0; i-- )
        {
            actions.set( i, actions.get( i - 1 ) );
        }
        
        actions.set( 0, action );
    }
    
    private static void moveToEnd( final List<Action> actions,
                                   final int index )
    {
        final Action action = actions.get( index );
        
        for( int i = index + 1, n = actions.size(); i < n; i++ )
        {
            actions.set( i - 1, actions.get( i ) );
        }
        
        actions.set( actions.size() - 1, action );
    }
    
    private void readMetadata()
    {
        final IExtensionRegistry registry = Platform.getExtensionRegistry();
        
        final IExtensionPoint point 
            = registry.getExtensionPoint( FacetCorePlugin.PLUGIN_ID, 
                                          EXTENSION_ID );
        
        if( point == null )
        {
            throw new RuntimeException( "Extension point not found!" ); //$NON-NLS-1$
        }
        
        final List<IConfigurationElement> cfgels = new ArrayList<IConfigurationElement>();
        
        for( IExtension extension : point.getExtensions() )
        {
            for( IConfigurationElement cfgel : extension.getConfigurationElements() )
            {
                cfgels.add( cfgel );
            }
        }
        
        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_CATEGORY ) )
            {
                try
                {
                    readCategory( config );
                }
                catch( InvalidExtensionException e )
                {
                    // Continue. The problem has been reported in the log.
                }
            }
        }
        
        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_PROJECT_FACET ) )
            {
                try
                {
                    readProjectFacet( config );
                }
                catch( InvalidExtensionException e )
                {
                    // Continue. The problem has been reported in the log.
                }
            }
        }
        
        final Map<ProjectFacetVersion,IConfigurationElement> fvToConstraint 
            = new HashMap<ProjectFacetVersion,IConfigurationElement>();
        
        final Map<ProjectFacetVersion,List<IConfigurationElement>> fvToActions 
            = new HashMap<ProjectFacetVersion,List<IConfigurationElement>>();
        
        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_PROJECT_FACET_VERSION ) )
            {
                readProjectFacetVersion( config, fvToConstraint, fvToActions );
            }
        }
        
        calculateVersionComparisonTables( fvToConstraint, fvToActions );
        
        ProjectFacetGroupsExtensionPoint.processExtensions( this );        
        
        for( Map.Entry<ProjectFacetVersion,IConfigurationElement> x : fvToConstraint.entrySet() )
        {
            readConstraint( x.getValue(), x.getKey() );
        }
        
        for( Map.Entry<ProjectFacetVersion,List<IConfigurationElement>> x : fvToActions.entrySet() )
        {
            final ProjectFacetVersion fv = x.getKey();
            final List<IConfigurationElement> actions = x.getValue();
            
            for( IConfigurationElement config : actions )
            {
                readAction( config, (ProjectFacet) fv.getProjectFacet(), fv.getVersionString() );
            }
        }

        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_ACTION ) )
            {
                readAction( config );
            }
            else if( config.getName().equals( EL_EVENT_HANDLER ) )
            {
                readEventHandler( config );
            }
        }
        
        for( IConfigurationElement config : cfgels )
        {
            if( config.getName().equals( EL_PROJECT_FACET ) )
            {
                readDefaultVersionInfo( config );
            }
        }
    }
    
    private void readCategory( final IConfigurationElement config )
    
        throws InvalidExtensionException
        
    {
        final Category category = new Category();
        category.setId( findRequiredAttribute( config, ATTR_ID ) );
        category.setPluginId( config.getContributor().getName() );

        final IConfigurationElement elLabel = findOptionalElement( config, EL_LABEL );
        category.setLabel( getElementValue( elLabel, category.getId() ) );
        
        final IConfigurationElement elDesc = findOptionalElement( config, EL_DESCRIPTION );
        category.setDescription( getElementValue( elDesc, DEFAULT_DESCRIPTION ) );
        
        this.categories.addItemWithKey( category.getId(), category );
    }
    
    private void readProjectFacet( final IConfigurationElement config )
    
        throws InvalidExtensionException
        
    {
        final ProjectFacet f = new ProjectFacet();
        f.setId( findRequiredAttribute( config, ATTR_ID ) );
        f.setPluginId( config.getContributor().getName() );
        
        final IConfigurationElement elLabel = findOptionalElement( config, EL_LABEL );
        f.setLabel( getElementValue( elLabel, f.getId() ) );
        
        final IConfigurationElement elDesc = findOptionalElement( config, EL_DESCRIPTION );
        f.setDescription( getElementValue( elDesc, DEFAULT_DESCRIPTION ) );

        final IConfigurationElement elComp = findOptionalElement( config, EL_VERSION_COMPARATOR );
        
        if( elComp != null )
        {
            f.setVersionComparator( findRequiredAttribute( elComp, ATTR_CLASS ) );
        }
        
        final IConfigurationElement[] children = config.getChildren();
        
        for( int i = 0; i < children.length; i++ )
        {
            final IConfigurationElement child = children[ i ];
            final String childName = child.getName();
            
            if( childName.equals( EL_PROPERTY ) )
            {
                final String name = child.getAttribute( ATTR_NAME );
    
                if( name == null )
                {
                    reportMissingAttribute( child, ATTR_NAME );
                    continue;
                }
    
                final String value = child.getAttribute( ATTR_VALUE );
                
                if( value == null )
                {
                    reportMissingAttribute( child, ATTR_VALUE );
                    continue;
                }
                
                Object parsedValue = value;
                
                if( name.equals( IProjectFacet.PROP_HIDE_VERSION ) )
                {
                    parsedValue = Boolean.parseBoolean( value );
                }

                f.setProperty( name, parsedValue );
            }
        }
        
        String catname = null;
        
        final IConfigurationElement elMember = findOptionalElement( config, EL_MEMBER );
        
        if( elMember != null )
        {
            catname = findRequiredAttribute( elMember, ATTR_CATEGORY );
        }
        
        // ## DEPRECATED : 2.0 ##
        {
            final IConfigurationElement elCategory = findOptionalElement( config, EL_CATEGORY );
            
            if( elCategory != null )
            {
                catname = getElementValue( elCategory, null );
            }
        }
        
        if( catname != null )
        {
            if( isCategoryDefined( catname ) )
            {
                final Category category = (Category) getCategory( catname );
                
                f.setCategory( category );
                category.addProjectFacet( f );
            }
            else
            {
                final String msg
                    = NLS.bind( Resources.categoryNotDefined, catname ) +
                      NLS.bind( Resources.usedInPlugin, config.getContributor().getName() );
                
                FacetCorePlugin.log( msg );
            }
        }
        
        this.facets.addItem( f );
        this.facets.addKey( f.getId(), f );
        
        for( String alias : ProjectFacetAliasesExtensionPoint.getAliases( f ) )
        {
            this.facets.addKey( alias, f );
            f.addAlias( alias );
        }
    }
    
    private void readProjectFacetVersion( final IConfigurationElement config,
                                          final Map<ProjectFacetVersion,IConfigurationElement> fvToConstraint,
                                          final Map<ProjectFacetVersion,List<IConfigurationElement>> fvToActions )
    {
        final String fid = config.getAttribute( ATTR_FACET );

        if( fid == null )
        {
            reportMissingAttribute( config, ATTR_FACET );
            return;
        }
        
        final String ver = config.getAttribute( ATTR_VERSION );

        if( ver == null )
        {
            reportMissingAttribute( config, ATTR_VERSION );
            return;
        }
        
        final ProjectFacet f = (ProjectFacet) this.facets.getItemByKey( fid );
        
        if( f == null )
        {
            ProblemLog.reportMissingFacet( fid, config.getContributor().getName() );
            return;
        }
        
        final ProjectFacetVersion fv
            = new ProjectFacetVersion();
        
        fv.setProjectFacet( f );
        fv.setVersionString( ver );
        fv.setPluginId( config.getContributor().getName() );
        
        final List<IConfigurationElement> actions = new ArrayList<IConfigurationElement>();
        fvToActions.put( fv, actions );
        
        final IConfigurationElement[] children = config.getChildren();
        
        for( int i = 0; i < children.length; i++ )
        {
            final IConfigurationElement child = children[ i ];
            final String childName = child.getName();
            
            if( childName.equals( EL_CONSTRAINT ) )
            {
                fvToConstraint.put( fv, child );
            }
            else if( childName.equals( EL_ACTION ) )
            {
                actions.add( child );
            }
            else if( childName.equals( EL_PROPERTY ) )
            {
                final String name = child.getAttribute( ATTR_NAME );
    
                if( name == null )
                {
                    reportMissingAttribute( child, ATTR_NAME );
                    continue;
                }
    
                final String value = child.getAttribute( ATTR_VALUE );
                
                if( value == null )
                {
                    reportMissingAttribute( child, ATTR_VALUE );
                    continue;
                }
                
                fv.setProperty( name, value );
            }
        }
        
        f.addVersion( fv );

        // This has to happen after facet version is registered.
        
        for( int i = 0; i < children.length; i++ )
        {
            final IConfigurationElement child = children[ i ];
            final String childName = child.getName();
            
            if( childName.equals( EL_EVENT_HANDLER ) )
            {
                readEventHandler( child, f, ver );
            }
        }
    }
    
    /**
     * Pre-computes the tables that describe how versions of a facet compare
     * to each other. This allows the IProjectFacetVersion.compareTo() operation,
     * which is called rather frequently, to be reduced to a hash table lookup
     * instead of having to do a parse and comparison of two version strings.
     */
    
    private void calculateVersionComparisonTables( final Map<ProjectFacetVersion,IConfigurationElement> fvToConstraint,
                                                   final Map<ProjectFacetVersion,List<IConfigurationElement>> fvToActions )
    {
        final List<IProjectFacet> badFacets = new ArrayList<IProjectFacet>();
        
        for( IProjectFacet f : this.facets.getItemSet() )
        {
            try
            {
                final Comparator<String> comp = f.getVersionComparator();
                
                final List<IProjectFacetVersion> versions 
                    = new ArrayList<IProjectFacetVersion>( f.getVersions() );
                
                final Map<IProjectFacetVersion,Map<IProjectFacetVersion,Integer>> compTables
                    = new HashMap<IProjectFacetVersion,Map<IProjectFacetVersion,Integer>>();
                
                for( IProjectFacetVersion fv : versions )
                {
                    compTables.put( fv, new HashMap<IProjectFacetVersion,Integer>() );
                }
                
                for( int i = 0, n = versions.size(); i < n; i++ )
                {
                    final IProjectFacetVersion iVer = versions.get( i );
                    final String iVerStr = iVer.getVersionString();
                    final Map<IProjectFacetVersion,Integer> iCompTable = compTables.get( iVer );
                    
                    for( int j = i + 1; j < n; j++ )
                    {
                        final IProjectFacetVersion jVer = versions.get( j );
                        final String jVerStr = jVer.getVersionString();
                        final Map<IProjectFacetVersion,Integer> jCompTable = compTables.get( jVer );
                        
                        final int result = comp.compare( iVerStr, jVerStr );
                        
                        iCompTable.put( jVer, new Integer( result ) );
                        jCompTable.put( iVer, new Integer( result * -1 ) );
                    }
                }
                
                for( Map.Entry<IProjectFacetVersion,Map<IProjectFacetVersion,Integer>> entry
                     : compTables.entrySet() )
                {
                    final ProjectFacetVersion fv = (ProjectFacetVersion) entry.getKey();
                    fv.setComparisonTable( entry.getValue() );
                }
            }
            catch( Exception e )
            {
                // The failure here is due to the problem loading the provided
                // version comparator or due to the problem comparing the
                // version string. In either case, we log the exception and
                // remove all traces of this facet from the system to keep a
                // faulty facet from dragging down the entire framework.
                
                FacetCorePlugin.log( e );
                badFacets.add( f );
            }
        }
        
        for( IProjectFacet f : badFacets )
        {
            this.facets.removeItem( f );
            
            final Category category = (Category) f.getCategory();
            
            if( category != null )
            {
                category.removeProjectFacet( f );
            }
            
            for( IProjectFacetVersion fv : f.getVersions() )
            {
                fvToConstraint.remove( fv );
                fvToActions.remove( fv );
            }
        }
    }
    
    private void readDefaultVersionInfo( final IConfigurationElement config )
    {
        final String id = config.getAttribute( ATTR_ID );

        if( id == null || ! isProjectFacetDefined( id ) )
        {
            // The error should have already been reported, don't need to log
            // this again.
            
            return;
        }
        
        final ProjectFacet f = (ProjectFacet) getProjectFacet( id );
        boolean defaultVersionSpecified = false;

        final IConfigurationElement[] children = config.getChildren();
        
        for( int i = 0; i < children.length; i++ )
        {
            final IConfigurationElement child = children[ i ];
            final String childName = child.getName();
            
            if( childName.equals( EL_DEFAULT_VERSION ) )
            {
                final String clname = child.getAttribute( ATTR_PROVIDER );
                
                if( clname != null )
                {
                    final IDefaultVersionProvider defaultVersionProvider
                        = instantiate( f.getPluginId(), clname, IDefaultVersionProvider.class );

                    if( defaultVersionProvider != null )
                    {
                        f.setDefaultVersionProvider( defaultVersionProvider );
                        defaultVersionSpecified = true;
                    }
                }
                else
                {
                    final String version = child.getAttribute( ATTR_VERSION );
                    
                    if( version != null )
                    {
                        if( f.hasVersion( version ) )
                        {
                            f.setDefaultVersion( f.getVersion( version ) );
                            defaultVersionSpecified = true;
                        }
                        else
                        {
                            ProblemLog.reportMissingFacetVersion( f, version, config.getContributor().getName() );
                        }
                    }
                    else
                    {
                        reportMissingAttribute( config, ATTR_VERSION );
                    }
                }
            }
        }
        
        if( ! defaultVersionSpecified )
        {
            try
            {
                f.setDefaultVersion( f.getLatestVersion() );
            }
            catch( Exception e )
            {
                FacetCorePlugin.log( e );
            }
        }
    }
    
    private void readAction( final IConfigurationElement config )
    {
        final String fid = config.getAttribute( ATTR_FACET );

        if( fid == null )
        {
            reportMissingAttribute( config, ATTR_FACET );
            return;
        }
        
        final ProjectFacet f = (ProjectFacet) this.facets.getItemByKey( fid );
        
        if( f == null )
        {
            ProblemLog.reportMissingFacet( fid, config.getContributor().getName() );
            return;
        }
        
        String ver = config.getAttribute( ATTR_VERSION );

        if( ver == null )
        {
            ver = IVersionExpr.WILDCARD_SYMBOL;
        }
        
        readAction( config, f, ver );
    }

    private void readAction( final IConfigurationElement config,
                             final ProjectFacet f,
                             final String version )
    {
        final String pluginId = config.getContributor().getName();
        final ActionDefinition def = new ActionDefinition();
        
        def.setPluginId( pluginId );
        
        final String type = config.getAttribute( ATTR_TYPE );
        
        if( type == null )
        {
            reportMissingAttribute( config, ATTR_TYPE );
            return;
        }
        
        // Backwards compatibility of deprecated functionality.
        
        if( type.equals( "runtime-changed" ) ) //$NON-NLS-1$
        {
            final String msg
                = NLS.bind( Resources.deprecatedRuntimeChangedAction, pluginId );
            
            FacetCorePlugin.logWarning( msg, true );
            
            readEventHandler( config, f, version );
            
            return;
        }
        
        // End of backwards compatibility code.
        
        def.setActionType( Action.Type.valueOf( type ) ); 

        if( def.getActionType() == null )
        {
            final String msg
                = NLS.bind( Resources.invalidActionType, type ) +
                  NLS.bind( Resources.usedInPlugin, pluginId );
            
            FacetCorePlugin.log( msg );
            
            return;
        }
        
        try
        {
            def.setVersionExpr( new VersionExpr<ProjectFacetVersion>( f, version, pluginId ) );
        }
        catch( CoreException e )
        {
            FacetCorePlugin.log( e );
            return;
        }

        final IConfigurationElement[] children = config.getChildren();
        
        for( int i = 0; i < children.length; i++ )
        {
            final IConfigurationElement child = children[ i ];
            final String childName = child.getName();
            
            if( childName.equals( EL_CONFIG_FACTORY ) )
            {
                final String clname = child.getAttribute( ATTR_CLASS );
                
                if( clname == null )
                {
                    reportMissingAttribute( child, ATTR_CLASS );
                    return;
                }
                
                def.setConfigFactoryClassName( clname );
            }
            else if( childName.equals( EL_DELEGATE ) )
            {
                final String clname = child.getAttribute( ATTR_CLASS );
                
                if( clname == null )
                {
                    reportMissingAttribute( config, ATTR_CLASS );
                    return;
                }
                
                def.setDelegateClassName( clname );
            }
            else if( childName.equals( EL_PROPERTY ) )
            {
                final String name = child.getAttribute( ATTR_NAME );

                if( name == null )
                {
                    reportMissingAttribute( child, ATTR_NAME );
                    return;
                }

                final String value = child.getAttribute( ATTR_VALUE );
                
                if( value == null )
                {
                    reportMissingAttribute( child, ATTR_VALUE );
                    return;
                }
                
                Object parsedValue = value;
                
                if( name.equals( IActionDefinition.PROP_FROM_VERSIONS ) )
                {
                    try
                    {
                        parsedValue = new VersionExpr<ProjectFacetVersion>( f, value, pluginId );
                    }
                    catch( CoreException e )
                    {
                        FacetCorePlugin.log( e );
                        return;
                    }
                }

                def.setProperty( name, parsedValue );
            }
        }
        
        String id = config.getAttribute( ATTR_ID );
        
        if( id == null )
        {
            final StringBuffer buf = new StringBuffer();
            
            buf.append( f.getId() );
            buf.append( '#' );
            buf.append( version );
            buf.append( '#' );
            buf.append( def.getActionType().name() );

            for( Map.Entry<String,Object> entry : def.getProperties().entrySet() )
            {
                buf.append( '#' );
                buf.append( entry.getKey() );
                buf.append( '=' );
                buf.append( entry.getValue().toString() );
            }
            
            id = buf.toString();
        }
        
        def.setId( id );
        
        if( isActionDefined( id ) )
        {
            final String msg
                = NLS.bind( Resources.actionAlreadyDefined, id, pluginId );
            
            FacetCorePlugin.logError( msg );
        }
        else
        {
            this.actions.addItemWithKey( def.getId(), def );
            f.addActionDefinition( def );
        }
    }
    
    private void readEventHandler( final IConfigurationElement config )
    {
        final String fid = config.getAttribute( ATTR_FACET );

        if( fid == null )
        {
            reportMissingAttribute( config, ATTR_FACET );
            return;
        }
        
        final ProjectFacet f = (ProjectFacet) this.facets.getItemByKey( fid );
        
        if( f == null )
        {
            ProblemLog.reportMissingFacet( fid, config.getContributor().getName() );
            return;
        }
        
        String ver = config.getAttribute( ATTR_VERSION );

        if( ver == null )
        {
            ver = IVersionExpr.WILDCARD_SYMBOL;
        }
        
        readEventHandler( config, f, ver );
    }
    
    /**
     * Support for a deprecated extension point.
     */

    private void readEventHandler( final IConfigurationElement config,
                                   final ProjectFacet f,
                                   final String version )
    {
        final String pluginId = config.getContributor().getName();
        
        final String type = config.getAttribute( ATTR_TYPE );
        
        if( type == null )
        {
            reportMissingAttribute( config, ATTR_TYPE );
            return;
        }
        
        final IFacetedProjectEvent.Type t;
        
        if( type.equals( "runtime-changed" ) || type.equals( "RUNTIME_CHANGED" )) //$NON-NLS-1$ //$NON-NLS-2$
        {
            t = IFacetedProjectEvent.Type.PRIMARY_RUNTIME_CHANGED;
        }
        else
        {
            t = IFacetedProjectEvent.Type.valueOf( type );
        }
        
        if( t == null )
        {
            final String msg
                = NLS.bind( Resources.invalidEventHandlerType, type ) +
                  NLS.bind( Resources.usedInPlugin, pluginId );
            
            FacetCorePlugin.log( msg );
            
            return;
        }
        
        final IVersionExpr vexpr;
        
        try
        {
            vexpr = new VersionExpr<ProjectFacetVersion>( f, version, pluginId );
        }
        catch( CoreException e )
        {
            FacetCorePlugin.log( e );
            return;
        }
        
        String delegateClassName = null;

        final IConfigurationElement[] children = config.getChildren();
        
        for( int i = 0; i < children.length; i++ )
        {
            final IConfigurationElement child = children[ i ];
            final String childName = child.getName();
            
            if( childName.equals( EL_DELEGATE ) )
            {
                final String clname = child.getAttribute( ATTR_CLASS );
                
                if( clname == null )
                {
                    reportMissingAttribute( config, ATTR_CLASS );
                    return;
                }
                
                delegateClassName = clname;
            }
        }
        
        if( delegateClassName == null )
        {
            reportMissingElement( config, EL_DELEGATE );
            return;
        }
        
        final LegacyEventHandlerAdapter adapter
            = new LegacyEventHandlerAdapter( f, vexpr, pluginId, delegateClassName );
        
        addListener( adapter, t );
    }
    
    private void readConstraint( final IConfigurationElement config,
                                 final ProjectFacetVersion fv )
    {
        final ProblemLog.Policy problemLoggingPolicy 
            = ProblemLog.Policy.createBasedOnIgnoreProblemsAttr( config );

        final IConfigurationElement[] ops = config.getChildren();
        final List<IConstraint> parsed = new ArrayList<IConstraint>();
        
        for( int j = 0; j < ops.length; j++ )
        {
            final IConstraint op = readConstraintHelper( ops[ j ], fv, problemLoggingPolicy );
            
            if( op != null )
            {
                parsed.add( op );
            }
        }
        
        if( parsed.size() == 1 )
        {
            fv.setConstraint( parsed.get( 0 ) );
        }
        else if( parsed.size() > 1 )
        {
            final IConstraint and 
                = new Constraint( fv, IConstraint.Type.AND, 
                                  parsed.toArray() );
            
            fv.setConstraint( and );
        }
    }
    
    private IConstraint readConstraintHelper( final IConfigurationElement root,
                                              final ProjectFacetVersion fv,
                                              final ProblemLog.Policy parentProblemLoggingPolicy )
    {
        final String pluginId = root.getContributor().getName();
        
        final ProblemLog.Policy localProblemLoggingPolicy 
            = ProblemLog.Policy.createBasedOnIgnoreProblemsAttr( root, parentProblemLoggingPolicy );
        
        final IConstraint.Type type
            = IConstraint.Type.valueOf( root.getName() );
        
        final Object[] operands;
     
        if( type == IConstraint.Type.AND ||
            type == IConstraint.Type.OR )
        {
            final IConfigurationElement[] children = root.getChildren();
            final List<Object> operandsList = new ArrayList<Object>( children.length );
            
            for( int i = 0; i < children.length; i++ )
            {
                final IConstraint operand 
                    = readConstraintHelper( children[ i ], fv, localProblemLoggingPolicy );
                
                if( operand != null )
                {
                    operandsList.add( operand );
                }
                else
                {
                    if( type == IConstraint.Type.AND )
                    {
                        return null;
                    }
                }
            }
            
            operands = operandsList.toArray();
        }
        else if( type == IConstraint.Type.REQUIRES ||
                 type == IConstraint.Type.CONFLICTS )
        {
            final String gid = root.getAttribute( ATTR_GROUP );
            final String fid = root.getAttribute( ATTR_FACET );
            String vexprstr = root.getAttribute( ATTR_VERSION );
            
            final String softStr = root.getAttribute( ATTR_SOFT );
            Boolean soft = Boolean.FALSE;
            
            if( softStr != null && softStr.equals( Boolean.TRUE.toString() ) )
            {
                soft = Boolean.TRUE;
            }
            
            if( gid != null && ( fid != null || vexprstr != null ) )
            {
                final String template
                    = type == IConstraint.Type.REQUIRES
                      ? Resources.invalidRequiresConstraint
                      : Resources.invalidConflictsConstraint;
                
                final String msg = NLS.bind( template, pluginId );
                
                FacetCorePlugin.logError( msg, true );
                return null;
            }
            else if( gid != null )
            {
                if( ! isGroupDefined( gid ) )
                {
                    ProblemLog.reportMissingGroup( gid, pluginId, localProblemLoggingPolicy );
                    return null;
                }
                
                final IGroup group = getGroup( gid );
                
                if( type == IConstraint.Type.REQUIRES )
                {
                    operands = new Object[] { group, soft };
                }
                else
                {
                    operands = new Object[] { group };
                }
            }
            else if( fid != null )
            {
                if( ! isProjectFacetDefined( fid ) )
                {
                    ProblemLog.reportMissingFacet( fid, pluginId, localProblemLoggingPolicy );
                    return null;
                }
                
                final IProjectFacet f = getProjectFacet( fid );

                VersionExpr vexpr = null;
                
                try
                {
                    if( vexprstr == null || vexprstr.trim().length() == 0 )
                    {
                        vexprstr = IVersionExpr.WILDCARD_SYMBOL;
                    }
                    
                    vexpr = new VersionExpr( f, vexprstr, pluginId );
                }
                catch( CoreException e )
                {
                    FacetCorePlugin.log( e );
                    return null;
                }
                
                if( type == IConstraint.Type.REQUIRES )
                {
                    operands = new Object[] { f, vexpr, soft };
                }
                else
                {
                    operands = new Object[] { f, vexpr };
                }
            }
            else
            {
                final String msg
                    = Resources.bind( Resources.missingOneOfTwoAttributes,
                                      pluginId, root.getName(), ATTR_GROUP,
                                      ATTR_FACET );
                
                FacetCorePlugin.logError( msg, true );
                return null;
            }
        }
        else
        {
            throw new IllegalStateException();
        }
        
        return new Constraint( fv, type, operands );
    }
    
    private static String toString( final Collection<? extends Object> collection )
    {
        final StringBuffer buf = new StringBuffer();
        
        for( Object obj : collection )
        {
            if( buf.length() > 0 )
            {
                buf.append( ", " ); //$NON-NLS-1$
            }
            
            if( obj instanceof IProjectFacetVersion )
            {
                final IProjectFacetVersion fv = (IProjectFacetVersion) obj;
                
                buf.append( fv.getProjectFacet().getId() );
                buf.append( ' ' );
                buf.append( fv.getVersionString() );
            }
            else
            {
                buf.append( obj.toString() );
            }
        }
        
        return buf.toString();
    }
    
    private final class ResourceChangeListener
    
        implements IResourceChangeListener
        
    {
        public void register()
        {
            final IWorkspace ws = ResourcesPlugin.getWorkspace();
            ws.addResourceChangeListener( this, IResourceChangeEvent.POST_CHANGE );
        }
        
        public void resourceChanged( final IResourceChangeEvent event )
        {
            final IResourceDelta delta = event.getDelta();
            final List<FacetedProject> projectsToRefresh = new ArrayList<FacetedProject>();
            
            synchronized( FacetedProjectFrameworkImpl.this.projects )
            {
                for( IResourceDelta subdelta : delta.getAffectedChildren( IResourceDelta.REMOVED ) )
                {
                    final String pjname = subdelta.getFullPath().segment( 0 );
                    
                    final IFacetedProject fpj 
                        = FacetedProjectFrameworkImpl.this.projects.remove( pjname );
                    
                    if( fpj != null )
                    {
                        try
                        {
                            ( (FacetedProject) fpj ).markDeleted();
                        }
                        catch( CoreException e )
                        {
                            FacetCorePlugin.log( e );
                        }
                    }
                }
                
                for( FacetedProject fproj : FacetedProjectFrameworkImpl.this.projects.values() )
                {
                    final IResourceDelta subdelta = delta.findMember( fproj.f.getFullPath() );
                    
                    if( subdelta != null )
                    {
                        projectsToRefresh.add( fproj );
                    }
                }
            }
            
            for( FacetedProject fproj : projectsToRefresh )
            {
                try
                {
                    fproj.refresh();
                }
                catch( CoreException e )
                {
                    FacetCorePlugin.log( e );
                }
            }
        }
    }

    public static final class Resources
    
        extends NLS
        
    {
        public static String missingOneOfTwoAttributes;
        public static String categoryNotDefined;
        public static String facetNotDefined;
        public static String facetVersionNotDefined;
        public static String actionNotDefined;
        public static String actionAlreadyDefined;
        public static String groupNotDefined;
        public static String presetNotDefined;
        public static String templateNotDefined;
        public static String usedInPlugin;
        public static String invalidActionType;
        public static String invalidEventHandlerType;
        public static String invalidRequiresConstraint;
        public static String invalidConflictsConstraint;
        public static String deprecatedRuntimeChangedAction;
        public static String tracingActionSorting;
        public static String tracingFrameworkActivationStarting;
        public static String tracingFrameworkActivationFinished;
        
        static
        {
            initializeMessages( FacetedProjectFrameworkImpl.class.getName(), 
                                Resources.class );
        }
        
        public static String bind( final String template,
                                   final Object arg1,
                                   final Object arg2,
                                   final Object arg3 )
        {
            return NLS.bind( template, new Object[] { arg1, arg2, arg3 } );
        }

        public static String bind( final String template,
                                   final Object arg1,
                                   final Object arg2,
                                   final Object arg3,
                                   final Object arg4 )
        {
            return NLS.bind( template, new Object[] { arg1, arg2, arg3, arg4 } );
        }
    }
    
}
