Skip to content
68 changes: 68 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,74 @@ public class ListProjectBranchesExample {
}
```

### Sorting results

You can sort the results of `list*` methods by one or multiple fields using the `OrderByField` class.
If sort direction is not specified, results will be sorted in ascending (`ASC`) order by default.

#### Example: Sort string comments by `id` descending

```java
import com.crowdin.client.Client;
import com.crowdin.client.core.model.Credentials;
import com.crowdin.client.stringcomments.model.OrderByField;
import com.crowdin.client.stringcomments.model.SortOrder;
import com.crowdin.client.stringcomments.model.StringComment;

import java.util.Collections;
import java.util.List;

public class ListCommentsSortedExample {

public static void main(String[] args) {
Credentials credentials = new Credentials("your-token", "your-organization");
Client client = new Client(credentials);

OrderByField orderByIdDesc = new OrderByField();
orderByIdDesc.setFieldName("id");
orderByIdDesc.setOrderBy(SortOrder.DESC); // Optional: default is ASC

List<StringComment> comments = client
.getStringCommentsApi()
.listStringComments(
123L, // projectId
null, null, null, null, null, null,
Collections.singletonList(orderByIdDesc)
)
.getData()
.stream()
.map(response -> response.getData())
.toList();

comments.forEach(comment -> System.out.println(comment.getId()));
}

}
```
#### Example: Sort by multiple fields

You can also sort by multiple fields, for example: first by `createdAt`, then by `id`.

```java
import java.util.Arrays;
import com.crowdin.client.stringcomments.model.OrderByField;
import com.crowdin.client.stringcomments.model.SortOrder;

