Skip to content

Commit

Permalink
Backend: MetadataOdoo: OdooUtils enhancement -> getRawValue and isUns…
Browse files Browse the repository at this point in the history
…et method (#2410)

This commit is one of many prepare PRs / commits for a bigger PR:
SumStateAlert #2260
By Seperating the big #2260 into smaller commits we would like to make the review easier.

Co-authored-by: Kai Jeschek <[email protected]>
  • Loading branch information
DerStoecki and da-Kai authored Nov 1, 2023
1 parent 70c6f0c commit 5fc3d44
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -555,9 +555,7 @@ protected static <T extends Object> Optional<T> getAsOptional(Object object, Cla
* @return the odoo reference id or empty {@link Optional}
*/
protected static Optional<Integer> getOdooReferenceId(Object object) {
if (object instanceof Object[]) {
var odooReference = (Object[]) object;

if (object instanceof Object[] odooReference) {
if (odooReference.length > 0 && odooReference[0] instanceof Integer) {
return Optional.of((Integer) odooReference[0]);
}
Expand Down Expand Up @@ -599,6 +597,42 @@ protected static byte[] getOdooReport(Credentials credentials, String report, in
}
}

/**
* Odoo returns unset values as false. So this Method checks if the value is
* meant to be null.
*
* @param <T> type to be expected
* @param entry raw entry value
* @param expectedType class instance of expected type
* @return false if value is meant to be null.
*/
private static <T> boolean isUnset(Object entry, Class<T> expectedType) {
var entryType = entry.getClass();
if (entryType.isAssignableFrom(Boolean.class) && !expectedType.isAssignableFrom(Boolean.class)
&& !Boolean.class.cast(entry)) {
return true;
}
return false;
}

private static Object getRawValue(Field field, Map<String, ?> values) {
if (field == null || values == null) {
var warningMsg = new StringBuilder() //
.append("[getAsOrElse] missing parameter (") //
.append(field == null ? "field is null, " : "") //
.append(values == null ? "values is null, " : "") //
.toString();
log.warn(warningMsg);
return null;
}

if (!values.containsKey(field.id())) {
return null;
}

return values.get(field.id());
}

/**
* Return Field value in values and cast it to type.
*
Expand All @@ -623,29 +657,42 @@ public static <T> T getAs(Field field, Map<String, ?> values, Class<T> type) {
* @return value found in map casted to type or alternate on error
*/
public static <T> T getAsOrElse(Field field, Map<String, ?> values, Class<T> type, T alternate) {
if (field == null || values == null || type == null) {
var warningMsg = new StringBuilder().append("[getAsOrElse] missing parameter (")
.append(field == null ? "field is null, " : "").append(values == null ? "values is null, " : "")
.append(type == null ? "type is null, " : "").toString();
log.warn(warningMsg);
var entry = getRawValue(field, values);

if (entry == null || isUnset(entry, type)) {
return alternate;
}

if (!values.containsKey(field.id())) {
try {
if (type.equals(ZonedDateTime.class)) {
return type.cast(DateTime.stringToDateTime(entry.toString()));
}
return type.cast(entry);
} catch (Throwable t) {
log.warn(t.getMessage());
return alternate;
}
}

var entry = values.get(field.id());
var entryType = entry.getClass();
/**
* Return Field value in values and cast it to value of type 'enumType'.
*
* @param <T> expected type of value
* @param field to search for
* @param values map with values to search in
* @param enumType to cast into
* @param alternate value to return
* @return value found in map casted to type or alternate on error
*/
public static <T extends Enum<T>> T getAsEnum(Field field, Map<String, ?> values, Class<T> enumType, T alternate) {
var entry = getRawValue(field, values);

// Entry equals false if table value is null;
if (entryType.isAssignableFrom(Boolean.class) && !type.isAssignableFrom(Boolean.class)
&& !Boolean.class.cast(entry)) {
return null;
if (entry == null || isUnset(entry, enumType)) {
return alternate;
}

try {
return type.cast(entry);
return Enum.valueOf(enumType, entry.toString().toUpperCase());
} catch (Throwable t) {
log.warn(t.getMessage());
return alternate;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,74 @@
package io.openems.backend.metadata.odoo.odoo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Map;

import org.junit.Test;

import io.openems.backend.metadata.odoo.Field;
import io.openems.backend.metadata.odoo.Field.EdgeDevice;
import io.openems.backend.metadata.odoo.odoo.Domain.Operator;

public class OdooUtilsTest {

private static class Utility {
private static enum Enum {
FOO, BAR
}

private static enum Fields implements Field {
INTEGER, STRING, ENUM, UNAVAILABLE, BOOLEAN, NOT_AVAILABLE;

@Override
public String id() {
return this.name();
}

@Override
public int index() {
throw new UnsupportedOperationException();
}

@Override
public boolean isQuery() {
throw new UnsupportedOperationException();
}
}
}

@Test
public void testGetAsStringArray() {
var arr = OdooUtils.getAsStringArray(EdgeDevice.APIKEY, EdgeDevice.COMMENT);
assertEquals(EdgeDevice.APIKEY.id(), arr[0]);
assertEquals(EdgeDevice.COMMENT.id(), arr[1]);
}

@Test
public void testDateTimeConvertion() {
var time = ZonedDateTime.of(2000, 7, 26, 23, 54, 20, 4, ZoneId.of("Europe/Berlin"));
var timeStr = OdooUtils.DateTime.dateTimeToString(time);

var timeConv = OdooUtils.DateTime.stringToDateTime(timeStr);

assertNotEquals(time, timeConv);

var simpleTime = time.withZoneSameInstant(OdooUtils.DateTime.SERVER_TIMEZONE).withNano(0);

assertEquals(timeConv, simpleTime);

assertNull(OdooUtils.DateTime.dateTimeToString(null));
assertNull(OdooUtils.DateTime.stringToDateTime(null));

assertNull(OdooUtils.DateTime.stringToDateTime("Not a valid date"));
}

@Test
public void testGetAsObjectArray() {
var arr = OdooUtils.getAsObjectArray(new Domain(EdgeDevice.APIKEY, Operator.EQ, "foo"),
Expand All @@ -34,4 +87,49 @@ public void testGetAsObjectArray() {
}
}

@Test
public void testGetOdooReferenceId() {
var reference = new Object[] { 1, "id" };
var wrongObject = new Object[] { "foo", "bar" };

assertEquals(Integer.valueOf(1), OdooUtils.getOdooReferenceId(reference).get());
assertTrue(OdooUtils.getOdooReferenceId(wrongObject).isEmpty());
assertTrue(OdooUtils.getOdooReferenceId(null).isEmpty());
}

@Test
public void testValueConverter() {
assertThrows(UnsupportedOperationException.class, Utility.Fields.INTEGER::isQuery);
assertThrows(UnsupportedOperationException.class, Utility.Fields.INTEGER::index);

var testData = Map.of(//
Utility.Fields.INTEGER.id(), 0, //
Utility.Fields.STRING.id(), "Test", //
Utility.Fields.ENUM.id(), Utility.Enum.FOO, Utility.Fields.BOOLEAN.id(), true,
Utility.Fields.UNAVAILABLE.id(), false);

var integerVal = OdooUtils.getAs(Utility.Fields.INTEGER, testData, Integer.class);
var stringVal = OdooUtils.getAs(Utility.Fields.STRING, testData, String.class);
var enumVal = OdooUtils.getAsEnum(Utility.Fields.ENUM, testData, Utility.Enum.class, Utility.Enum.BAR);

assertEquals(integerVal, Integer.valueOf(0));
assertEquals(stringVal, "Test");
assertEquals(enumVal, Utility.Enum.FOO);

assertEquals(true, OdooUtils.getAsOrElse(Utility.Fields.BOOLEAN, testData, Boolean.class, false));
assertEquals("else", OdooUtils.getAsOrElse(Utility.Fields.UNAVAILABLE, testData, String.class, "else"));

assertNull(OdooUtils.getAs(Utility.Fields.INTEGER, null, Integer.class));
assertNull(OdooUtils.getAs(null, testData, Integer.class));
assertNull(OdooUtils.getAs(Utility.Fields.NOT_AVAILABLE, testData, Integer.class));

// False types
assertEquals("else", OdooUtils.getAsOrElse(Utility.Fields.INTEGER, testData, String.class, "else"));
assertEquals(Integer.valueOf(0), OdooUtils.getAsOrElse(Utility.Fields.STRING, testData, Integer.class, 0));
assertEquals(EdgeDevice.ID,
OdooUtils.getAsEnum(Utility.Fields.ENUM, testData, EdgeDevice.class, EdgeDevice.ID));
assertEquals(Utility.Enum.BAR,
OdooUtils.getAsEnum(Utility.Fields.UNAVAILABLE, testData, Utility.Enum.class, Utility.Enum.BAR));
}

}

0 comments on commit 5fc3d44

Please sign in to comment.