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