package io.swagger; import com.google.common.base.Functions; import com.google.common.collect.Collections2; import com.google.common.collect.Sets; import io.swagger.jaxrs.DefaultParameterExtension; import io.swagger.jaxrs.Reader; import io.swagger.jaxrs.ext.SwaggerExtensions; import io.swagger.jersey.SwaggerJersey2Jaxrs; import io.swagger.models.Model; import io.swagger.models.Swagger; import io.swagger.models.TestEnum; import io.swagger.models.parameters.FormParameter; import io.swagger.models.parameters.HeaderParameter; import io.swagger.models.parameters.Parameter; import io.swagger.params.BaseBean; import io.swagger.params.ChildBean; import io.swagger.params.EnumBean; import io.swagger.params.RefBean; import io.swagger.resources.Resource2031; import io.swagger.resources.ResourceWithFormData; import io.swagger.resources.ResourceWithJacksonBean; import io.swagger.resources.ResourceWithKnownInjections; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; import org.testng.annotations.Test; import org.testng.internal.collections.Pair; import javax.ws.rs.BeanParam; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.fail; public class SwaggerJersey2JaxrsTest { // Here so that we can get the params with the @BeanParam annotation instantiated properly void testRoute(@BeanParam BaseBean baseBean, @BeanParam ChildBean childBean, @BeanParam RefBean refBean, @BeanParam EnumBean enumBean, Integer nonBean) { } void testFormDataParamRoute(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataContentDisposition fileDetail) { } @Test(description = "not skip all types passed to extension") public void testAllTypes() { for (Class cls : Arrays.asList(BaseBean.class, ChildBean.class, RefBean.class)) { Set<Type> typesToSkip = new java.util.HashSet<Type>(); new SwaggerJersey2Jaxrs().extractParameters(new ArrayList<Annotation>(), cls, typesToSkip, SwaggerExtensions.chain()); assertEquals(typesToSkip.size(), 0); } } @Test(description = "return the proper @BeanParam Parameters based on the call to extractParameters") public void returnProperBeanParam() throws NoSuchMethodException { final Method method = getClass().getDeclaredMethod("testRoute", BaseBean.class, ChildBean.class, RefBean.class, EnumBean.class, Integer.class); final List<Pair<Type, Annotation[]>> parameters = getParameters(method.getGenericParameterTypes(), method.getParameterAnnotations()); for (Pair<Type, Annotation[]> parameter : parameters) { Type parameterType = parameter.first(); List<Parameter> swaggerParams = new SwaggerJersey2Jaxrs().extractParameters(Arrays.asList(parameter.second()), parameterType, new HashSet<Type>(), SwaggerExtensions.chain()); // Ensure proper number of parameters returned if (parameterType.equals(BaseBean.class)) { assertEquals(swaggerParams.size(), 2); } else if (parameterType.equals(ChildBean.class)) { assertEquals(swaggerParams.size(), 5); } else if (parameterType.equals(RefBean.class)) { assertEquals(swaggerParams.size(), 5); } else if (parameterType.equals(EnumBean.class)) { assertEquals(swaggerParams.size(), 1); HeaderParameter enumParam = (HeaderParameter) swaggerParams.get(0); assertEquals(enumParam.getType(), "string"); final Set<String> enumValues = Sets.newHashSet(Collections2.transform(Arrays.asList(TestEnum.values()), Functions.toStringFunction())); assertEquals(enumParam.getEnum(), enumValues); } else if (parameterType.equals(Integer.class)) { assertEquals(swaggerParams.size(), 0); } else { fail(String.format("Parameter of type %s was not expected", parameterType)); } // Ensure the proper parameter type and name is returned (The rest is handled by pre-existing logic) for (Parameter param : swaggerParams) { assertEquals(param.getName(), param.getClass().getSimpleName().replace("eter", "")); } } } @Test(description = "return the proper @BeanParam Parameters based on the call to DefaultParameterExtension.extractParameters") public void returnProperBeanParamWithDefaultParameterExtension() throws NoSuchMethodException { final Method method = getClass().getDeclaredMethod("testRoute", BaseBean.class, ChildBean.class, RefBean.class, EnumBean.class, Integer.class); final List<Pair<Type, Annotation[]>> parameters = getParameters(method.getGenericParameterTypes(), method.getParameterAnnotations()); for (Pair<Type, Annotation[]> parameter : parameters) { Type parameterType = parameter.first(); List<Parameter> swaggerParams = new DefaultParameterExtension().extractParameters(Arrays.asList(parameter.second()), parameterType, new HashSet<Type>(), SwaggerExtensions.chain()); // Ensure proper number of parameters returned if (parameterType.equals(BaseBean.class)) { assertEquals(swaggerParams.size(), 2); } else if (parameterType.equals(ChildBean.class)) { assertEquals(swaggerParams.size(), 5); } else if (parameterType.equals(RefBean.class)) { assertEquals(swaggerParams.size(), 5); } else if (parameterType.equals(EnumBean.class)) { assertEquals(swaggerParams.size(), 1); HeaderParameter enumParam = (HeaderParameter) swaggerParams.get(0); assertEquals(enumParam.getType(), "string"); final Set<String> enumValues = Sets.newHashSet(Collections2.transform(Arrays.asList(TestEnum.values()), Functions.toStringFunction())); assertEquals(enumParam.getEnum(), enumValues); } else if (parameterType.equals(Integer.class)) { assertEquals(swaggerParams.size(), 0); } else { fail(String.format("Parameter of type %s was not expected", parameterType)); } // Ensure the proper parameter type and name is returned (The rest is handled by pre-existing logic) for (Parameter param : swaggerParams) { assertEquals(param.getName(), param.getClass().getSimpleName().replace("eter", "")); } } } @Test(description = "return the proper @FormDataParam Parameters based on the call to extractParameters") public void returnProperFormDataParam() throws NoSuchMethodException { final Method method = getClass().getDeclaredMethod("testFormDataParamRoute", InputStream.class, FormDataContentDisposition.class); final List<Pair<Type, Annotation[]>> parameters = getParameters(method.getGenericParameterTypes(), method.getParameterAnnotations()); for (Pair<Type, Annotation[]> parameter : parameters) { Type parameterType = parameter.first(); List<Parameter> swaggerParams = new SwaggerJersey2Jaxrs().extractParameters(Arrays.asList(parameter.second()), parameterType, new HashSet<Type>(), SwaggerExtensions.chain()); if (parameterType.equals(InputStream.class)) { assertEquals(((FormParameter) swaggerParams.get(0)).getType(), "file"); } else { assertEquals(swaggerParams.size(), 0); } } } private List<Pair<Type, Annotation[]>> getParameters(Type[] type, Annotation[][] annotations) { final Iterator<Type> typeIterator = Arrays.asList(type).iterator(); final Iterator<Annotation[]> paramIterator = Arrays.asList(annotations).iterator(); final List<Pair<Type, Annotation[]>> result = new ArrayList<Pair<Type, Annotation[]>>(); while (paramIterator.hasNext() && typeIterator.hasNext()) { Pair<Type, Annotation[]> pair = new Pair<Type, Annotation[]>(typeIterator.next(), paramIterator.next()); result.add(pair); } return result; } @Test(description = "scan class level and field level annotations") public void scanClassAnfFieldLevelAnnotations() { final Swagger swagger = new Reader(new Swagger()).read(ResourceWithKnownInjections.class); final List<Parameter> resourceParameters = swagger.getPaths().get("/resource/{id}").getGet().getParameters(); assertNotNull(resourceParameters); assertEquals(resourceParameters.size(), 4); assertEquals(getName(resourceParameters, 0), "fieldParam"); assertEquals(getName(resourceParameters, 1), "skip"); assertEquals(getName(resourceParameters, 2), "limit"); assertEquals(getName(resourceParameters, 3), "methodParam"); } @Test(description = "FormDataBodyPart should be ignored when generating the Swagger document") public void testFormDataBodyPart() { final Swagger swagger = new Reader(new Swagger()).read(ResourceWithFormData.class); final List<Parameter> parameters = swagger.getPath("/test/document/{documentName}.json").getPost().getParameters(); assertEquals(parameters.size(), 3); assertEquals(parameters.get(0).getName(), "documentName"); assertEquals(parameters.get(1).getName(), "input"); assertEquals(parameters.get(2).getName(), "id"); } @Test(description = "JsonUnwrapped, JsonIgnore, JsonValue should be honoured") public void testJacksonFeatures() { final Swagger swagger = new Reader(new Swagger()).read(ResourceWithJacksonBean.class); Model o = swagger.getDefinitions().get("JacksonBean"); assertEquals(o.getProperties().keySet(), Sets.newHashSet("identity", "bean", "code", "message", "precodesuf", "premessagesuf")); } @Test(description = "Tests issue 2031") public void testIssue2031() { final Swagger swagger = new Reader(new Swagger()).read(Resource2031.class); assertNotNull(swagger); } private String getName(List<Parameter> resourceParameters, int i) { return resourceParameters.get(i).getName(); } }