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 }