/*
 * Copyright 2019 VicTools.
 *
 * 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 com.github.victools.jsonschema.module.swagger15;

import com.github.victools.jsonschema.generator.ConfigFunction;
import com.github.victools.jsonschema.generator.FieldScope;
import com.github.victools.jsonschema.generator.MethodScope;
import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder;
import com.github.victools.jsonschema.generator.SchemaGeneratorConfigPart;
import com.github.victools.jsonschema.generator.SchemaGeneratorGeneralConfigPart;
import com.github.victools.jsonschema.generator.TypeScope;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.function.Predicate;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

/**
 * Test for the {@link SwaggerModule} class.
 */
@RunWith(JUnitParamsRunner.class)
public class SwaggerModuleTest {

    private SchemaGeneratorConfigBuilder configBuilder;
    private SchemaGeneratorGeneralConfigPart typesInGeneralConfigPart;
    private SchemaGeneratorConfigPart<FieldScope> fieldConfigPart;
    private SchemaGeneratorConfigPart<MethodScope> methodConfigPart;

    @Before
    public void setUp() {
        this.configBuilder = Mockito.mock(SchemaGeneratorConfigBuilder.class);
        this.typesInGeneralConfigPart = Mockito.spy(new SchemaGeneratorGeneralConfigPart());
        this.fieldConfigPart = Mockito.spy(new SchemaGeneratorConfigPart<>());
        this.methodConfigPart = Mockito.spy(new SchemaGeneratorConfigPart<>());
        Mockito.when(this.configBuilder.forTypesInGeneral()).thenReturn(this.typesInGeneralConfigPart);
        Mockito.when(this.configBuilder.forFields()).thenReturn(this.fieldConfigPart);
        Mockito.when(this.configBuilder.forMethods()).thenReturn(this.methodConfigPart);
    }

    @Test
    public void testApplyToConfigBuilderWithDefaultOptions() {
        new SwaggerModule().applyToConfigBuilder(this.configBuilder);

        this.verifyCommonConfigurations();

        Mockito.verify(this.configBuilder, Mockito.times(2)).forTypesInGeneral();
        Mockito.verify(this.typesInGeneralConfigPart).withTitleResolver(Mockito.any());
        Mockito.verify(this.typesInGeneralConfigPart).withDescriptionResolver(Mockito.any());

        Mockito.verifyNoMoreInteractions(this.configBuilder, this.typesInGeneralConfigPart, this.fieldConfigPart, this.methodConfigPart);
    }

    @Test
    public void testApplyToConfigBuilderWithAllOptions() {
        new SwaggerModule(SwaggerOption.ENABLE_PROPERTY_NAME_OVERRIDES, SwaggerOption.IGNORING_HIDDEN_PROPERTIES,
                SwaggerOption.NO_APIMODEL_DESCRIPTION, SwaggerOption.NO_APIMODEL_TITLE)
                .applyToConfigBuilder(this.configBuilder);

        this.verifyCommonConfigurations();

        Mockito.verify(this.fieldConfigPart).withPropertyNameOverrideResolver(Mockito.any());
        Mockito.verify(this.fieldConfigPart).withIgnoreCheck(Mockito.any());

        Mockito.verify(this.methodConfigPart).withIgnoreCheck(Mockito.any());

        Mockito.verifyNoMoreInteractions(this.configBuilder, this.typesInGeneralConfigPart, this.fieldConfigPart, this.methodConfigPart);
    }

    @Test
    public void testApplyToConfigBuilderWithPropertyNameOverrides() {
        new SwaggerModule(SwaggerOption.ENABLE_PROPERTY_NAME_OVERRIDES)
                .applyToConfigBuilder(this.configBuilder);

        this.verifyCommonConfigurations();

        Mockito.verify(this.configBuilder, Mockito.times(2)).forTypesInGeneral();
        Mockito.verify(this.typesInGeneralConfigPart).withTitleResolver(Mockito.any());
        Mockito.verify(this.typesInGeneralConfigPart).withDescriptionResolver(Mockito.any());

        Mockito.verify(this.fieldConfigPart).withPropertyNameOverrideResolver(Mockito.any());

        Mockito.verifyNoMoreInteractions(this.configBuilder, this.typesInGeneralConfigPart, this.fieldConfigPart, this.methodConfigPart);
    }

