    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.injectors.AbstractInjector;
    016    import org.picocontainer.parameters.CollectionComponentParameter;
    017
    018    import java.lang.reflect.Array;
    019    import java.lang.reflect.Type;
    020    import java.lang.annotation.Annotation;
    021    import java.util.Map;
    022
    023    /**
    024     * Base class for parameter constraints.
    025     *
    026     * @author Nick Sieger
    027     */
    028    public abstract class AbstractConstraint extends CollectionComponentParameter implements Constraint {
    029
    030        /** Construct an AbstractContraint. */
    031        protected AbstractConstraint() {
    032            super(false);
    033        }
    034
    035        @Override
    036            public Object resolveInstance(final PicoContainer container,
    037                                      final ComponentAdapter<?> adapter,
    038                                      final Type expectedType,
    039                                      final NameBinding expectedNameBinding, final boolean useNames, final Annotation binding) throws PicoCompositionException
    040        {
    041            final Object[] array =
    042                (Object[])super.resolveInstance(container, adapter, getArrayType((Class) expectedType), expectedNameBinding,
    043                                                useNames, null);
    044            if (array.length == 1) {
    045                return array[0];
    046            }
    047            return null;
    048        }
    049
    050        @Override
    051            public boolean isResolvable(final PicoContainer container,
    052                                    final ComponentAdapter<?> adapter,
    053                                    final Type expectedType,
    054                                    final NameBinding expectedNameBinding, final boolean useNames, final Annotation binding) throws PicoCompositionException
    055        {
    056            return super.isResolvable(container, adapter, getArrayType((Class) expectedType), expectedNameBinding, useNames,
    057                                      binding);
    058        }
    059
    060        @Override
    061            public void verify(final PicoContainer container,
    062                           final ComponentAdapter<?> adapter,
    063                           final Type expectedType,
    064                           final NameBinding expectedNameBinding, final boolean useNames, final Annotation binding) throws PicoCompositionException
    065        {
    066            super.verify(container, adapter, getArrayType((Class) expectedType), expectedNameBinding, useNames, binding);
    067        }
    068
    069        @Override
    070            public abstract boolean evaluate(ComponentAdapter adapter);
    071
    072        @Override
    073            protected Map<Object, ComponentAdapter<?>> getMatchingComponentAdapters(final PicoContainer container,
    074                                                                                final ComponentAdapter adapter,
    075                                                                                final Class keyType,
    076                                                                                final Class valueType)
    077        {
    078            final Map<Object, ComponentAdapter<?>> map =
    079                super.getMatchingComponentAdapters(container, adapter, keyType, valueType);
    080            if (map.size() > 1) {
    081                throw new AbstractInjector.AmbiguousComponentResolutionException(valueType, map.keySet().toArray(new Object[map.size()]));
    082            }
    083            return map;
    084        }
    085
    086        private Type getArrayType(final Class expectedType) {
    087            return Array.newInstance(expectedType, 0).getClass();
    088        }
    089    }