@ApiOperation(value = "List models", nickname= "listModels", tags = { "Models" })
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", dataType = "string", value = "Only return models with the given version.", paramType = "query"),
            @ApiImplicitParam(name = "category", dataType = "string", value = "Only return models with the given category.", paramType = "query"),
            @ApiImplicitParam(name = "categoryLike", dataType = "string", value = "Only return models with a category like the given name.", paramType = "query"),
            @ApiImplicitParam(name = "categoryNotEquals", dataType = "string", value = "Only return models which do not have the given category.", paramType = "query"),
            @ApiImplicitParam(name = "name", dataType = "string", value = "Only return models with the given name.", paramType = "query"),
            @ApiImplicitParam(name = "nameLike", dataType = "string", value = "Only return models with a name like the given name.", paramType = "query"),
            @ApiImplicitParam(name = "key", dataType = "string", value = "Only return models with the given key.", paramType = "query"),
            @ApiImplicitParam(name = "deploymentId", dataType = "string", value = "Only return models with the given category.", paramType = "query"),
            @ApiImplicitParam(name = "version", dataType = "integer", value = "Only return models with the given version.", paramType = "query"),
            @ApiImplicitParam(name = "latestVersion", dataType = "boolean", value = "If true, only return models which are the latest version. Best used in combination with key. If false is passed in as value, this is ignored and all versions are returned.", paramType = "query"),
            @ApiImplicitParam(name = "deployed", dataType = "boolean", value = "If true, only deployed models are returned. If false, only undeployed models are returned (deploymentId is null).", paramType = "query"),
            @ApiImplicitParam(name = "tenantId", dataType = "string", value = "Only return models with the given tenantId.", paramType = "query"),
            @ApiImplicitParam(name = "tenantIdLike", dataType = "string", value = "Only return models with a tenantId like the given value.", paramType = "query"),
            @ApiImplicitParam(name = "withoutTenantId", dataType = "boolean", value = "If true, only returns models without a tenantId set. If false, the withoutTenantId parameter is ignored.", paramType = "query"),
            @ApiImplicitParam(name = "sort", dataType = "string", value = "Property to sort on, to be used together with the order.", allowableValues = "id,category,createTime,key,lastUpdateTime,name,version,tenantId", paramType = "query"),
    })
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates request was successful and the models are returned"),
            @ApiResponse(code = 400, message = "Indicates a parameter was passed in the wrong format. The status-message contains additional information.")
    })
    @GetMapping(value = "/repository/models", produces = "application/json")
    public DataResponse<ModelResponse> getModels(@ApiParam(hidden = true) @RequestParam Map<String, String> allRequestParams) {
        ModelQuery modelQuery = repositoryService.createModelQuery();

        if (allRequestParams.containsKey("id")) {
            modelQuery.modelId(allRequestParams.get("id"));
        }
        if (allRequestParams.containsKey("category")) {
            modelQuery.modelCategory(allRequestParams.get("category"));
        }
        if (allRequestParams.containsKey("categoryLike")) {
            modelQuery.modelCategoryLike(allRequestParams.get("categoryLike"));
        }
        if (allRequestParams.containsKey("categoryNotEquals")) {
            modelQuery.modelCategoryNotEquals(allRequestParams.get("categoryNotEquals"));
        }
        if (allRequestParams.containsKey("name")) {
            modelQuery.modelName(allRequestParams.get("name"));
        }
        if (allRequestParams.containsKey("nameLike")) {
            modelQuery.modelNameLike(allRequestParams.get("nameLike"));
        }
        if (allRequestParams.containsKey("key")) {
            modelQuery.modelKey(allRequestParams.get("key"));
        }
        if (allRequestParams.containsKey("version")) {
            modelQuery.modelVersion(Integer.valueOf(allRequestParams.get("version")));
        }
        if (allRequestParams.containsKey("latestVersion")) {
            boolean isLatestVersion = Boolean.parseBoolean(allRequestParams.get("latestVersion"));
            if (isLatestVersion) {
                modelQuery.latestVersion();
            }
        }
        if (allRequestParams.containsKey("deploymentId")) {
            modelQuery.deploymentId(allRequestParams.get("deploymentId"));
        }
        if (allRequestParams.containsKey("deployed")) {
            boolean isDeployed = Boolean.parseBoolean(allRequestParams.get("deployed"));
            if (isDeployed) {
                modelQuery.deployed();
            } else {
                modelQuery.notDeployed();
            }
        }
        if (allRequestParams.containsKey("tenantId")) {
            modelQuery.modelTenantId(allRequestParams.get("tenantId"));
        }
        if (allRequestParams.containsKey("tenantIdLike")) {
            modelQuery.modelTenantIdLike(allRequestParams.get("tenantIdLike"));
        }
        if (allRequestParams.containsKey("withoutTenantId")) {
            boolean withoutTenantId = Boolean.parseBoolean(allRequestParams.get("withoutTenantId"));
            if (withoutTenantId) {
                modelQuery.modelWithoutTenantId();
            }
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessModelInfoWithQuery(modelQuery);
        }
        
        return paginateList(allRequestParams, modelQuery, "id", allowedSortProperties, restResponseFactory::createModelResponseList);
    }
