/*
 *  Copyright (c) 2017 Touch Instinct
 *
 *  This file is part of RoboSwag library.
 *
 *  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/LICENSE-2.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 ru.touchin.templates.retrofit;

import android.support.annotation.NonNull;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.SocketException;
import java.util.Collection;
import java.util.Map;

import javax.net.ssl.SSLException;

import okhttp3.ResponseBody;
import okhttp3.internal.http2.StreamResetException;
import retrofit2.Converter;
import ru.touchin.roboswag.core.log.Lc;
import ru.touchin.templates.ApiModel;

/**
 * Created by Gavriil Sitnikov on 14/02/2017.
 * Object to deserialize responses of remote requests from Retrofit.
 *
 * @param <T> Type of response object.
 */
public abstract class JsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {

    @SuppressWarnings("PMD.AvoidInstanceofChecksInCatchClause")
    //AvoidInstanceofChecksInCatchClause: we just don't need assertion on specific exceptions
    @NonNull
    @Override
    public T convert(@NonNull final ResponseBody value) throws IOException {
        final T result;
        try {
            result = parseResponse(value);
        } catch (final IOException exception) {
            if (!(exception instanceof SocketException)
                    && !(exception instanceof InterruptedIOException)
                    && !(exception instanceof SSLException)
                    && !(exception instanceof StreamResetException)) {
                Lc.assertion(exception);
            }
            throw exception;
        } finally {
            value.close();
        }

        if (result instanceof ApiModel) {
            try {
                ((ApiModel) result).validate();
            } catch (final ApiModel.ValidationException validationException) {
                Lc.assertion(validationException);
                throw validationException;
            }
        }
        if (result instanceof Collection) {
            try {
                ApiModel.validateCollection((Collection) result, getValidateCollectionRule());
            } catch (final ApiModel.ValidationException validationException) {
                Lc.assertion(validationException);
                throw validationException;
            }
        }
        if (result instanceof Map) {
            try {
                ApiModel.validateCollection(((Map) result).values(), getValidateCollectionRule());
            } catch (final ApiModel.ValidationException validationException) {
                Lc.assertion(validationException);
                throw validationException;
            }
        }

        return result;
    }

    @NonNull
    protected ApiModel.CollectionValidationRule getValidateCollectionRule() {
        return ApiModel.CollectionValidationRule.EXCEPTION_IF_ANY_INVALID;
    }

    /**
     * Parses response to specific object.
     *
     * @param value Response to parse;
     * @return Parsed object;
     * @throws IOException Throws during parsing.
     */
    @NonNull
    protected abstract T parseResponse(@NonNull ResponseBody value) throws IOException;

}
@@ -2216,140 +2216,148 @@
     
-try %7B%0A                ((ApiModel) result).validate();%0A            %7D catch (final ApiModel.ValidationException validationException) %7B
+validateModel((ApiModel) result);%0A        %7D%0A        if (result instanceof Collection) %7B%0A            validateCollection((Collection) result);
 %0A   
@@ -2357,32 +2357,34 @@
 t);%0A        
+%7D%0A
         
 Lc.assertion
@@ -2375,84 +2375,91 @@
     
-Lc.assertion(validationException);%0A                throw validationException
+if (result instanceof Map) %7B%0A            validateCollection(((Map)result).values())
 ;%0A  
@@ -2468,65 +2468,122 @@
     
+%7D%0A%0A
     
-%7D%0A
     
+return result;%0A
     %7D%0A
+%0A
     
-    if (result instanceof Collec
+private void validateModel(@NonNull final ApiModel result) throws IOExcep
 tion
-)
  %7B%0A 
@@ -2581,36 +2581,32 @@
 ption %7B%0A        
-    
 try %7B%0A          
@@ -2611,95 +2611,27 @@
     
-    ApiModel.validateCollection((Collection) result, getValidateCollectionRul
+result.validat
 e()
-)
 ;%0A
-    
     
@@ -2693,36 +2693,32 @@
 ionException) %7B%0A
-    
             Lc.a
@@ -2752,36 +2752,32 @@
 n);%0A            
-    
 throw validation
@@ -2799,65 +2799,108 @@
     
-    
 %7D%0A    
- 
-   
 %7D
+%0A
 %0A    
-    if (result instanceof Map) %7B%0A    
+private void validateCollection(@NonNull final Collection result) throws IOException %7B%0A
     
@@ -2921,20 +2921,16 @@
         
-    
 ApiModel
@@ -2953,31 +2953,14 @@
 ion(
-((Map) result).values()
+result
 , ge
@@ -2983,28 +2983,24 @@
 ionRule());%0A
-    
         %7D ca
@@ -3066,36 +3066,32 @@
 ) %7B%0A            
-  
-  
 Lc.assertion(val
@@ -3113,36 +3113,32 @@
 n);%0A            
-    
 throw validation
@@ -3160,47 +3160,9 @@
     
-   
- %7D%0A        %7D%0A%0A        return result;
+%7D
 %0A   

fix static