    @Test
    public void testApplyToConfigBuilderIgnoringHiddenProperties() {
        new SwaggerModule(SwaggerOption.IGNORING_HIDDEN_PROPERTIES)
                .applyToConfigBuilder(this.configBuilder);

        this.verifyCommonConfigurations();

        Mockito.verify(this.configBuilder, Mockito.times(2)).forTypesInGeneral();
        Mockito.verify(this.typesInGeneralConfigPart).withTitleResolver(Mockito.any());
        Mockito.verify(this.typesInGeneralConfigPart).withDescriptionResolver(Mockito.any());

        Mockito.verify(this.fieldConfigPart).withIgnoreCheck(Mockito.any());

        Mockito.verify(this.methodConfigPart).withIgnoreCheck(Mockito.any());

        Mockito.verifyNoMoreInteractions(this.configBuilder, this.typesInGeneralConfigPart, this.fieldConfigPart, this.methodConfigPart);
    }

    @Test
    public void testApplyToConfigBuilderWithoutApiModelTitle() {
        new SwaggerModule(SwaggerOption.NO_APIMODEL_TITLE)
                .applyToConfigBuilder(this.configBuilder);

        this.verifyCommonConfigurations();

        Mockito.verify(this.configBuilder).forTypesInGeneral();
        Mockito.verify(this.typesInGeneralConfigPart).withDescriptionResolver(Mockito.any());

        Mockito.verifyNoMoreInteractions(this.configBuilder, this.typesInGeneralConfigPart, this.fieldConfigPart, this.methodConfigPart);
    }

    @Test
    public void testApplyToConfigBuilderWithoutApiModelDescription() {
        new SwaggerModule(SwaggerOption.NO_APIMODEL_DESCRIPTION)
                .applyToConfigBuilder(this.configBuilder);

        this.verifyCommonConfigurations();

        Mockito.verify(this.configBuilder).forTypesInGeneral();
        Mockito.verify(this.typesInGeneralConfigPart).withTitleResolver(Mockito.any());

        Mockito.verifyNoMoreInteractions(this.configBuilder, this.typesInGeneralConfigPart, this.fieldConfigPart, this.methodConfigPart);
    }

    private void verifyCommonConfigurations() {
        Mockito.verify(this.configBuilder).forFields();
        Mockito.verify(this.configBuilder).forMethods();

        Mockito.verify(this.fieldConfigPart).withDescriptionResolver(Mockito.any());
        Mockito.verify(this.fieldConfigPart).withNumberInclusiveMinimumResolver(Mockito.any());
        Mockito.verify(this.fieldConfigPart).withNumberExclusiveMinimumResolver(Mockito.any());
        Mockito.verify(this.fieldConfigPart).withNumberInclusiveMaximumResolver(Mockito.any());
        Mockito.verify(this.fieldConfigPart).withNumberExclusiveMaximumResolver(Mockito.any());
        Mockito.verify(this.fieldConfigPart).withEnumResolver(Mockito.any());

        Mockito.verify(this.methodConfigPart).withDescriptionResolver(Mockito.any());
        Mockito.verify(this.methodConfigPart).withNumberInclusiveMinimumResolver(Mockito.any());
        Mockito.verify(this.methodConfigPart).withNumberExclusiveMinimumResolver(Mockito.any());
        Mockito.verify(this.methodConfigPart).withNumberInclusiveMaximumResolver(Mockito.any());
        Mockito.verify(this.methodConfigPart).withNumberExclusiveMaximumResolver(Mockito.any());
        Mockito.verify(this.methodConfigPart).withEnumResolver(Mockito.any());
    }

    Object parametersForTestIgnoreCheck() {
        return new Object[][]{
            {"unannotatedField", false},
            {"annotatedAsNotHiddenField", false},
            {"annotatedAsNotHiddenGetterField", false},
            {"annotatedField", true},
            {"annotatedGetterField", true}
        };
    }

    @Test
    @Parameters
    public void testIgnoreCheck(String fieldName, boolean expectedResult) {
        new SwaggerModule(SwaggerOption.IGNORING_HIDDEN_PROPERTIES).applyToConfigBuilder(this.configBuilder);

        TestType testType = new TestType(TestClassForIgnoreCheck.class);
        FieldScope field = testType.getMemberField(fieldName);

        ArgumentCaptor<Predicate<FieldScope>> captor = ArgumentCaptor.forClass(Predicate.class);
        Mockito.verify(this.fieldConfigPart).withIgnoreCheck(captor.capture());
        boolean result = captor.getValue().test(field);
        Assert.assertEquals(expectedResult, result);
    }

