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 }