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    }