    Object parametersForTestPropertyNameOverrideResolver() {
        return new Object[][]{
            {"unannotatedField", null},
            {"annotatedWithoutValueField", null},
            {"annotatedWithoutValueGetterField", null},
            {"annotatedWithSameNameField", null},
            {"annotatedWithSameNameGetterField", null},
            {"annotatedField", "overrideOne"},
            {"annotatedGetterField", "overrideTwo"}
        };
    }

    @Test
    @Parameters
    public void testPropertyNameOverrideResolver(String fieldName, String expectedNameOverride) {
        new SwaggerModule(SwaggerOption.ENABLE_PROPERTY_NAME_OVERRIDES).applyToConfigBuilder(this.configBuilder);

        TestType testType = new TestType(TestClassForPropertyNameOverride.class);
        FieldScope field = testType.getMemberField(fieldName);

        ArgumentCaptor<ConfigFunction<FieldScope, String>> captor = ArgumentCaptor.forClass(ConfigFunction.class);
        Mockito.verify(this.fieldConfigPart).withPropertyNameOverrideResolver(captor.capture());
        String override = captor.getValue().apply(field);
        Assert.assertEquals(expectedNameOverride, override);
    }

    Object parametersForTestTitleResolver() {
        return new Object[][]{
            {"unannotatedField", false, null},
            {"exampleWithEmptyApiModel", false, null},
            {"exampleWithApiModelTitle", false, "example title"},
            {"listExampleWithApiModelTitle", false, null},
            {"listExampleWithApiModelTitle", true, "example title"}
        };
    }

    @Test
    @Parameters
    public void testTitleResolver(String fieldName, boolean asContainerItem, String expectedTitle) {
        new SwaggerModule().applyToConfigBuilder(this.configBuilder);

        TestType testType = new TestType(TestClassForDescription.class);
        FieldScope field = testType.getMemberField(fieldName);
        if (asContainerItem) {
            field = field.asFakeContainerItemScope();
        }

        ArgumentCaptor<ConfigFunction<TypeScope, String>> captor = ArgumentCaptor.forClass(ConfigFunction.class);
        Mockito.verify(this.typesInGeneralConfigPart).withTitleResolver(captor.capture());
        String title = captor.getValue().apply(field);
        Assert.assertEquals(expectedTitle, title);
    }

    Object parametersForTestDescriptionResolver() {
        return new Object[][]{
            {"unannotatedField", false, null, null},
            {"annotatedWithoutValueField", false, null, null},
            {"annotatedWithoutValueGetterField", false, null, null},
            {"annotatedField", false, "annotation value 1", null},
            {"annotatedGetterField", false, "annotation value 2", null},
            {"exampleWithEmptyApiModel", false, null, null},
            {"exampleWithApiModelDescription", false, null, "type description"},
            {"arrayExampleWithApiModelDescription", false, null, null},
            {"arrayExampleWithApiModelDescription", true, null, "type description"},
            {"exampleWithTwoDescriptions", false, "property description", "type description"},
            {"exampleWithApiModelTitle", false, null, null}
        };
    }

    @Test
    @Parameters
    public void testDescriptionResolver(String fieldName, boolean asContainerItem, String expectedMemberDescription, String expectedTypeDescription) {
        new SwaggerModule().applyToConfigBuilder(this.configBuilder);

        TestType testType = new TestType(TestClassForDescription.class);
        FieldScope field = testType.getMemberField(fieldName);
        if (asContainerItem) {
            field = field.asFakeContainerItemScope();
        }

        ArgumentCaptor<ConfigFunction<FieldScope, String>> memberCaptor = ArgumentCaptor.forClass(ConfigFunction.class);
        Mockito.verify(this.fieldConfigPart).withDescriptionResolver(memberCaptor.capture());
        String memberDescription = memberCaptor.getValue().apply(field);
        Assert.assertEquals(expectedMemberDescription, memberDescription);

        ArgumentCaptor<ConfigFunction<TypeScope, String>> typeCaptor = ArgumentCaptor.forClass(ConfigFunction.class);
        Mockito.verify(this.typesInGeneralConfigPart).withDescriptionResolver(typeCaptor.capture());
        TypeScope scope = Mockito.mock(TypeScope.class);
        Mockito.when(scope.getType()).thenReturn(field.getType());
        String typeDescription = typeCaptor.getValue().apply(scope);
        Assert.assertEquals(expectedTypeDescription, typeDescription);
    }

