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 ******************************************************************************/
008package org.picocontainer.parameters;
009
010import java.io.Serializable;
011import java.lang.annotation.Annotation;
012import java.lang.reflect.Type;
013
014import org.picocontainer.ComponentAdapter;
015import org.picocontainer.NameBinding;
016import org.picocontainer.PicoCompositionException;
017import org.picocontainer.PicoContainer;
018import 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")
029public 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}