public class ListCommentsSortedExample {

public static void main(String[] args) {
OrderByField orderByCreatedAtAsc = new OrderByField();
orderByCreatedAtAsc.setFieldName("createdAt"); // ASC by default

OrderByField orderByIdDesc = new OrderByField();
orderByIdDesc.setFieldName("id");
orderByIdDesc.setOrderBy(SortOrder.DESC);

List<OrderByField> orderBy = Arrays.asList(orderByCreatedAtAsc, orderByIdDesc);
}
}
```

### Customization

This client uses [Apache http client](https://hc.apache.org/) and [Jackson json library](https://github.com/FasterXML/jackson).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.crowdin.client.core.http.impl.util;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class RequestEncoder {
public static String encodeSpaces(String url) {
try {
return URLEncoder.encode(url, "UTF-8").replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
return null;
}
}
}
31 changes: 31 additions & 0 deletions src/main/java/com/crowdin/client/core/model/OrderByField.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.crowdin.client.core.model;

import com.crowdin.client.core.http.impl.util.RequestEncoder;
import lombok.Data;

import java.util.List;
import java.util.stream.Collectors;

@Data
public class OrderByField {
private String fieldName;
private SortOrder orderBy;

public static String generateSortParam(List<OrderByField> fields) {
if (fields == null || fields.isEmpty()) {
return null;
}

String sortParam = fields.stream()
.map(field -> {
if (field.getOrderBy() == null) {
field.setOrderBy(SortOrder.ASC);
}

return field.getFieldName() + " " + field.getOrderBy().to(field.getOrderBy());
})
.collect(Collectors.joining(","));

return RequestEncoder.encodeSpaces(sortParam);
}
}
16 changes: 16 additions & 0 deletions src/main/java/com/crowdin/client/core/model/SortOrder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.crowdin.client.core.model;

public enum SortOrder implements EnumConverter<SortOrder> {
ASC, DESC;

public static SortOrder from(String value) {
if (value == null) return ASC;

return SortOrder.valueOf(value.toUpperCase());
}

@Override
public String to(SortOrder v) {
return (v != null ? v : ASC).name().toLowerCase();
}
}
123 changes: 101 additions & 22 deletions src/main/java/com/crowdin/client/glossaries/GlossariesApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@
import com.crowdin.client.core.http.HttpRequestConfig;
import com.crowdin.client.core.http.exceptions.HttpBadRequestException;
import com.crowdin.client.core.http.exceptions.HttpException;
import com.crowdin.client.core.model.ClientConfig;
import com.crowdin.client.core.model.Credentials;
import com.crowdin.client.core.model.DownloadLink;
import com.crowdin.client.core.model.DownloadLinkResponseObject;
import com.crowdin.client.core.model.PatchRequest;
import com.crowdin.client.core.model.ResponseList;
import com.crowdin.client.core.model.ResponseObject;
import com.crowdin.client.core.model.*;
import com.crowdin.client.glossaries.model.*;

import java.util.List;
Expand Down Expand Up @@ -59,11 +53,36 @@ public ResponseList<Concept> listConcepts(Long glossaryId, Integer limit, Intege
return listConcepts(glossaryId, params);
}

/**
* @param glossaryId glossary identifier
* @param limit maximum number of items to retrieve (default 25)
* @param offset starting offset in the collection (default 0)
* @param orderBy list of OrderByFields
* @return list of concepts
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.glossaries.concepts.getMany" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.glossaries.concepts.getMany" target="_blank"><b>Enterprise API Documentation</b></a></li>
* </ul>
*/
public ResponseList<Concept> listConcepts(Long glossaryId, Integer limit, Integer offset, List<OrderByField> orderBy) throws HttpException, HttpBadRequestException {
ListConceptsParams params = new ListConceptsParams();
params.setLimit(limit);
params.setOffset(offset);
params.setOrderByList(orderBy);
return listConcepts(glossaryId, params);
}

public ResponseList<Concept> listConcepts(Long glossaryId, ListConceptsParams params) throws HttpException, HttpBadRequestException {
ListConceptsParams query = Optional.ofNullable(params).orElse(new ListConceptsParams());

String orderBy = query.getOrderByList() != null
? OrderByField.generateSortParam(query.getOrderByList())
: query.getOrderBy();

Map<String, Optional<Object>> queryParams = HttpRequestConfig.buildUrlParams(
"orderBy", Optional.ofNullable(params.getOrderBy()),
"limit", Optional.ofNullable(params.getLimit()),
"offset", Optional.ofNullable(params.getOffset())
"orderBy", Optional.ofNullable(orderBy),
"limit", Optional.ofNullable(query.getLimit()),
"offset", Optional.ofNullable(query.getOffset())
);
ConceptResponseList conceptResponseList = this.httpClient.get(this.url + "/glossaries/" + glossaryId + "/concepts", new HttpRequestConfig(queryParams), ConceptResponseList.class);
return ConceptResponseList.to(conceptResponseList);
Expand Down Expand Up @@ -128,12 +147,39 @@ public ResponseList<Glossary> listGlossaries(Long groupId, Integer limit, Intege
return listGlossaries(params);
}

/**
* @param groupId group identifier
* @param limit maximum number of items to retrieve (default 25)
* @param offset starting offset in the collection (default 0)
* @param orderBy list of OrderByField
* @return list of glossaries
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.glossaries.getMany" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.glossaries.getMany" target="_blank"><b>Enterprise API Documentation</b></a></li>
* </ul>
*/
public ResponseList<Glossary> listGlossaries(Long groupId, Integer limit, Integer offset, List<OrderByField> orderBy) throws HttpException, HttpBadRequestException {
ListGlossariesParams params = new ListGlossariesParams();
params.setGroupId(groupId);
params.setLimit(limit);
params.setOffset(offset);
params.setOrderByList(orderBy);
return listGlossaries(params);
}

public ResponseList<Glossary> listGlossaries(ListGlossariesParams params) throws HttpException, HttpBadRequestException {
ListGlossariesParams query = Optional.ofNullable(params).orElse(new ListGlossariesParams());

String orderBy = query.getOrderByList() != null
? OrderByField.generateSortParam(query.getOrderByList())
: query.getOrderBy();

Map<String, Optional<Object>> queryParams = HttpRequestConfig.buildUrlParams(
"groupId", Optional.ofNullable(params.getGroupId()),
"userId", Optional.ofNullable(params.getUserId()),
"limit", Optional.ofNullable(params.getLimit()),
"offset", Optional.ofNullable(params.getOffset())
"groupId", Optional.ofNullable(query.getGroupId()),
"userId", Optional.ofNullable(query.getUserId()),
"limit", Optional.ofNullable(query.getLimit()),
"offset", Optional.ofNullable(query.getOffset()),
"orderBy", Optional.ofNullable(orderBy)
);
GlossaryResponseList glossaryResponseList = this.httpClient.get(this.url + "/glossaries", new HttpRequestConfig(queryParams), GlossaryResponseList.class);
return GlossaryResponseList.to(glossaryResponseList);
Expand Down Expand Up @@ -285,16 +331,49 @@ public ResponseList<Term> listTerms(Long glossaryId, Long userId, String languag
return listTerms(glossaryId, params);
}

/**
* @param glossaryId glossary identifier
* @param userId user identifier
* @param languageId language identifier
* @param conceptId concept identifier
* @param translationOfTermId term identifier
* @param limit maximum number of items to retrieve (default 25)
* @param offset starting offset in the collection (default 0)
* @param orderBy list of OrderByField
* @return list of terms
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.glossaries.terms.getMany" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.glossaries.terms.getMany" target="_blank"><b>Enterprise API Documentation</b></a></li>
* </ul>
*/
public ResponseList<Term> listTerms(Long glossaryId, Long userId, String languageId, Long conceptId, @Deprecated Long translationOfTermId, Integer limit, Integer offset, List<OrderByField> orderBy) throws HttpException, HttpBadRequestException {
ListTermsParams params = new ListTermsParams();
params.setUserId(userId);
params.setLanguageId(languageId);
params.setConceptId(conceptId);
params.setTranslationOfTermId(translationOfTermId);
params.setLimit(limit);
params.setOffset(offset);
params.setOrderByList(orderBy);
return listTerms(glossaryId, params);
}

public ResponseList<Term> listTerms(Long glossaryId, ListTermsParams params) throws HttpException, HttpBadRequestException {
ListTermsParams query = Optional.ofNullable(params).orElse(new ListTermsParams());

String orderBy = query.getOrderByList() != null
? OrderByField.generateSortParam(query.getOrderByList())
: query.getOrderBy();

Map<String, Optional<Object>> queryParams = HttpRequestConfig.buildUrlParams(
"orderBy", Optional.ofNullable(params.getOrderBy()),
"userId", Optional.ofNullable(params.getUserId()),
"languageId", Optional.ofNullable(params.getLanguageId()),
"conceptId", Optional.ofNullable(params.getConceptId()),
"translationOfTermId", Optional.ofNullable(params.getTranslationOfTermId()),
"croql", Optional.ofNullable(params.getCroql()),
"limit", Optional.ofNullable(params.getLimit()),
"offset", Optional.ofNullable(params.getOffset())
"orderBy", Optional.ofNullable(orderBy),
"userId", Optional.ofNullable(query.getUserId()),
"languageId", Optional.ofNullable(query.getLanguageId()),
"conceptId", Optional.ofNullable(query.getConceptId()),
"translationOfTermId", Optional.ofNullable(query.getTranslationOfTermId()),
"croql", Optional.ofNullable(query.getCroql()),
"limit", Optional.ofNullable(query.getLimit()),
"offset", Optional.ofNullable(query.getOffset())
);
TermResponseList termResponseList = this.httpClient.get(this.url + "/glossaries/" + glossaryId + "/terms", new HttpRequestConfig(queryParams), TermResponseList.class);
return TermResponseList.to(termResponseList);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.crowdin.client.glossaries.model;

import com.crowdin.client.core.model.OrderByField;
import com.crowdin.client.core.model.Pagination;
import lombok.Data;

import java.util.List;

@Data
public class ListConceptsParams extends Pagination {

private String orderBy;
private List<OrderByField> orderByList;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.crowdin.client.glossaries.model;

import com.crowdin.client.core.model.OrderByField;
import com.crowdin.client.core.model.Pagination;
import lombok.Data;

import java.util.List;

@Data
public class ListGlossariesParams extends Pagination {

private String orderBy;
private Long userId;
private Long groupId;
private List<OrderByField> orderByList;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.crowdin.client.glossaries.model;

import com.crowdin.client.core.model.OrderByField;
import com.crowdin.client.core.model.Pagination;
import lombok.Data;

import java.util.List;

@Data
public class ListTermsParams extends Pagination {

Expand All @@ -15,4 +18,5 @@ public class ListTermsParams extends Pagination {
*/
private Long translationOfTermId;
private String croql;
private List<OrderByField> orderByList;
}
31 changes: 25 additions & 6 deletions src/main/java/com/crowdin/client/labels/LabelsApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@
import com.crowdin.client.core.http.HttpRequestConfig;
import com.crowdin.client.core.http.exceptions.HttpBadRequestException;
import com.crowdin.client.core.http.exceptions.HttpException;
import com.crowdin.client.core.model.BooleanInt;
import com.crowdin.client.core.model.ClientConfig;
import com.crowdin.client.core.model.Credentials;
import com.crowdin.client.core.model.PatchRequest;
import com.crowdin.client.core.model.ResponseList;
import com.crowdin.client.core.model.ResponseObject;
import com.crowdin.client.core.model.*;
import com.crowdin.client.labels.model.AddLabelRequest;
import com.crowdin.client.labels.model.Label;
import com.crowdin.client.labels.model.LabelResponseList;
Expand Down Expand Up @@ -58,6 +53,30 @@ public ResponseList<Label> listLabels(Long projectId, Integer limit, Integer off
return LabelResponseList.to(labelResponseList);
}

/**
* @param projectId Project Identifier
* @param limit A maximum number of items to retrieve. Default: 25
* @param offset A starting offset in the collection. Default: 0
* @param isSystem Filter collection by isSystem value
* @param orderBy list of OrderByField
* @return list of labels
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.projects.labels.getMany" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.projects.labels.getMany" target="_blank"><b>Enterprise API Documentation</b></a></li>
* </ul>
*/
public ResponseList<Label> listLabels(Long projectId, Integer limit, Integer offset, BooleanInt isSystem, List<OrderByField> orderBy) throws HttpException, HttpBadRequestException {
String builtUrl = String.format("%s/projects/%d/labels", this.url, projectId);
Map<String, Optional<Object>> queryParams = HttpRequestConfig.buildUrlParams(
"limit", Optional.ofNullable(limit),
"offset", Optional.ofNullable(offset),
"isSystem", Optional.ofNullable(isSystem),
"orderBy", Optional.ofNullable(OrderByField.generateSortParam(orderBy))
);
LabelResponseList labelResponseList = this.httpClient.get(builtUrl, new HttpRequestConfig(queryParams), LabelResponseList.class);
return LabelResponseList.to(labelResponseList);
}

/**
* @param projectId Project Identifier
* @param request Request object
Expand Down
Loading