    Object parametersForTestDescriptionResolverWithNoApiModelDescription() {
        return new Object[][]{
            {"unannotatedField", null},
            {"annotatedWithoutValueField", null},
            {"annotatedWithoutValueGetterField", null},
            {"annotatedField", "annotation value 1"},
            {"annotatedGetterField", "annotation value 2"},
            {"exampleWithEmptyApiModel", null},
            {"exampleWithApiModelDescription", null},
            {"exampleWithTwoDescriptions", "property description"},
            {"exampleWithApiModelTitle", null}
        };
    }

    @Test
    @Parameters
    public void testDescriptionResolverWithNoApiModelDescription(String fieldName, String expectedMemberDescription) {
        new SwaggerModule(SwaggerOption.NO_APIMODEL_DESCRIPTION).applyToConfigBuilder(this.configBuilder);

        TestType testType = new TestType(TestClassForDescription.class);
        FieldScope field = testType.getMemberField(fieldName);

        ArgumentCaptor<ConfigFunction<FieldScope, String>> captor = ArgumentCaptor.forClass(ConfigFunction.class);
        Mockito.verify(this.fieldConfigPart).withDescriptionResolver(captor.capture());
        String description = captor.getValue().apply(field);
        Assert.assertEquals(expectedMemberDescription, description);

        Mockito.verify(this.typesInGeneralConfigPart).withTitleResolver(Mockito.any());
        Mockito.verifyNoMoreInteractions(this.typesInGeneralConfigPart);
    }

    Object parametersForTestNumberMinMaxResolvers() {
        return new Object[][]{
            {"unannotatedInt", false, null, null, null, null},
            {"unannotatedIntArray", false, null, null, null, null},
            {"unannotatedIntArray", true, null, null, null, null},
            {"minMinusHundredLong", false, "-100", null, null, null},
            {"minMinusHundredOnGetterLong", false, "-100", null, null, null},
            {"maxFiftyShort", false, null, null, "50", null},
            {"maxFiftyOnGetterShort", false, null, null, "50", null},
            {"tenToTwentyInclusiveDouble", false, "10.1", null, "20.2", null},
            {"tenToTwentyInclusiveOnGetterDouble", false, "10.1", null, "20.2", null},
            {"tenToTwentyExclusiveDecimal", false, null, "10.1", null, "20.2"},
            {"tenToTwentyExclusiveOnGetterDecimal", false, null, "10.1", null, "20.2"},
            {"positiveByte", false, null, BigDecimal.ZERO, null, null},
            {"positiveOnGetterByte", false, null, BigDecimal.ZERO, null, null},
            {"positiveOrZeroBigInteger", false, BigDecimal.ZERO, null, null, null},
            {"positiveOrZeroOnGetterBigInteger", false, BigDecimal.ZERO, null, null, null},
            {"negativeDecimal", false, null, null, null, BigDecimal.ZERO},
            {"negativeOnGetterDecimal", false, null, null, null, BigDecimal.ZERO},
            {"negativeOrZeroLong", false, null, null, BigDecimal.ZERO, null},
            {"negativeOrZeroOnGetterLong", false, null, null, BigDecimal.ZERO, null}
        };
    }

