Java tutorial
package com.odoo.core.rpc.wrapper; /** * Odoo, Open Source Management Solution * Copyright (C) 2012-today Odoo SA (<http:www.odoo.com>) * <p/> * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version * <p/> * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details * <p/> * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http:www.gnu.org/licenses/> * <p/> * Created on 21/4/15 4:01 PM */ import android.content.Context; import android.net.Uri; import com.android.volley.DefaultRetryPolicy; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.TimeoutError; import com.android.volley.VolleyError; import com.android.volley.toolbox.HttpClientStack; import com.android.volley.toolbox.JsonObjectRequest; import com.android.volley.toolbox.RequestFuture; import com.android.volley.toolbox.Volley; import com.google.gson.Gson; import com.google.gson.internal.LinkedTreeMap; import com.odoo.core.rpc.Odoo; import com.odoo.core.rpc.handler.OdooVersionException; import com.odoo.core.rpc.helper.OArguments; import com.odoo.core.rpc.helper.ODomain; import com.odoo.core.rpc.helper.ORecordValues; import com.odoo.core.rpc.helper.OdooFields; import com.odoo.core.rpc.helper.OdooSession; import com.odoo.core.rpc.helper.OdooUserCurrency; import com.odoo.core.rpc.helper.OdooVersion; import com.odoo.core.rpc.helper.utils.OdooLog; import com.odoo.core.rpc.helper.utils.gson.OdooRecord; import com.odoo.core.rpc.helper.utils.gson.OdooResponse; import com.odoo.core.rpc.helper.utils.gson.OdooResult; import com.odoo.core.rpc.http.OdooSafeClient; import com.odoo.core.rpc.listeners.IDatabaseListListener; import com.odoo.core.rpc.listeners.IModuleInstallListener; import com.odoo.core.rpc.listeners.IOdooConnectionListener; import com.odoo.core.rpc.listeners.IOdooLoginCallback; import com.odoo.core.rpc.listeners.IOdooResponse; import com.odoo.core.rpc.listeners.OdooError; import com.odoo.core.rpc.listeners.OdooSyncResponse; import com.odoo.core.support.OUser; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; public class OdooWrapper<T> implements Response.Listener<JSONObject> { public static final String TAG = OdooWrapper.class.getName(); protected String serverURL; protected OdooVersion mVersion = new OdooVersion(); private RequestQueue requestQueue; private OdooResponseQueue responseQueue; protected IOdooConnectionListener mIOdooConnectionListener; protected OdooSession odooSession = new OdooSession(); protected OUser user; protected Gson gson; private Odoo mOdoo; private HashMap<String, Object> tempContext = null; private Integer new_request_timeout = Odoo.REQUEST_TIMEOUT_MS; private Integer new_request_max_retry = Odoo.DEFAULT_MAX_RETRIES; public OdooWrapper(Context context, String baseURL) { serverURL = stripURL(baseURL); gson = new Gson(); responseQueue = new OdooResponseQueue(); requestQueue = Volley.newRequestQueue(context, new HttpClientStack(OdooSafeClient.getSafeClient(true))); } @SuppressWarnings("unchecked") protected T connect(boolean synchronizedTask) throws OdooVersionException { mOdoo = (Odoo) this; if (serverURL != null) { OdooLog.v("Connecting to " + serverURL); if (!synchronizedTask) { getVersionInfo(new IOdooResponse() { @Override public void onResponse(OdooResult response) { if (mVersion.getVersionNumber() < 10) { getSessionInfo(new IOdooResponse() { @Override public void onResponse(OdooResult response) { if (mIOdooConnectionListener != null) { mIOdooConnectionListener.onConnect(mOdoo); } } @Override public void onError(OdooError error) { if (mIOdooConnectionListener != null) { mIOdooConnectionListener.onError(error); } } }); } else { if (mIOdooConnectionListener != null) { mIOdooConnectionListener.onConnect(mOdoo); } } } @Override public void onError(OdooError error) { if (mIOdooConnectionListener != null) { mIOdooConnectionListener.onError(error); } } }); } else { getVersionInfo(); getSessionInfo(); } } return (T) this; } public T withRetryPolicy(Integer request_timeout, Integer max_retry) { new_request_timeout = request_timeout; new_request_max_retry = max_retry; return (T) this; } private void newJSONPOSTRequest(final String url, JSONObject params, IOdooResponse odooResponse, OdooSyncResponse backResponse) { OdooLog.d("REQUEST URL : " + url); final JSONObject postData = createRequestWrapper(params, odooResponse); OdooLog.d("POST DATA: " + postData); RequestFuture<JSONObject> requestFuture = RequestFuture.newFuture(); if (backResponse == null) { Response.ErrorListener errorListener = new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { OdooLog.d("ERROR RESPONSE : " + error.getMessage()); String message = error.getMessage(); int responseCode = -1; if (error.networkResponse != null) { message = "Server Error :" + error.networkResponse.statusCode; switch (error.networkResponse.statusCode) { case 400: responseCode = Odoo.ErrorCode.OdooServerError.get(); break; case 404: responseCode = Odoo.ErrorCode.InvalidURL.get(); break; default: responseCode = Odoo.ErrorCode.UnknownError.get(); } } OdooError odooError = new OdooError(message, error); odooError.setResponseCode(responseCode); if (error instanceof TimeoutError) { odooError.setMessage("Request Time out"); odooError.setServerTrace("Requested too many records. \n\n" + "You can update values before requesting data:\n" + "Odoo.REQUEST_TIMEOUT_MS\n" + "Odoo.DEFAULT_MAX_RETRIES"); } try { IOdooResponse response = responseQueue.get(postData.getInt("id")); if (response != null) { response.onError(odooError); responseQueue.remove(postData.getInt("id")); } } catch (JSONException e) { OdooLog.e(e, e.getMessage()); } } }; JsonObjectRequest request = new JsonObjectRequest(url, postData, OdooWrapper.this, errorListener); request.setRetryPolicy(new DefaultRetryPolicy(new_request_timeout, new_request_max_retry, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); requestQueue.add(request); } else { JsonObjectRequest request = new JsonObjectRequest(url, postData, requestFuture, requestFuture); request.setRetryPolicy(new DefaultRetryPolicy(new_request_timeout, new_request_max_retry, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); requestQueue.add(request); try { backResponse.setResponse(parseToResponse(requestFuture.get())); } catch (Exception e) { OdooLog.e(e); } } new_request_timeout = Odoo.REQUEST_TIMEOUT_MS; new_request_max_retry = Odoo.DEFAULT_MAX_RETRIES; } public void requestController(String fullURL, JSONObject data, IOdooResponse callback) { requestController(fullURL, data, callback, null); } public OdooResult requestController(String fullURL, JSONObject data) { OdooSyncResponse response = new OdooSyncResponse(); requestController(fullURL, data, null, response); return validateResult(response); } private void requestController(String fullURL, JSONObject data, IOdooResponse callback, OdooSyncResponse backResponse) { newJSONPOSTRequest(fullURL, data, callback, backResponse); } private JSONObject createRequestWrapper(JSONObject params, IOdooResponse callback) { JSONObject requestData = new JSONObject(); try { int randomId = getRequestID(); JSONObject newParams = params; if (newParams == null) { newParams = new JSONObject(); } if (mVersion != null && mVersion.getVersionNumber() == 7) { newParams.put("session_id", odooSession.getSessionId()); } requestData.put("jsonrpc", "2.0"); requestData.put("method", "call"); requestData.put("params", newParams); requestData.put("id", randomId); if (callback != null) responseQueue.add(randomId, callback); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } return requestData; } private int getRequestID() { return Math.abs(new Random().nextInt(9999)); } public OdooResult getVersionInfo() throws OdooVersionException { OdooSyncResponse response = new OdooSyncResponse(); getVersionInfo(null, response); OdooResult version = validateResult(response); mVersion = OdooVersion.parseVersion(version); return version; } public void getVersionInfo(IOdooResponse res) { getVersionInfo(res, null); } private void getVersionInfo(final IOdooResponse res, OdooSyncResponse backResponse) { String url = serverURL + "/web/webclient/version_info"; newJSONPOSTRequest(url, null, new IOdooResponse() { @Override public void onResponse(OdooResult response) { try { mVersion = OdooVersion.parseVersion(response); res.onResponse(response); } catch (OdooVersionException e) { OdooError error = new OdooError(e.getMessage(), null); error.setResponseCode(Odoo.ErrorCode.OdooVersionError.get()); res.onError(error); } } @Override public void onError(OdooError error) { res.onError(error); } }, backResponse); } public OdooResult getSessionInfo() { OdooSyncResponse response = new OdooSyncResponse(); getSessionInfo(null, response); OdooResult session = validateResult(response); if (session != null) odooSession = OdooSession.parseSessionInfo(session); return session; } public void getSessionInfo(IOdooResponse callback) { getSessionInfo(callback, null); } private void getSessionInfo(final IOdooResponse callback, OdooSyncResponse backResponse) { String url = serverURL + "/web/session/get_session_info"; newJSONPOSTRequest(url, null, new IOdooResponse() { @Override public void onResponse(OdooResult response) { odooSession = OdooSession.parseSessionInfo(response); if (callback != null) callback.onResponse(response); } @Override public void onError(OdooError error) { if (callback != null) callback.onError(error); } }, backResponse); } public List<String> getDatabaseList() { OdooSyncResponse response = new OdooSyncResponse(); getDatabaseList(null, response); return response.get().result.getArray("result"); } public void getDatabaseList(IDatabaseListListener callback) { getDatabaseList(callback, null); } private void getDatabaseList(final IDatabaseListListener callback, OdooSyncResponse backResponse) { try { if (odooSession.getDb() != null && !odooSession.getDb().equals("false")) { // Ignoring if server is odoo.com if (callback != null) { callback.onDatabasesLoad(Collections.singletonList(odooSession.getDb())); } else { OdooResponse response = new OdooResponse(); OdooResult result = new OdooResult(); result.put("result", Collections.singletonList(odooSession.getDb())); response.result = result; backResponse.setResponse(response); } } else { Uri uri = Uri.parse(serverURL); if (!isRunbotURL(serverURL) && uri.getHost().endsWith(".odoo.com") && mVersion.getVersionNumber() >= 10) { String[] parts = uri.getHost().split("\\."); if (callback != null) { callback.onDatabasesLoad(Collections.singletonList(parts[0])); } else { OdooResponse response = new OdooResponse(); OdooResult result = new OdooResult(); result.put("result", Collections.singletonList(parts[0])); response.result = result; backResponse.setResponse(response); } } else { String url = serverURL; JSONObject params = new JSONObject(); // Fix for listing databases. Removed get_list from odoo 9.0+ if (mVersion.getVersionNumber() == 9) { url += "/jsonrpc"; params.put("method", "list"); params.put("service", "db"); params.put("args", new JSONArray()); } else if (mVersion.getVersionNumber() >= 10) { url += "/web/database/list"; params.put("context", new JSONObject()); } else { url += "/web/database/get_list"; params.put("context", new JSONObject()); } newJSONPOSTRequest(url, params, new IOdooResponse() { @Override public void onResponse(OdooResult response) { List<String> dbs = response.getArray("result"); List<String> dbNames = new ArrayList<>(); dbNames.addAll(dbs); // Fix for runtbot databases. Filtering from host prefix if (isRunbotURL(serverURL)) { String dbPrefix = getDBPrefix(serverURL); dbNames.clear(); for (String db : dbs) { if (db.contains(dbPrefix)) { dbNames.add(db); } } } callback.onDatabasesLoad(dbNames); } @Override public void onError(OdooError error) { if (mIOdooConnectionListener != null) { mIOdooConnectionListener.onError(error); } } }, backResponse); } } } catch (Exception e) { e.printStackTrace(); } } public OUser authenticate(String username, String password, String database) { OdooSyncResponse response = new OdooSyncResponse(); authenticate(username, password, database, null, response); OdooResult userResult = response.get().result; if (!(userResult.get("uid") instanceof Boolean)) { userResult.put("username", username); bindOdooSession(userResult); generateUserObject(username, password, database, null, response); if (response.getObject() != null) return (OUser) response.getObject(); } return null; } public void authenticate(String username, String password, String database, IOdooLoginCallback callback) { authenticate(username, password, database, callback, null); } /** * Authenticate user * * @param username Username * @param password Password * @param database Database * @param callback Callback Response */ private void authenticate(final String username, final String password, final String database, final IOdooLoginCallback callback, final OdooSyncResponse backResponse) { try { String url = serverURL + "/web/session/authenticate"; JSONObject params = new JSONObject(); params.put("db", database); params.put("login", username); params.put("password", password); params.put("context", new JSONObject()); newJSONPOSTRequest(url, params, new IOdooResponse() { @Override public void onResponse(OdooResult res) { if (res.get("uid") instanceof Boolean) { OdooError error = new OdooError("Authentication Fail", null); error.setResponseCode(Odoo.ErrorCode.AuthenticationFail.get()); callback.onLoginFail(error); } else { if (!(res.get("uid") instanceof Boolean)) { res.put("username", username); // FIX for 10.0+ bindOdooSession(res); generateUserObject(username, password, database, callback, backResponse); } } } @Override public void onError(OdooError error) { callback.onLoginFail(error); } }, backResponse); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } } private void bindOdooSession(OdooResult response) { if (odooSession == null) odooSession = new OdooSession(); if (mVersion.getVersionNumber() > 7 && response.containsKey("company_id")) odooSession.setCompanyId(response.getInt("company_id")); odooSession.setDb(response.getString("db")); odooSession.setSessionId(response.getString("session_id")); odooSession.setUid(response.getInt("uid")); odooSession.setUserContext(response.getMap("user_context")); odooSession.setUsername(response.getString("username")); if (mVersion.getVersionNumber() >= 10) { OdooResult currencies = response.getMap("currencies"); List<OdooUserCurrency> currencyList = new ArrayList<>(); for (String key : currencies.keySet()) { OdooResult map = currencies.getMap(key); OdooUserCurrency currency = new OdooUserCurrency(); List<Double> values = map.getArray("digits"); currency.id = Integer.parseInt(key); currency.digits = new Integer[] { values.get(0).intValue(), values.get(1).intValue() }; currency.position = map.getString("position"); currency.symbol = map.getString("symbol"); currencyList.add(currency); } odooSession.setCurrencies(currencyList); if (mVersion.isEnterprise()) { if (response.containsKey("expiration_date")) odooSession.setExpiration_date(response.getString("expiration_date")); if (response.containsKey("expiration_reason")) odooSession.setExpiration_reason(response.getString("expiration_reason")); if (response.containsKey("warning")) odooSession.setWarning_level(response.getString("warning")); } odooSession.setIs_admin(response.getBoolean("is_admin")); odooSession.setIs_superuser(response.getBoolean("is_superuser")); odooSession.setServer_version(response.getString("server_version")); odooSession.setWeb_base_url(response.getString("web.base.url")); } } public T withContext(HashMap<String, Object> context) { if (context != null) { tempContext = new HashMap<>(); tempContext.putAll(context); } return (T) this; } public void nameSearch(String model, String query, ODomain domain, int limit, IOdooResponse callback) { nameSearch(model, query, domain, limit, callback, null); } public OdooResult nameSearch(String model, String query, ODomain domain, int limit) { OdooSyncResponse response = new OdooSyncResponse(); nameSearch(model, query, domain, limit, null, response); return validateResult(response); } private void nameSearch(String model, String query, ODomain domain, int limit, IOdooResponse callback, OdooSyncResponse backResponse) { try { HashMap<String, Object> kwargs = new HashMap<>(); kwargs.put("name", query); kwargs.put("args", (domain != null) ? domain.getAsList() : new ArrayList<>()); kwargs.put("operator", "ilike"); kwargs.put("limit", limit); callMethod(model, "name_search", new OArguments(), kwargs, null, callback, backResponse); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } } public int searchCount(String model, ODomain domain) { OdooSyncResponse response = new OdooSyncResponse(); searchCount(model, domain, null, response); OdooResult result = validateResult(response); return result.getInt("result"); } public void searchCount(String model, ODomain domain, IOdooResponse callback) { searchCount(model, domain, callback, null); } private void searchCount(String model, ODomain domain, IOdooResponse callback, OdooSyncResponse backResponse) { try { JSONObject params = new JSONObject(); params.put("model", model); params.put("method", "search_count"); OArguments args = new OArguments(); args.add(domain.getArray()); callMethod(model, "search_count", args, new HashMap<String, Object>(), new HashMap<String, Object>(), callback, backResponse); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } } public OdooResult searchRead(String model, OdooFields fields, ODomain domain, int offset, int limit, String sort) { OdooSyncResponse response = new OdooSyncResponse(); searchRead(model, fields, domain, offset, limit, sort, null, response); return validateResult(response); } public void searchRead(String model, OdooFields fields, ODomain domain, int offset, int limit, String sort, final IOdooResponse callback) { searchRead(model, fields, domain, offset, limit, sort, callback, null); } private void searchRead(String model, OdooFields fields, ODomain domain, int offset, int limit, String sort, final IOdooResponse callback, OdooSyncResponse backResponse) { try { String url = serverURL + "/web/dataset/search_read"; JSONObject params = new JSONObject(); params.put("model", model); if (fields == null) { fields = new OdooFields(); } params.put("fields", fields.get().getJSONArray("fields")); if (domain == null) { domain = new ODomain(); } params.put("domain", domain.getArray()); JSONObject context = updateCTX(odooSession.getUserContext()); params.put("context", context); params.put("offset", offset); params.put("limit", limit); params.put("sort", (sort == null) ? "" : sort); newJSONPOSTRequest(url, params, callback, backResponse); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } } public OdooResult executeWorkFlow(String model, int id, String signal) { OdooSyncResponse response = new OdooSyncResponse(); executeWorkFlow(model, id, signal, null, response); return validateResult(response); } public void executeWorkFlow(String model, int id, String signal, IOdooResponse callback) { executeWorkFlow(model, id, signal, callback, null); } private void executeWorkFlow(String model, int id, String signal, IOdooResponse callback, OdooSyncResponse backResponse) { String url = serverURL + "/web/dataset/exec_workflow"; try { JSONObject params = new JSONObject(); params.put("model", model); params.put("id", id); params.put("signal", signal); newJSONPOSTRequest(url, params, callback, backResponse); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } } private JSONObject updateCTX(JSONObject context) { try { if (tempContext != null) { for (String key : tempContext.keySet()) { context.put(key, tempContext.get(key)); } } } catch (Exception e) { e.printStackTrace(); } return context; } public OdooResult read(String model, int id, OdooFields fields) { OdooSyncResponse response = new OdooSyncResponse(); read(model, id, fields, null, response); return validateResult(response); } public void read(String model, int id, OdooFields fields, IOdooResponse callback) { read(model, id, fields, callback, null); } private void read(String model, int id, OdooFields fields, final IOdooResponse callback, OdooSyncResponse backResponse) { String url = serverURL + "/web/dataset/call_kw/" + model + "/read"; try { JSONObject params = new JSONObject(); params.put("model", model); params.put("method", "read"); OArguments args = new OArguments(); args.add(id); if (fields == null) { fields = new OdooFields(); } args.add(fields.getArray()); params.put("args", args.getArray()); JSONObject kwargs = new JSONObject(); kwargs.put("context", odooSession.getUserContext()); params.put("kwargs", kwargs); newJSONPOSTRequest(url, params, callback, backResponse); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } } public OdooResult getModelFields(String model) { OdooSyncResponse response = new OdooSyncResponse(); getModelFields(model, null, response); return validateResult(response); } public void getModelFields(String model, IOdooResponse callback) { getModelFields(model, callback, null); } private void getModelFields(String model, IOdooResponse callback, OdooSyncResponse backResponse) { OdooFields fields = new OdooFields(); fields.addAll(new String[] { "name", "field_description", "ttype", "model_id" }); ODomain domain = new ODomain(); domain.add("model_id", "=", model); searchRead("ir.model.fields", fields, domain, 0, 0, null, callback, backResponse); } public void callMethod(String model, String method, OArguments arguments, HashMap<String, Object> kwargs, IOdooResponse callback) { callMethod(model, method, arguments, kwargs, null, callback, null); } public OdooResult callMethod(String model, String method, OArguments arguments, HashMap<String, Object> kwargs) { OdooSyncResponse response = new OdooSyncResponse(); callMethod(model, method, arguments, kwargs, null, null, response); return validateResult(response); } public void callMethod(String model, String method, OArguments arguments, HashMap<String, Object> kwargs, HashMap<String, Object> context, IOdooResponse callback) { callMethod(model, method, arguments, kwargs, context, callback, null); } public OdooResult callMethod(String model, String method, OArguments arguments, HashMap<String, Object> kwargs, HashMap<String, Object> context) { OdooSyncResponse response = new OdooSyncResponse(); callMethod(model, method, arguments, kwargs, context, null, response); return validateResult(response); } private void callMethod(String model, String method, OArguments arguments, HashMap<String, Object> kwargs, HashMap<String, Object> context, IOdooResponse callback, OdooSyncResponse backResponse) { String url = serverURL + "/web/dataset/call_kw"; try { JSONObject params = new JSONObject(); params.put("model", model); params.put("method", method); params.put("args", arguments.getArray()); params.put("kwargs", (kwargs != null) ? new JSONObject(gson.toJson(kwargs)) : new JSONObject()); params.put("context", (context != null) ? new JSONObject(gson.toJson(updateContext(context))) : odooSession.getUserContext()); newJSONPOSTRequest(url, params, callback, backResponse); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } } public HashMap<String, Object> updateContext(HashMap<String, Object> newContext) { newContext.putAll(odooSession.userContext()); return newContext; } public OdooResult permRead(String model, List<Integer> ids) { OdooSyncResponse response = new OdooSyncResponse(); permRead(model, ids, null, response); return validateResult(response); } public void permRead(String model, List<Integer> ids, IOdooResponse callback) { permRead(model, ids, callback, null); } private void permRead(String model, List<Integer> ids, IOdooResponse callback, OdooSyncResponse backResponse) { try { OArguments args = new OArguments(); args.add(new JSONArray(ids.toString())); callMethod(model, "perm_read", args, null, null, callback, backResponse); } catch (JSONException e) { OdooLog.e(e, e.getMessage()); } } public OdooResult createRecord(String model, ORecordValues values) { OdooSyncResponse response = new OdooSyncResponse(); createRecord(model, values, null, response); return validateResult(response); } public void createRecord(String model, ORecordValues values, IOdooResponse callback) { createRecord(model, values, callback, null); } private void createRecord(String model, ORecordValues values, IOdooResponse callback, OdooSyncResponse backResponse) { try { OArguments args = new OArguments(); args.add(new JSONObject(gson.toJson(values))); HashMap<String, Object> map = new HashMap<>(); map.put("context", gson.fromJson(odooSession.getUserContext() + "", HashMap.class)); callMethod(model, "create", args, map, null, callback, backResponse); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } } public OdooResult updateRecord(String model, ORecordValues values, int id) { OdooSyncResponse response = new OdooSyncResponse(); List<Integer> ids = new ArrayList<>(); ids.add(id); updateRecord(model, values, ids, null, response); return validateResult(response); } public OdooResult updateRecord(String model, ORecordValues values, List<Integer> ids) { OdooSyncResponse response = new OdooSyncResponse(); updateRecord(model, values, ids, null, response); return validateResult(response); } public void updateRecord(String model, ORecordValues values, int id, IOdooResponse callback) { List<Integer> ids = new ArrayList<>(); ids.add(id); updateRecord(model, values, ids, callback, null); } public void updateRecord(String model, ORecordValues values, List<Integer> ids, IOdooResponse callback) { updateRecord(model, values, ids, callback, null); } private void updateRecord(String model, ORecordValues values, List<Integer> ids, IOdooResponse callback, OdooSyncResponse backResponse) { try { OArguments args = new OArguments(); args.add(new JSONArray(ids.toString())); args.add(new JSONObject(gson.toJson(values))); HashMap<String, Object> map = new HashMap<>(); map.put("context", gson.fromJson(odooSession.getUserContext() + "", HashMap.class)); callMethod(model, "write", args, map, null, callback, backResponse); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } } public OdooResult unlinkRecord(String model, int id) { List<Integer> ids = new ArrayList<>(); ids.add(id); OdooSyncResponse response = new OdooSyncResponse(); unlinkRecord(model, ids, null, response); return validateResult(response); } public OdooResult unlinkRecord(String model, List<Integer> ids) { OdooSyncResponse response = new OdooSyncResponse(); unlinkRecord(model, ids, null, response); return validateResult(response); } public void unlinkRecord(String model, int id, IOdooResponse callback) { List<Integer> ids = new ArrayList<>(); ids.add(id); unlinkRecord(model, ids, callback, null); } public void unlinkRecord(String model, List<Integer> ids, IOdooResponse callback) { unlinkRecord(model, ids, callback, null); } private void unlinkRecord(String model, List<Integer> ids, IOdooResponse callback, OdooSyncResponse backResponse) { try { OArguments args = new OArguments(); args.add(new JSONArray(ids.toString())); HashMap<String, Object> map = new HashMap<>(); map.put("context", gson.fromJson(odooSession.getUserContext() + "", HashMap.class)); callMethod(model, "unlink", args, map, null, callback, backResponse); } catch (Exception e) { OdooLog.e(e, e.getMessage()); } } public boolean installedOnServer(String moduleName) { OdooSyncResponse response = new OdooSyncResponse(); installedOnServer(moduleName, null, response); OdooResult results = validateResult(response); return results != null && results.getRecords().size() > 0 && results.getRecords().get(0).getString("state").equals("installed"); } public void installedOnServer(String moduleName, IModuleInstallListener callback) { installedOnServer(moduleName, callback, null); } private void installedOnServer(String moduleName, final IModuleInstallListener callback, OdooSyncResponse backResponse) { OdooFields fields = new OdooFields(); fields.addAll(new String[] { "state", "name" }); ODomain domain = new ODomain(); domain.add("name", "=", moduleName); searchRead("ir.module.module", fields, domain, 0, 0, null, new IOdooResponse() { @Override public void onResponse(OdooResult response) { if (response.getRecords().size() > 0) { OdooRecord rec = response.getRecords().get(0); callback.installedOnServer(rec.getString("state").equals("installed")); } } @Override public void onError(OdooError error) { OdooLog.e(error); callback.installedOnServer(false); } }, backResponse); } private void generateUserObject(String username, String password, String db, final IOdooLoginCallback callback, final OdooSyncResponse backResponse) { final OUser[] users = new OUser[1]; users[0] = new OUser(); users[0].setUsername(username); users[0].setPassword(password); users[0].setDatabase(db); users[0].setOdooVersion(mVersion); users[0].setUserId(odooSession.getUid()); users[0].setCompanyId(odooSession.getCompanyId()); users[0].setHost(serverURL); OdooFields fields = new OdooFields(); fields.addAll(new String[] { "name", "partner_id", "tz", "image_medium", "company_id" }); ODomain domain = new ODomain(); domain.add("id", "=", users[0].getUserId()); if (backResponse != null) { OdooResult result = read("res.users", users[0].getUserId(), fields); users[0] = parseUserObject(users[0], result); backResponse.setObject(users[0]); } else { read("res.users", users[0].getUserId(), fields, new IOdooResponse() { @Override public void onResponse(OdooResult response) { users[0] = parseUserObject(users[0], response); callback.onLoginSuccess(mOdoo, users[0]); } @Override public void onError(OdooError error) { callback.onLoginFail(error); } }); } } private OUser parseUserObject(OUser user, OdooResult result) { // Odoo 10.0+ returns array of object in read method if (result.containsKey("result") && result.get("result") instanceof ArrayList) { List<LinkedTreeMap> items = (List<LinkedTreeMap>) result.get("result"); result = new OdooResult(); result.putAll(items.get(0)); } user.setName(result.getString("name")); user.setAvatar(result.getString("image_medium")); user.setTimezone(result.getString("tz")); Double partner_id = (Double) result.getArray("partner_id").get(0); Double company_id = (Double) result.getArray("company_id").get(0); user.setPartnerId(partner_id.intValue()); user.setCompanyId(company_id.intValue()); if (mVersion.getVersionNumber() == 7) { //FIX: Odoo 7 Not returning company id with user login details odooSession.setCompanyId(company_id.intValue()); } return user; } private String stripURL(String url) { if (url != null) { String newUrl; if (url.endsWith("/")) { newUrl = url.substring(0, url.lastIndexOf("/")); } else { newUrl = url; } return newUrl; } return null; } /** * Handling response queue callbacks * * @param response request response */ @Override public void onResponse(JSONObject response) { OdooLog.d("RESPONSE:" + response); OdooResponse responseMap = parseToResponse(response); if (responseMap != null) { int id = responseMap.id; IOdooResponse odooResponse = responseQueue.get(id); if (odooResponse != null) { if (responseMap.error != null) { OdooError error = OdooError.parse(responseMap.error); error.setResponseCode(Odoo.ErrorCode.OdooServerError.get()); odooResponse.onError(error); } else { odooResponse.onResponse(responseMap.result); } responseQueue.remove(id); } } } private OdooResult validateResult(OdooSyncResponse response) { OdooLog.d("SYNC_RESPONSE:" + response); if (response.get() == null) { return null; } else { if (response.get().result != null) { return response.get().result; } else { OdooResult error = new OdooResult(); error.put("error", response.get().error); return error; } } } private OdooResponse parseToResponse(JSONObject response) { try { // Fixed for direct array in result // It will add one more key to result:(result:[] become result:{"result": []}); if (response.has("result")) { if (!(response.get("result") instanceof JSONObject)) { JSONObject obj = new JSONObject(); obj.put("result", response.get("result")); response.put("result", obj); } } else if (!response.has("error")) { JSONObject result = response; response = new JSONObject(); response.put("result", result); } } catch (Exception e) { OdooLog.e(e, e.getMessage()); } return gson.fromJson(response.toString(), OdooResponse.class); } private String getDBPrefix(String host) { Pattern pattern = Pattern.compile(".runbot[1-9]{1,2}..odoo.com?(.+?)", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(host); return matcher.replaceAll("").replaceAll("http://", "").replaceAll("https://", ""); } private boolean isRunbotURL(String host) { Pattern pattern = Pattern.compile(".runbot[1-9]{1,2}..odoo.com?(.+?)", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(host); return matcher.find(); } }