001/*
002 *  Copyright 2010, 2011 Chris Pheby
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.jadira.bindings.core.spring;
017
018import java.lang.annotation.Annotation;
019import java.util.HashSet;
020import java.util.Set;
021
022import org.jadira.bindings.core.annotation.BindingScope;
023import org.jadira.bindings.core.annotation.DefaultBinding;
024import org.jadira.bindings.core.binder.BasicBinder;
025import org.jadira.bindings.core.binder.ConverterKey;
026import org.springframework.core.convert.TypeDescriptor;
027import org.springframework.core.convert.converter.ConditionalGenericConverter;
028
029/**
030 * Implementation of Spring's {@link ConditionalGenericConverter} that makes use
031 * of Jadira Binding to perform conversions.
032 */
033public class BindingConverter implements ConditionalGenericConverter {
034
035    private static final BasicBinder BINDING = new BasicBinder();
036    
037    /**
038     * {@inheritDoc}
039     */
040    /* @Override */
041    public Set<ConvertiblePair> getConvertibleTypes() {
042        
043        Set<ConvertiblePair> result = new HashSet<ConvertiblePair>();
044        
045                Iterable<ConverterKey<?,?>> entries = BINDING.getConverterEntries();
046        for (ConverterKey<?,?> next : entries) {
047            result.add(new ConvertiblePair(next.getInputClass(), next.getOutputClass()));
048        }
049        
050        return result;
051    }
052
053    /**
054     * {@inheritDoc}
055     */
056    /* @Override */
057    public Object convert(Object object, TypeDescriptor sourceType, TypeDescriptor targetType) {
058        
059        final Object result;
060        result = BINDING.convertTo(object.getClass(), targetType.getObjectType(), object, matchAnnotationToScope(targetType.getAnnotations()));
061        return result;
062    }
063
064    /**
065     * {@inheritDoc}
066     */
067    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
068
069        try {
070            BINDING.findConverter(sourceType.getObjectType(), targetType.getObjectType(), matchAnnotationToScope(targetType.getAnnotations()));
071            return true;
072        } catch (IllegalStateException e) {
073            return false;
074        }       
075    }
076    
077    /**
078     * Helper method for matching and returning a scope annotation 
079     * @param annotations Annotations to inspect for a scope annotation
080     * @return The matched annotation
081     */
082    private <T> Class<? extends Annotation> matchAnnotationToScope(Annotation[] annotations) {
083
084        for (Annotation next : annotations) {
085            Class<? extends Annotation> nextType = next.annotationType();
086            if (nextType.getAnnotation(BindingScope.class) != null) {
087                return nextType;
088            }
089        }
090        return DefaultBinding.class;
091    }
092}