    @Test
    @Parameters
    public void testNumberMinMaxResolvers(String fieldName, boolean asContainerItem, BigDecimal expectedMinInclusive, BigDecimal expectedMinExclusive,
            BigDecimal expectedMaxInclusive, BigDecimal expectedMaxExclusive) throws Exception {
        new SwaggerModule().applyToConfigBuilder(this.configBuilder);

        TestType testType = new TestType(TestClassForNumberMinMax.class);
        FieldScope field = testType.getMemberField(fieldName);
        if (asContainerItem) {
            field = field.asFakeContainerItemScope();
        }

        ArgumentCaptor<ConfigFunction<FieldScope, BigDecimal>> minInclusiveCaptor = ArgumentCaptor.forClass(ConfigFunction.class);
        Mockito.verify(this.fieldConfigPart).withNumberInclusiveMinimumResolver(minInclusiveCaptor.capture());
        BigDecimal minInclusive = minInclusiveCaptor.getValue().apply(field);
        Assert.assertEquals(expectedMinInclusive, minInclusive);

        ArgumentCaptor<ConfigFunction<FieldScope, BigDecimal>> minExclusiveCaptor = ArgumentCaptor.forClass(ConfigFunction.class);
        Mockito.verify(this.fieldConfigPart).withNumberExclusiveMinimumResolver(minExclusiveCaptor.capture());
        BigDecimal minExclusive = minExclusiveCaptor.getValue().apply(field);
        Assert.assertEquals(expectedMinExclusive, minExclusive);

        ArgumentCaptor<ConfigFunction<FieldScope, BigDecimal>> maxInclusiveCaptor = ArgumentCaptor.forClass(ConfigFunction.class);
        Mockito.verify(this.fieldConfigPart).withNumberInclusiveMaximumResolver(maxInclusiveCaptor.capture());
        BigDecimal maxInclusive = maxInclusiveCaptor.getValue().apply(field);
        Assert.assertEquals(expectedMaxInclusive, maxInclusive);

        ArgumentCaptor<ConfigFunction<FieldScope, BigDecimal>> maxExclusiveCaptor = ArgumentCaptor.forClass(ConfigFunction.class);
        Mockito.verify(this.fieldConfigPart).withNumberExclusiveMaximumResolver(maxExclusiveCaptor.capture());
        BigDecimal maxExclusive = maxExclusiveCaptor.getValue().apply(field);
        Assert.assertEquals(expectedMaxExclusive, maxExclusive);
    }

    private static class TestClassForPropertyNameOverride {

        String unannotatedField;
        @ApiModelProperty
        int annotatedWithoutValueField;
        double annotatedWithoutValueGetterField;
        @ApiModelProperty(name = "annotatedWithSameNameField")
        Object annotatedWithSameNameField;
        boolean annotatedWithSameNameGetterField;
        @ApiModelProperty(name = "overrideOne")
        Object annotatedField;
        boolean annotatedGetterField;

        public String getUnannotatedField() {
            return this.unannotatedField;
        }

        public int getAnnotatedWithoutValueField() {
            return this.annotatedWithoutValueField;
        }

        @ApiModelProperty
        public double getAnnotatedWithoutValueGetterField() {
            return this.annotatedWithoutValueGetterField;
        }

        public Object getAnnotatedWithSameNameField() {
            return this.annotatedWithSameNameField;
        }

        @ApiModelProperty(name = "annotatedWithSameNameGetterField")
        public boolean isAnnotatedWithSameNameGetterField() {
            return this.annotatedWithSameNameGetterField;
        }

        public Object getAnnotatedField() {
            return this.annotatedField;
        }

        @ApiModelProperty(name = "overrideTwo")
        public boolean isAnnotatedGetterField() {
            return this.annotatedGetterField;
        }
    }

    private static class TestClassForDescription {

        String unannotatedField;
        @ApiModelProperty
        int annotatedWithoutValueField;
        double annotatedWithoutValueGetterField;
        @ApiModelProperty(value = "annotation value 1")
        List<Object> annotatedField;
        boolean annotatedGetterField;

        ExampleWithEmptyApiModel exampleWithEmptyApiModel;
        ExampleWithApiModelDescription exampleWithApiModelDescription;
        ExampleWithApiModelDescription[] arrayExampleWithApiModelDescription;
        @ApiModelProperty(value = "property description")
        ExampleWithApiModelDescription exampleWithTwoDescriptions;
        ExampleWithApiModelTitle exampleWithApiModelTitle;
        List<ExampleWithApiModelTitle> listExampleWithApiModelTitle;

        public String getUnannotatedField() {
            return this.unannotatedField;
        }

        public int getAnnotatedWithoutValueField() {
            return this.annotatedWithoutValueField;
        }

        @ApiModelProperty
        public double getAnnotatedWithoutValueGetterField() {
            return this.annotatedWithoutValueGetterField;
        }

        public List<Object> getAnnotatedField() {
            return this.annotatedField;
        }

