001    /*******************************************************************************
002     * Copyright (C) PicoContainer Organization. All rights reserved. 
003     * ---------------------------------------------------------------------------
004     * The software in this package is published under the terms of the BSD style
005     * license a copy of which has been included with this distribution in the
006     * LICENSE.txt file. 
007     ******************************************************************************/
008    package org.picocontainer.parameters;
009    
010    import java.io.Serializable;
011    import java.lang.annotation.Annotation;
012    import java.lang.reflect.Type;
013    
014    import org.picocontainer.ComponentAdapter;
015    import org.picocontainer.NameBinding;
016    import org.picocontainer.PicoCompositionException;
017    import org.picocontainer.PicoContainer;
018    import org.picocontainer.PicoVisitor;
019    
020    /**
021     * Once in a great while, you actually want to pass in 'null' as an argument.  Instead
022     * of bypassing the type checking mechanisms available in 
023     * {@link org.picocontainer.parameters.ConstantParameter ConstantParameter}, we provide a  <em>Special Type</em>
024     * geared to marking nulls.
025     * @author Michael Rimov
026     *
027     */
028    @SuppressWarnings("serial")
029    public class NullParameter extends AbstractParameter implements Serializable {
030    
031            /**
032             * The one and only instance of null parameter.
033             */
034            public static final NullParameter INSTANCE = new NullParameter();
035            
036            /**
037             * Only once instance of Null parameter needed.
038             */
039            protected NullParameter() {
040            }
041    
042            /**
043             * {@inheritDoc}
044             * @see org.picocontainer.Parameter#accept(org.picocontainer.PicoVisitor)
045             */
046            public void accept(PicoVisitor visitor) {
047                    visitor.visitParameter(this);
048            }
049    
050            /**
051             * {@inheritDoc}
052             * @see org.picocontainer.Parameter#resolve(org.picocontainer.PicoContainer, org.picocontainer.ComponentAdapter, org.picocontainer.ComponentAdapter, java.lang.reflect.Type, org.picocontainer.NameBinding, boolean, java.lang.annotation.Annotation)
053             */
054            public Resolver resolve(PicoContainer container,
055                            ComponentAdapter<?> forAdapter,
056                            ComponentAdapter<?> injecteeAdapter, Type expectedType,
057                            NameBinding expectedNameBinding, boolean useNames,
058                            Annotation binding) {
059                    return new ValueResolver(isAssignable(expectedType), null, null);
060            }
061    
062            /**
063             * {@inheritDoc}
064             * @see org.picocontainer.Parameter#verify(org.picocontainer.PicoContainer, org.picocontainer.ComponentAdapter, java.lang.reflect.Type, org.picocontainer.NameBinding, boolean, java.lang.annotation.Annotation)
065             */
066            public void verify(PicoContainer container, ComponentAdapter<?> adapter,
067                            Type expectedType, NameBinding expectedNameBinding,
068                            boolean useNames, Annotation binding) {
069                    if (!isAssignable(expectedType)) {
070                            throw new PicoCompositionException(expectedType + " cannot be assigned a null value");
071                    }
072            }
073            
074            /**
075             * Nulls cannot be assigned to primitives.
076             * @param expectedType
077             * @return
078             */
079        protected boolean isAssignable(Type expectedType) {
080            if (expectedType instanceof Class<?>) {
081                Class<?> expectedClass = Class.class.cast(expectedType);
082                if (expectedClass.isPrimitive()) {
083                    return false;
084                }
085            }
086            return true;
087        }
088            
089            
090    }