/*
 * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode;

import com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation.MethodPool;
import com.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.simulation.MethodSimulator;
import com.sebastian_daschner.jaxrs_analyzer.model.Types;
import com.sebastian_daschner.jaxrs_analyzer.model.elements.Element;
import com.sebastian_daschner.jaxrs_analyzer.model.elements.HttpResponse;
import com.sebastian_daschner.jaxrs_analyzer.model.elements.JsonValue;
import com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction;
import com.sebastian_daschner.jaxrs_analyzer.model.methods.ProjectMethod;
import com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult;

import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * Analyzes JAX-RS resource methods. This class is thread-safe.
 *
 * @author Sebastian Daschner
 */
class ResourceMethodContentAnalyzer extends MethodContentAnalyzer {

    private final Lock lock = new ReentrantLock();

    /**
     * Analyzes the method (including own project methods).
     *
     * @param methodResult The method result
     */
    void analyze(final MethodResult methodResult) {
        lock.lock();
        try {
            buildPackagePrefix(methodResult.getParentResource().getOriginalClass());

            final List<Instruction> visitedInstructions = interpretRelevantInstructions(methodResult.getInstructions());

            // find project defined methods in invoke occurrences
            final Set<ProjectMethod> projectMethods = findProjectMethods(visitedInstructions);

            // add project methods to global method pool
            projectMethods.forEach(MethodPool.getInstance()::addProjectMethod);

            Element returnedElement = new MethodSimulator().simulate(visitedInstructions);
            final String returnType = methodResult.getOriginalMethodSignature().getReturnType();

            // void resource methods are interpreted later; stop analyzing on error
            if (Types.PRIMITIVE_VOID.equals(returnType)) {
                return;
            }

            if (returnedElement == null) {
                // happens for abstract methods or if there is no return
                return;
            }

            final Set<Object> possibleObjects = returnedElement.getPossibleValues().stream().filter(o -> !(o instanceof HttpResponse))
                    .collect(Collectors.toSet());

            // for non-Response methods add a default if there are non-Response objects or none objects at all
            if (!Types.RESPONSE.equals(returnType)) {
                final HttpResponse defaultResponse = new HttpResponse();

                if (Types.OBJECT.equals(returnType))
                    defaultResponse.getEntityTypes().addAll(returnedElement.getTypes());
                else
                    defaultResponse.getEntityTypes().add(returnType);

                possibleObjects.stream().filter(o -> o instanceof JsonValue).map(o -> (JsonValue) o).forEach(defaultResponse.getInlineEntities()::add);

                methodResult.getResponses().add(defaultResponse);
            }

            // add Response results as well
            returnedElement.getPossibleValues().stream().filter(o -> o instanceof HttpResponse).map(o -> (HttpResponse) o).forEach(methodResult.getResponses()::add);
        } finally {
            lock.unlock();
        }
    }

}

@@ -3818,24 +3818,121 @@
 s()::add);%0A%0A
+                defaultResponse.getContentTypes().addAll(methodResult.getResponseMediaTypes());%0A%0A
             

Return type is not picked up correctly? #134