    001    /*****************************************************************************
    002     * Copyright (C) PicoContainer Organization. All rights reserved.            *
    003     * ------------------------------------------------------------------------- *
    004     * The software in this package is published under the terms of the BSD      *
    005     * style license a copy of which has been included with this distribution in *
    006     * the LICENSE.txt file.                                                     *
    007     *****************************************************************************/
    008
    009    package org.picocontainer.gems.constraints;
    010
    011    import org.picocontainer.ComponentAdapter;
    012    import org.picocontainer.NameBinding;
    013    import org.picocontainer.PicoContainer;
    014    import org.picocontainer.PicoCompositionException;
    015    import org.picocontainer.Parameter;
    016    import org.picocontainer.injectors.AbstractInjector;
    017    import org.picocontainer.parameters.CollectionComponentParameter;
    018
    019    import java.lang.reflect.Array;
    020    import java.lang.reflect.Type;
    021    import java.lang.annotation.Annotation;
    022    import java.util.Map;
    023
    024    /**
    025     * Base class for parameter constraints.
    026     *
    027     * @author Nick Sieger
    028     */
    029    public abstract class AbstractConstraint extends CollectionComponentParameter implements Constraint {
    030
    031        /** Construct an AbstractContraint. */
    032        protected AbstractConstraint() {
    033            super(false);
    034        }
    035
    036        @Override
    037            public Resolver resolve(final PicoContainer container,
    038                             final ComponentAdapter<?> forAdapter,
    039                             ComponentAdapter<?> injecteeAdapter, final Type expectedType,
    040                             final NameBinding expectedNameBinding, final boolean useNames, final Annotation binding) throws PicoCompositionException {
    041            final Resolver resolver;
    042            return new Parameter.DelegateResolver(super.resolve(container, forAdapter,
    043                    null, getArrayType((Class) expectedType), expectedNameBinding, useNames, binding)) {
    044                @Override
    045                public Object resolveInstance() {
    046                    final Object[] array = (Object[]) super.resolveInstance();
    047                    if (array.length == 1) {
    048                        return array[0];
    049                    }
    050                    return null;
    051                }
    052            };
    053        }
    054
    055        @Override
    056            public void verify(final PicoContainer container,
    057                           final ComponentAdapter<?> adapter,
    058                           final Type expectedType,
    059                           final NameBinding expectedNameBinding, final boolean useNames, final Annotation binding) throws PicoCompositionException {
    060            super.verify(container, adapter, getArrayType((Class) expectedType), expectedNameBinding, useNames, binding);
    061        }
    062
    063        @Override
    064            public abstract boolean evaluate(ComponentAdapter adapter);
    065
    066        @Override
    067            protected Map<Object, ComponentAdapter<?>> getMatchingComponentAdapters(final PicoContainer container,
    068                                                                                final ComponentAdapter adapter,
    069                                                                                final Class keyType,
    070                                                                                final Class valueType) {
    071            final Map<Object, ComponentAdapter<?>> map =
    072                super.getMatchingComponentAdapters(container, adapter, keyType, valueType);
    073            if (map.size() > 1) {
    074                throw new AbstractInjector.AmbiguousComponentResolutionException(valueType, map.keySet().toArray(new Object[map.size()]));
    075            }
    076            return map;
    077        }
    078
    079        private Type getArrayType(final Class expectedType) {
    080            return Array.newInstance(expectedType, 0).getClass();
    081        }
    082    }