Skip to content

Commit

Permalink
Feature/GitHub actions (#5)
Browse files Browse the repository at this point in the history
* setup sort, count, and fix criteria grouping

* setup jacoco

* setup badges

* commit badges

* add some unit tests

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
pascallibenzi and github-actions[bot] authored Jan 2, 2025
1 parent 80c626c commit 0146965
Show file tree
Hide file tree
Showing 22 changed files with 512 additions and 152 deletions.
1 change: 1 addition & 0 deletions .github/badges/json-rpc-client-jacoco.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions .github/badges/rpc-core-jacoco.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions .github/badges/xml-rpc-core-jacoco.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
70 changes: 70 additions & 0 deletions .github/workflows/maven-java.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path

name: Maven Package

on: [ push, pull_request ]

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write

steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

- name: Build with Maven
run: mvn -B verify --file pom.xml

# generates coverage-report.md and publishes as checkrun
- name: Generate JaCoCo Badge
uses: cicirello/jacoco-badge-generator@v2
with:
jacoco-csv-file: java-odoo-rpc-core/target/site/jacoco/jacoco.csv
badges-directory: .github/badges
generate-coverage-badge: true
coverage-badge-filename: rpc-core-jacoco.svg
coverage-label: rpc-core
colors: '#4c1 #97ca00 #a4a61d #dfb317 #fe7d37 #e05d44'
intervals: 100 80 70 60 50 0

# generates coverage-report.md and publishes as checkrun
- name: Generate JaCoCo Badge
uses: cicirello/jacoco-badge-generator@v2
with:
jacoco-csv-file: java-odoo-json-rpc-client/target/site/jacoco/jacoco.csv
badges-directory: .github/badges
generate-coverage-badge: true
coverage-badge-filename: json-rpc-client-jacoco.svg
coverage-label: json-rpc
colors: '#4c1 #97ca00 #a4a61d #dfb317 #fe7d37 #e05d44'
intervals: 100 80 70 60 50 0

# generates coverage-report.md and publishes as checkrun
- name: Generate JaCoCo Badge
uses: cicirello/jacoco-badge-generator@v2
with:
jacoco-csv-file: java-odoo-xml-rpc-core/target/site/jacoco/jacoco.csv
badges-directory: .github/badges
generate-coverage-badge: true
coverage-badge-filename: xml-rpc-core-jacoco.svg
coverage-label: xml-rpc
colors: '#4c1 #97ca00 #a4a61d #dfb317 #fe7d37 #e05d44'
intervals: 100 80 70 60 50 0

- name: Commit and push the badge (if it changed)
uses: EndBug/add-and-commit@v9
with:
default_author: github_actions
message: 'commit badges'
add: '*.svg'
author: "GitHub Actions"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 4 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

[![Static Badge](https://img.shields.io/badge/maven%20central-0.0.4-green)](https://central.sonatype.com/artifact/ch.helvethink.odoo4java/java-odoo-rpc-parent/0.0.4)

Coverage: ![rpc-core-cov](.github/badges/rpc-core-jacoco.svg)
![xml-rpc-cov](.github/badges/xml-rpc-core-jacoco.svg)
![json-rpc-cov](.github/badges/json-rpc-client-jacoco.svg)

The `Java Odoo RPC` project provides tooling and abstraction for interactions with your Odoo RPC API (JSON and XML).\
First, it provides the [java-odoo-xml-rpc-core](java-odoo-xml-rpc-core/README.MD) library which provides you some tooling for the serialization of
objects returned by Odoo using the XML-RPC external API.\
Expand Down
Empty file added coverage-results.md
Empty file.
4 changes: 2 additions & 2 deletions java-odoo-json-rpc-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@
<publishingServerId>central</publishingServerId>
</configuration>
</plugin>
<plugin>
<!-- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.2.3</version>
Expand All @@ -166,7 +166,7 @@
</goals>
</execution>
</executions>
</plugin>
</plugin> -->

<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import ch.helvethink.odoo4java.models.OdooObject;
import ch.helvethink.odoo4java.rpc.OdooRpcClient;
import ch.helvethink.odoo4java.serialization.OdooObjectMapper;
import ch.helvethink.odoo4java.tools.CriteriaTools;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.gson.Gson;
Expand All @@ -39,18 +40,18 @@
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.codehaus.plexus.util.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.*;

import static ch.helvethink.odoo4java.serialization.OdooConstants.OdooMethods.*;
import static ch.helvethink.odoo4java.serialization.OdooConstants.OdooPagination.ODOO_LIMIT;
import static ch.helvethink.odoo4java.serialization.OdooConstants.OdooPagination.ODOO_OFFSET;
import static ch.helvethink.odoo4java.serialization.OdooConstants.OdooPagination.*;
import static ch.helvethink.odoo4java.serialization.OdooConstants.OdooServices.ODOO_COMMON_SERVICE;
import static ch.helvethink.odoo4java.serialization.OdooConstants.OdooServices.ODOO_OBJECT_SERVICE;
import static java.util.Arrays.asList;

/**
* Abstraction of Odoo's JSON-RPC API
Expand Down Expand Up @@ -158,18 +159,48 @@ private JsonObject getResult(final Request request) throws IOException {
}
}

@Override
public <T extends OdooObj> List<T> findByCriteria(final int limit, final int page, final Class<T> classToConvert, final String... criteria) {
return findByCriteria(limit, page, "", classToConvert, criteria);
}

@Override
public int countByCriteria(final Class<? extends OdooObj> objectType, final String... criteria) {
// Warn, some of the json apis do not accept the limit field (and it produces a silent error...)
JsonObject requestArgs = new JsonObject();

final RequestBody requestBody =
new JsonRPCRequestBuilder()
.withMethod(XML_RPC_EXECUTE_METHOD_NAME)
.withService(ODOO_OBJECT_SERVICE)
.withParamArgs(dbName, uid, password,
objectType.getDeclaredAnnotation(OdooObject.class).value(),
"search_count",
new Gson().toJsonTree(CriteriaTools.groupCriteria(criteria)),
requestArgs)
.buildRequest();

final Request request0 = new Request.Builder()
.url(instanceUrl + JSONRPC_ENDPOINT)
.post(requestBody)
.build();

return requestSingleResult(request0);
}

/**
* {@inheritDoc}
*/
public <T extends OdooObj> List<T> findByCriteria(final int limit, final Class<T> classToConvert, final String... criteria) {
return findByCriteria(limit, 0, classToConvert, criteria);
return findByCriteria(limit, 0, "", classToConvert, criteria);
}

/**
* {@inheritDoc}
*/
public <T extends OdooObj> List<T> findByCriteria(final int limit, final int page, final Class<T> classToConvert, final String... criteria) {
return genericCall(limit, page, classToConvert, ODOO_SEARCH_READ_API, criteria);
@Override
public <T extends OdooObj> List<T> findByCriteria(final int limit, final int page, final String sortByField, final Class<T> classToConvert, final String... criteria) {
return genericCall(limit, page, sortByField, classToConvert, ODOO_SEARCH_READ_API, criteria);
}

/**
Expand Down Expand Up @@ -202,7 +233,7 @@ public <T extends OdooObj> List<T> findListByIdsInt(final List<Integer> idsToFet
if (idsToFetch == null || idsToFetch.isEmpty()) {
return Collections.emptyList();
}
return genericCall(0, 0, classToConvert, ODOO_READ_METHOD, idsToFetch);
return genericCall(0, 0, "", classToConvert, ODOO_READ_METHOD, idsToFetch);
}

/**
Expand Down Expand Up @@ -247,7 +278,6 @@ public int deleteOdooObject(final Integer id, final Class<? extends OdooObj> cla
* @return The id of the saved object in odoo
*/
int genericSave(final String method, final OdooObj toSave, Integer id) {

final JsonRPCRequestBuilder jsonRPCRequestBuilder = new JsonRPCRequestBuilder();
final Object[] params = {dbName, uid, password, toSave.getClass().getDeclaredAnnotation(OdooObject.class).value(), method,
method.equals("write") ? new Object[]{
Expand Down Expand Up @@ -284,26 +314,33 @@ private int requestSingleResult(final Request request) {
}
}

/**
* Generic call through Odoo JSON-RPC API
*
* @param limit Results limit
* @param responseType The type of objects we want to retrieve
* @param method The JSON-RPC method we need to call (search_name, execute, ...)
* @param requestCriteria The request criteria
* @param <T> Type of objects we're retrieving
* @return The list of objects returned by Odoo
*/
<T extends OdooObj> List<T> genericCall(final int limit, final int page, final Class<T> responseType, final String method, final Object... requestCriteria) {
return genericCall(limit, page, "", responseType, method, requestCriteria);
}

/**
* Generic call through Odoo JSON-RPC API
*
* @param limit Results limit
* @param responseType The type of objects we want to retrieve
* @param method The JSON-RPC method we need to call (search_name, execute, ...)
* @param requestCriteria The request criteria
* @param <T> Type of objects we're retrieving
* @return The list of objects returned by Odoo
*/
<T extends OdooObj> List<T> genericCall(final int limit, final int page, final String sortByField, final Class<T> responseType, final String method, final Object... requestCriteria) {
final Object[] requestCriteriaNotEmpty = requestCriteria == null || requestCriteria.length == 0 ?
new Object[]{"id", ">", "-1"} : requestCriteria;

final List<?> criteria = method.equals(ODOO_NAME_SEARCH_API) ? Arrays.asList(requestCriteria) :
method.equals(ODOO_READ_METHOD) ?
List.of(requestCriteriaNotEmpty) : List.of(List.of(List.of(requestCriteriaNotEmpty)));
List.of(requestCriteriaNotEmpty) : CriteriaTools.groupCriteria(requestCriteriaNotEmpty);

// Warn, some of the json apis do not accept the limit field (and it produces a silent error...)
JsonObject requestArgs = new JsonObject();
if(!StringUtils.isEmpty(sortByField)) {
requestArgs.addProperty(ODOO_SORT, sortByField);
}
if (limit > 0) {
requestArgs.addProperty(ODOO_LIMIT, limit);
requestArgs.addProperty(ODOO_OFFSET, page * limit);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ void testGenericCallValidResponse() throws IOException {

when(mockResponse.body().string()).thenReturn(mockResponseJson);

List<Project> projects = odooClient.genericCall(10, 0, Project.class, "search_read", "param1", "param2");
List<Project> projects = odooClient.genericCall(10, 0, Project.class, "search_read", "id", ">", "10");

assertNotNull(projects);
assertEquals(1, projects.size());
Expand Down
4 changes: 2 additions & 2 deletions java-odoo-rpc-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
<publishingServerId>central</publishingServerId>
</configuration>
</plugin>
<plugin>
<!-- <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.2.3</version>
Expand All @@ -149,7 +149,7 @@
</goals>
</execution>
</executions>
</plugin>
</plugin> -->

<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public interface OdooRpcClient {
<T extends OdooObj> List<T> findByCriteria(final int limit, final int page, final Class<T> classToConvert, final String... criteria);


int countByCriteria(Class<? extends OdooObj> objectType, String... criteria);

/**
* Find an Odoo object using criteria.
* If no criteria, will send all the objects (id >=0 )
Expand All @@ -61,6 +63,8 @@ public interface OdooRpcClient {
*/
<T extends OdooObj> List<T> findByCriteria(final int limit, final Class<T> classToConvert, final String... criteria);

<T extends OdooObj> List<T> findByCriteria(int limit, int page, String sortByField, Class<T> classToConvert, String... criteria);

/**
* Fetch an object by its id
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ public static final class OdooPagination {
* Offset option
*/
public static final String ODOO_OFFSET = "offset";
/**
* Sort option
*/
public static final String ODOO_SORT = "order";

/**
* No public constructor - constants class
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* MIT License
*
* Copyright (c) 2024 Helvethink
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/

package ch.helvethink.odoo4java.tools;

import ch.helvethink.odoo4java.FetchException;

import java.util.ArrayList;
import java.util.List;

/**
* Tooling class for criteria
*/
public final class CriteriaTools {

/**
* Hide constructor because this is a tooling class
*/
private CriteriaTools(){}

/**
* Group varargs by 3 for requests
* @param requestCriteria List of objects for request
* @return criteria grouped
*/
public static List<List<List<Object>>> groupCriteria(final Object[] requestCriteria) {
checkCriteriaArraySize(requestCriteria);
final List<List<Object>> criteria = new ArrayList<>();
for(int i = 0; i < requestCriteria.length; i = i+3) {
criteria.add(List.of(requestCriteria[i],requestCriteria[i+1],requestCriteria[i+2]));
}
return List.of(criteria);
}

/**
* Check if array is well constructed
* @param requestCriteria The request criteria array
*/
private static void checkCriteriaArraySize(final Object[] requestCriteria) {
if(requestCriteria.length % 3 != 0) {
throw new FetchException("Criteria must be an array of size dividable by 3 (term1, operator, term2) for each criteria");
}
}

/**
* Group varargs by 3 for requests
* @param requestCriteria List of strings for request
* @return criteria grouped
*/
public static List<List<List<String>>> groupCriteria(final String[] requestCriteria) {
if(requestCriteria.length % 3 != 0) {

}
final List<List<String>> criteria = new ArrayList<>();
for(int i = 0; i < requestCriteria.length; i = i+3) {
criteria.add(List.of(requestCriteria[i],requestCriteria[i+1],requestCriteria[i+2]));
}
return List.of(criteria);
}

}
Loading

0 comments on commit 0146965

Please sign in to comment.