001/*
002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     dmetzler
016 */
017package org.nuxeo.runtime.mockito;
018
019import java.lang.annotation.Annotation;
020import java.lang.reflect.Field;
021import java.util.HashMap;
022import java.util.Map;
023
024import org.mockito.Captor;
025import org.mockito.Mock;
026import org.mockito.MockitoAnnotations;
027import org.mockito.exceptions.Reporter;
028import org.mockito.internal.configuration.CaptorAnnotationProcessor;
029import org.mockito.internal.configuration.DefaultAnnotationEngine;
030import org.mockito.internal.configuration.FieldAnnotationProcessor;
031import org.mockito.internal.configuration.MockitoAnnotationsMockAnnotationProcessor;
032
033/**
034 * Unfortunately, since there are some private methos in the Mockito DefaultAnnotationEngine we have to copy/paste some
035 * original code to insert our own logic.
036 *
037 * @since 5.7.8
038 */
039public class NuxeoDefaultAnnotationEngine extends DefaultAnnotationEngine {
040
041    private final Map<Class<? extends Annotation>, FieldAnnotationProcessor<?>> annotationProcessorMap = new HashMap<Class<? extends Annotation>, FieldAnnotationProcessor<?>>();
042
043    public NuxeoDefaultAnnotationEngine() {
044        registerAnnotationProcessor(Mock.class, new NuxeoServiceMockAnnotationProcessor());
045        registerAnnotationProcessor(MockitoAnnotations.Mock.class, new MockitoAnnotationsMockAnnotationProcessor());
046        registerAnnotationProcessor(Captor.class, new CaptorAnnotationProcessor());
047
048    }
049
050    /*
051     * (non-Javadoc)
052     * @see org.mockito.AnnotationEngine#createMockFor(java.lang.annotation.Annotation , java.lang.reflect.Field)
053     */
054    @Override
055    @SuppressWarnings("deprecation")
056    public Object createMockFor(Annotation annotation, Field field) {
057        return forAnnotation(annotation).process(annotation, field);
058    }
059
060    private <A extends Annotation> FieldAnnotationProcessor<A> forAnnotation(A annotation) {
061        if (annotationProcessorMap.containsKey(annotation.annotationType())) {
062            return (FieldAnnotationProcessor<A>) annotationProcessorMap.get(annotation.annotationType());
063        }
064        return new FieldAnnotationProcessor<A>() {
065            @Override
066            public Object process(A annotation, Field field) {
067                return null;
068            }
069        };
070    }
071
072    private <A extends Annotation> void registerAnnotationProcessor(Class<A> annotationClass,
073            FieldAnnotationProcessor<A> fieldAnnotationProcessor) {
074        annotationProcessorMap.put(annotationClass, fieldAnnotationProcessor);
075    }
076
077    void throwIfAlreadyAssigned(Field field, boolean alreadyAssigned) {
078        if (alreadyAssigned) {
079            new Reporter().moreThanOneAnnotationNotAllowed(field.getName());
080        }
081    }
082}