        @ApiModelProperty(value = "annotation value 2")
        public boolean isAnnotatedGetterField() {
            return this.annotatedGetterField;
        }

        @ApiModel
        private class ExampleWithEmptyApiModel {
        }

        @ApiModel(value = "example title")
        private class ExampleWithApiModelTitle {
        }

        @ApiModel(description = "type description")
        private class ExampleWithApiModelDescription {
        }
    }

    private static class TestClassForIgnoreCheck {

        String unannotatedField;
        @ApiModelProperty(hidden = false)
        int annotatedAsNotHiddenField;
        double annotatedAsNotHiddenGetterField;
        @ApiModelProperty(hidden = true)
        Object annotatedField;
        boolean annotatedGetterField;

        public String getUnannotatedField() {
            return this.unannotatedField;
        }

        public int getAnnotatedWithoutValueField() {
            return this.annotatedAsNotHiddenField;
        }

        @ApiModelProperty
        public double getAnnotatedWithoutValueGetterField() {
            return this.annotatedAsNotHiddenGetterField;
        }

        public Object getAnnotatedField() {
            return this.annotatedField;
        }

        @ApiModelProperty(hidden = true)
        public boolean isAnnotatedGetterField() {
            return this.annotatedGetterField;
        }
    }

    private static class TestClassForNumberMinMax {

        int unannotatedInt;
        int[] unannotatedIntArray;
        @ApiModelProperty(allowableValues = "range[-100, infinity)")
        long minMinusHundredLong;
        long minMinusHundredOnGetterLong;
        @ApiModelProperty(allowableValues = "range(-infinity, 50]")
        short maxFiftyShort;
        short maxFiftyOnGetterShort;
        @ApiModelProperty(allowableValues = "range[10.1, 20.2]")
        Double tenToTwentyInclusiveDouble;
        Double tenToTwentyInclusiveOnGetterDouble;
        @ApiModelProperty(allowableValues = "range(10.1, 20.2)")
        BigDecimal tenToTwentyExclusiveDecimal;
        BigDecimal tenToTwentyExclusiveOnGetterDecimal;
        @ApiModelProperty(allowableValues = "range(0, infinity]")
        byte positiveByte;
        byte positiveOnGetterByte;
        @ApiModelProperty(allowableValues = "range[0, infinity]")
        BigInteger positiveOrZeroBigInteger;
        BigInteger positiveOrZeroOnGetterBigInteger;
        @ApiModelProperty(allowableValues = "range(-infinity, 0)")
        BigDecimal negativeDecimal;
        BigDecimal negativeOnGetterDecimal;
        @ApiModelProperty(allowableValues = "range[-infinity, 0]")
        Long negativeOrZeroLong;
        Long negativeOrZeroOnGetterLong;

        @ApiModelProperty(allowableValues = "range[-100, infinity)")
        public long getMinMinusHundredOnGetterLong() {
            return this.minMinusHundredOnGetterLong;
        }

        @ApiModelProperty(allowableValues = "range(-infinity, 50]")
        public short getMaxFiftyOnGetterShort() {
            return this.maxFiftyOnGetterShort;
        }

        @ApiModelProperty(allowableValues = "range[10.1, 20.2]")
        public Double getTenToTwentyInclusiveOnGetterDouble() {
            return this.tenToTwentyInclusiveOnGetterDouble;
        }

        @ApiModelProperty(allowableValues = "range(10.1, 20.2)")
        public BigDecimal getTenToTwentyExclusiveOnGetterDecimal() {
            return this.tenToTwentyExclusiveOnGetterDecimal;
        }

        @ApiModelProperty(allowableValues = "range(0, infinity]")
        public byte getPositiveOnGetterByte() {
            return this.positiveOnGetterByte;
        }

        @ApiModelProperty(allowableValues = "range[0, infinity]")
        public BigInteger getPositiveOrZeroOnGetterBigInteger() {
            return this.positiveOrZeroOnGetterBigInteger;
        }

        @ApiModelProperty(allowableValues = "range(-infinity, 0)")
        public BigDecimal getNegativeOnGetterDecimal() {
            return this.negativeOnGetterDecimal;
        }

        @ApiModelProperty(allowableValues = "range[-infinity, 0]")
        public Long getNegativeOrZeroOnGetterLong() {
            return this.negativeOrZeroOnGetterLong;
        }
    }
}