@Test
    @Deployment(resources = { "org/flowable/rest/service/api/repository/oneTaskProcess.bpmn20.xml" })
    public void testGetModels() throws Exception {
        // Create 2 models
        Model model1 = null;
        Model model2 = null;

        try {
            model1 = repositoryService.newModel();
            model1.setCategory("Model category");
            model1.setKey("Model key");
            model1.setMetaInfo("Model metainfo");
            model1.setName("Model name");
            model1.setVersion(2);
            model1.setDeploymentId(deploymentId);
            repositoryService.saveModel(model1);

            model2 = repositoryService.newModel();
            model2.setCategory("Another category");
            model2.setKey("Another key");
            model2.setMetaInfo("Another metainfo");
            model2.setName("Another name");
            model2.setVersion(3);
            repositoryService.saveModel(model2);

            // Try filter-less, should return all models
            String url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION);
            assertResultsPresentInDataResponse(url, model1.getId(), model2.getId());

            // Filter based on id
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?id=" + model1.getId();
            assertResultsPresentInDataResponse(url, model1.getId());

            // Filter based on category
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?category=" + encode("Another category");
            assertResultsPresentInDataResponse(url, model2.getId());

            // Filter based on category like
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?categoryLike=" + encode("Mode%");
            assertResultsPresentInDataResponse(url, model1.getId());

            // Filter based on category not equals
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?categoryNotEquals=" + encode("Another category");
            assertResultsPresentInDataResponse(url, model1.getId());

            // Filter based on name
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?name=" + encode("Another name");
            assertResultsPresentInDataResponse(url, model2.getId());

            // Filter based on name like
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?nameLike=" + encode("%del name");
            assertResultsPresentInDataResponse(url, model1.getId());

            // Filter based on key
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?key=" + encode("Model key");
            assertResultsPresentInDataResponse(url, model1.getId());

            // Filter based on version
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?version=3";
            assertResultsPresentInDataResponse(url, model2.getId());

            // Filter based on deploymentId
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?deploymentId=" + deploymentId;
            assertResultsPresentInDataResponse(url, model1.getId());

            // Filter based on deployed=true
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?deployed=true";
            assertResultsPresentInDataResponse(url, model1.getId());

            // Filter based on deployed=false
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?deployed=false";
            assertResultsPresentInDataResponse(url, model2.getId());

            // Filter based on latestVersion
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?key=" + encode("Model key") + "&latestVersion=true";
            // Make sure both models have same key
            model2 = repositoryService.createModelQuery().modelId(model2.getId()).singleResult();
            model2.setKey("Model key");
            repositoryService.saveModel(model2);
            assertResultsPresentInDataResponse(url, model2.getId());

            // Filter without tenant ID, before tenant update
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?withoutTenantId=true";
            assertResultsPresentInDataResponse(url, model1.getId(), model2.getId());

            // Set tenant ID
            model1 = repositoryService.getModel(model1.getId());
            model1.setTenantId("myTenant");
            repositoryService.saveModel(model1);

            // Filter without tenant ID, after tenant update
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?withoutTenantId=true";
            assertResultsPresentInDataResponse(url, model2.getId());

            // Filter based on tenantId
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?tenantId=myTenant";
            assertResultsPresentInDataResponse(url, model1.getId());

            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?tenantId=anotherTenant";
            assertResultsPresentInDataResponse(url);

            // Filter based on tenantId like
            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?tenantIdLike=" + encode("%enant");
            assertResultsPresentInDataResponse(url, model1.getId());

            url = RestUrls.createRelativeResourceUrl(RestUrls.URL_MODEL_COLLECTION) + "?tenantIdLike=anotherTenant";
            assertResultsPresentInDataResponse(url);

        } finally {
            if (model1 != null) {
                try {
                    repositoryService.deleteModel(model1.getId());
                } catch (Throwable ignore) {
                }
            }
            if (model2 != null) {
                try {
                    repositoryService.deleteModel(model2.getId());
                } catch (Throwable ignore) {
                }
            }
        }
    }