/*******************************************************************************
 * Copyright (c) 2010, 2013 Sonatype, 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:
 *    Stuart McCulloch (Sonatype, Inc.) - initial API and implementation
 *******************************************************************************/
package org.eclipse.sisu.plexus;

import java.util.Map;

import org.codehaus.plexus.component.annotations.Component;
import org.eclipse.sisu.BeanScanning;
import org.eclipse.sisu.space.ClassSpace;
import org.eclipse.sisu.space.SpaceModule;
import org.eclipse.sisu.space.SpaceVisitor;

import com.google.inject.Binder;

/**
 * {@link PlexusBeanModule} that registers Plexus beans by scanning classes for runtime annotations.
 */
public final class PlexusAnnotatedBeanModule
    implements PlexusBeanModule
{
    // ----------------------------------------------------------------------
    // Constants
    // ----------------------------------------------------------------------

    private static final SpaceModule.Strategy PLEXUS_STRATEGY = new SpaceModule.Strategy()
    {
        public SpaceVisitor visitor( final Binder binder )
        {
            return new PlexusTypeVisitor( new PlexusTypeBinder( binder ) );
        }
    };

    // ----------------------------------------------------------------------
    // Implementation fields
    // ----------------------------------------------------------------------

    private final ClassSpace space;

    private final Map<?, ?> variables;

    private final BeanScanning scanning;

    // ----------------------------------------------------------------------
    // Constructors
    // ----------------------------------------------------------------------

    /**
     * Creates a bean source that scans the given class space for Plexus annotations using the given scanner.
     * 
     * @param space The local class space
     * @param variables The filter variables
     */
    public PlexusAnnotatedBeanModule( final ClassSpace space, final Map<?, ?> variables )
    {
        this( space, variables, BeanScanning.ON );
    }

    /**
     * Creates a bean source that scans the given class space for Plexus annotations using the given scanner.
     * 
     * @param space The local class space
     * @param variables The filter variables
     * @param scanning The scanning options
     */
    public PlexusAnnotatedBeanModule( final ClassSpace space, final Map<?, ?> variables, final BeanScanning scanning )
    {
        this.space = space;
        this.variables = variables;
        this.scanning = scanning;
    }

    // ----------------------------------------------------------------------
    // Public methods
    // ----------------------------------------------------------------------

    public PlexusBeanSource configure( final Binder binder )
    {
        if ( null != space && scanning != BeanScanning.OFF )
        {
            new SpaceModule( space, scanning ).with( PLEXUS_STRATEGY ).configure( binder );
        }
        return new PlexusAnnotatedBeanSource( variables );
    }

    // ----------------------------------------------------------------------
    // Implementation types
    // ----------------------------------------------------------------------

    private static final class PlexusAnnotatedBeanSource
        implements PlexusBeanSource
    {
        private final PlexusBeanMetadata metadata;

        PlexusAnnotatedBeanSource( final Map<?, ?> variables )
        {
            metadata = new PlexusAnnotatedMetadata( variables );
        }

        public PlexusBeanMetadata getBeanMetadata( final Class<?> implementation )
        {
            return implementation.isAnnotationPresent( Component.class ) ? metadata : null;
        }
    }
}

@@ -855,16 +855,49 @@
 .Binder;
+%0Aimport com.google.inject.Module;
 %0A%0A/**%0A *
@@ -1720,64 +1720,26 @@
 nal 
-ClassSpace space;%0A%0A    private final Map%3C?, ?%3E variab
+Module spaceModu
 le
-s
 ;%0A%0A 
@@ -1755,37 +1755,43 @@
 e final 
-BeanScanning scanning
+PlexusBeanSource beanSource
 ;%0A%0A    /
@@ -2739,62 +2739,220 @@
     
-this.space = space;%0A        this.variab
+if ( null != space && scanning != BeanScanning.OFF )%0A        %7B%0A            spaceModule = new SpaceModule( space, scanning ).with( PLEXUS_STRATEGY );%0A        %7D%0A        else%0A        %7B%0A            spaceModu
 le
-s
  = 
-variables
+null
 ;%0A  
@@ -2961,32 +2961,73 @@
     
-this.scanning = scanning
+%7D%0A        beanSource = new PlexusAnnotatedBeanSource( variables )
 ;%0A  
@@ -3307,40 +3307,14 @@
 pace
- && scanning != BeanScanning.OFF
+Module
  )%0A 
@@ -3334,21 +3334,17 @@
         
-new S
+s
 paceModu
@@ -3349,51 +3349,8 @@
 dule
-( space, scanning ).with( PLEXUS_STRATEGY )
 .con
@@ -3396,50 +3396,18 @@
 urn 
-new PlexusAnnotatedBeanSource( variables )
+beanSource
 ;%0A  

Move construction from configure into constructor