Skip to content

Commit

Permalink
IdCodec: Fix handling of composite ids with partial null components
Browse files Browse the repository at this point in the history
- Serialization of null value components should be "" instead of "null"
- Deserialize "" and null values to null-Id instances

356746
  • Loading branch information
paolobazzi committed Jul 19, 2023
1 parent afca6c5 commit 29b1318
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 3 deletions.
Expand Up @@ -17,6 +17,8 @@
import java.util.UUID;

import org.eclipse.scout.rt.dataobject.fixture.FixtureCompositeId;
import org.eclipse.scout.rt.dataobject.fixture.FixtureIntegerId;
import org.eclipse.scout.rt.dataobject.fixture.FixtureLongId;
import org.eclipse.scout.rt.dataobject.fixture.FixtureStringId;
import org.eclipse.scout.rt.dataobject.fixture.FixtureUuId;
import org.eclipse.scout.rt.dataobject.fixture.FixtureWrapperCompositeId;
Expand All @@ -36,6 +38,7 @@ public abstract class AbstractIdCodecTest {
protected static final UUID TEST_UUID = UUID.fromString("5833aae1-c813-4d7c-a342-56a53772a3ea");
protected static final String TEST_STRING = "foobar";
protected static final String TEST_STRING_2 = "bazäöl";
protected static final Date TEST_DATE = new Date(123456789);

/**
* @return IdCodec instance used for tests
Expand Down Expand Up @@ -104,6 +107,34 @@ public void testToQualifiedWrapperCompositeId() {
assertEquals("scout.FixtureWrapperCompositeId:foobar;5833aae1-c813-4d7c-a342-56a53772a3ea;bazäöl", ext);
}

@Test
public void testToQualifiedCompositeIdPartialNullValues() {
FixtureCompositeWithNullValuesId id1 = FixtureCompositeWithNullValuesId.of(null, UUID.fromString("711dc5d6-0a42-4f54-b79c-50110b9e742a"));
assertEquals("scout.FixtureCompositeWithNullValuesId:;711dc5d6-0a42-4f54-b79c-50110b9e742a", getCodec().toQualified(id1));
}

@Test
public void testToQualifiedCompositeIdPartialNullStringValuesA() {
FixtureCompositeWithNullStringValuesId id1 = FixtureCompositeWithNullStringValuesId.of("foo", "");
assertEquals("scout.FixtureCompositeWithNullStringValuesId:foo;", getCodec().toQualified(id1));
}

@Test
public void testToQualifiedCompositeIdPartialNullStringValuesB() {
FixtureCompositeWithNullStringValuesId id1 = FixtureCompositeWithNullStringValuesId.of("", "bar");
assertEquals("scout.FixtureCompositeWithNullStringValuesId:;bar", getCodec().toQualified(id1));
}

@Test
public void testToQualifiedCompositeIdPartialNullAllTypes() {
assertEquals("scout.FixtureCompositeWithAllTypesId:foo;;;;;", getCodec().toQualified(FixtureCompositeWithAllTypesId.of("foo", null, null, null, null, null)));
assertEquals("scout.FixtureCompositeWithAllTypesId:;5833aae1-c813-4d7c-a342-56a53772a3ea;;;;", getCodec().toQualified(FixtureCompositeWithAllTypesId.of(null, TEST_UUID, null, null, null, null)));
assertEquals("scout.FixtureCompositeWithAllTypesId:;;42;;;", getCodec().toQualified(FixtureCompositeWithAllTypesId.of(null, null, 42L, null, null, null)));
assertEquals("scout.FixtureCompositeWithAllTypesId:;;;43;;", getCodec().toQualified(FixtureCompositeWithAllTypesId.of(null, null, null, 43, null, null)));
assertEquals("scout.FixtureCompositeWithAllTypesId:;;;;123456789;", getCodec().toQualified(FixtureCompositeWithAllTypesId.of(null, null, null, null, TEST_DATE, null)));
assertEquals("scout.FixtureCompositeWithAllTypesId:;;;;;de-DE", getCodec().toQualified(FixtureCompositeWithAllTypesId.of(null, null, null, null, null, Locale.GERMANY)));
}

@Test
public void testToQualifiedIdNullValue() {
assertNull(getCodec().toQualified(null));
Expand Down Expand Up @@ -169,6 +200,34 @@ public void testToUnqualifiedWrapperCompositeId() {
assertEquals("foobar;5833aae1-c813-4d7c-a342-56a53772a3ea;bazäöl", ext);
}

@Test
public void testToUnqualifiedCompositeIdPartialNullValues() {
FixtureCompositeWithNullValuesId id1 = FixtureCompositeWithNullValuesId.of(null, UUID.fromString("711dc5d6-0a42-4f54-b79c-50110b9e742a"));
assertEquals(";711dc5d6-0a42-4f54-b79c-50110b9e742a", getCodec().toUnqualified(id1));
}

@Test
public void testToUnqualifiedCompositeIdPartialNullStringValuesA() {
FixtureCompositeWithNullStringValuesId id1 = FixtureCompositeWithNullStringValuesId.of("foo", "");
assertEquals("foo;", getCodec().toUnqualified(id1));
}

@Test
public void testToUnqualifiedCompositeIdPartialNullStringValuesB() {
FixtureCompositeWithNullStringValuesId id1 = FixtureCompositeWithNullStringValuesId.of("", "bar");
assertEquals(";bar", getCodec().toUnqualified(id1));
}

@Test
public void testToUnqualifiedCompositeIdPartialNullAllTypes() {
assertEquals("foo;;;;;", getCodec().toUnqualified(FixtureCompositeWithAllTypesId.of("foo", null, null, null, null, null)));
assertEquals(";5833aae1-c813-4d7c-a342-56a53772a3ea;;;;", getCodec().toUnqualified(FixtureCompositeWithAllTypesId.of(null, TEST_UUID, null, null, null, null)));
assertEquals(";;42;;;", getCodec().toUnqualified(FixtureCompositeWithAllTypesId.of(null, null, 42L, null, null, null)));
assertEquals(";;;43;;", getCodec().toUnqualified(FixtureCompositeWithAllTypesId.of(null, null, null, 43, null, null)));
assertEquals(";;;;123456789;", getCodec().toUnqualified(FixtureCompositeWithAllTypesId.of(null, null, null, null, TEST_DATE, null)));
assertEquals(";;;;;de-DE", getCodec().toUnqualified(FixtureCompositeWithAllTypesId.of(null, null, null, null, null, Locale.GERMANY)));
}

@Test
public void testToUnqualifiedIdNullValue() {
assertNull(getCodec().toUnqualified(null));
Expand Down Expand Up @@ -266,6 +325,7 @@ public void testFromQualifiedCompositeIdAllEmptyValue() {
assertNull(getCodec().fromQualified("scout.FixtureCompositeWithNullStringValuesId:;"));
assertNull(getCodec().fromQualified("scout.FixtureCompositeWithNullStringValuesId:"));
assertNull(getCodec().fromQualified("scout.FixtureCompositeId:"));
assertNull(getCodec().fromQualified("scout.FixtureCompositeId:;"));
}

@Test
Expand Down Expand Up @@ -293,11 +353,22 @@ public void testFromQualifiedCompositeIdPartialNullStringValuesB() {
assertEquals(id1, id3);
}

@Test
public void testFromQualifiedCompositeIdPartialNullAllTypes() {
assertEquals(FixtureCompositeWithAllTypesId.of("foo", null, null, null, null, null), getCodec().fromQualified("scout.FixtureCompositeWithAllTypesId:foo;;;;;"));
assertEquals(FixtureCompositeWithAllTypesId.of(null, TEST_UUID, null, null, null, null), getCodec().fromQualified("scout.FixtureCompositeWithAllTypesId:;5833aae1-c813-4d7c-a342-56a53772a3ea;;;;"));
assertEquals(FixtureCompositeWithAllTypesId.of(null, null, 42L, null, null, null), getCodec().fromQualified("scout.FixtureCompositeWithAllTypesId:;;42;;;"));
assertEquals(FixtureCompositeWithAllTypesId.of(null, null, null, 43, null, null), getCodec().fromQualified("scout.FixtureCompositeWithAllTypesId:;;;43;;"));
assertEquals(FixtureCompositeWithAllTypesId.of(null, null, null, null, TEST_DATE, null), getCodec().fromQualified("scout.FixtureCompositeWithAllTypesId:;;;;123456789;"));
assertEquals(FixtureCompositeWithAllTypesId.of(null, null, null, null, null, Locale.GERMANY), getCodec().fromQualified("scout.FixtureCompositeWithAllTypesId:;;;;;de-DE"));
}

@Test
public void testFromQualifiedCompositeIdWrongNumberOfComponents() {
assertThrows(PlatformException.class, () -> getCodec().fromQualified("scout.FixtureCompositeId:;"));
assertThrows(PlatformException.class, () -> getCodec().fromQualified("scout.FixtureCompositeId:foo"));
assertThrows(PlatformException.class, () -> getCodec().fromQualified("scout.FixtureCompositeId:foo;" + TEST_UUID + ";foo"));
assertThrows(PlatformException.class, () -> getCodec().fromQualified("scout.FixtureCompositeWithAllTypesId:;"));
assertThrows(PlatformException.class, () -> getCodec().fromQualified("scout.FixtureCompositeWithAllTypesId:;;;"));
}

@Test
Expand Down Expand Up @@ -386,19 +457,35 @@ public void testFromUnqualifiedCompositeIdPartialEmptyValue() {
FixtureCompositeId id1 = FixtureCompositeId.of("", TEST_UUID);
IId id2 = getCodec().fromUnqualified(FixtureCompositeId.class, ";" + TEST_UUID);
assertEquals(id1, id2);

FixtureCompositeId id3 = FixtureCompositeId.of("abc", null);
IId id4 = getCodec().fromUnqualified(FixtureCompositeId.class, "foo;");
assertEquals(id3, id4);
}

@Test
public void testFromUnqualifiedCompositeIdAllEmptyValue() {
assertNull(FixtureCompositeId.of("", null));
assertNull(getCodec().fromUnqualified(FixtureCompositeId.class, ""));
assertNull(getCodec().fromUnqualified(FixtureCompositeId.class, ";"));
}

@Test
public void testFromUnqualifiedCompositeIdPartialNullAllTypes() {
assertEquals(FixtureCompositeWithAllTypesId.of("foo", null, null, null, null, null), getCodec().fromUnqualified(FixtureCompositeWithAllTypesId.class, "foo;;;;;"));
assertEquals(FixtureCompositeWithAllTypesId.of(null, TEST_UUID, null, null, null, null), getCodec().fromUnqualified(FixtureCompositeWithAllTypesId.class, ";5833aae1-c813-4d7c-a342-56a53772a3ea;;;;"));
assertEquals(FixtureCompositeWithAllTypesId.of(null, null, 42L, null, null, null), getCodec().fromUnqualified(FixtureCompositeWithAllTypesId.class, ";;42;;;"));
assertEquals(FixtureCompositeWithAllTypesId.of(null, null, null, 43, null, null), getCodec().fromUnqualified(FixtureCompositeWithAllTypesId.class, ";;;43;;"));
assertEquals(FixtureCompositeWithAllTypesId.of(null, null, null, null, TEST_DATE, null), getCodec().fromUnqualified(FixtureCompositeWithAllTypesId.class, ";;;;123456789;"));
assertEquals(FixtureCompositeWithAllTypesId.of(null, null, null, null, null, Locale.GERMANY), getCodec().fromUnqualified(FixtureCompositeWithAllTypesId.class, ";;;;;de-DE"));
}

@Test
public void testFromUnqualifiedCompositeIdWrongNumberOfComponents() {
assertThrows(PlatformException.class, () -> getCodec().fromUnqualified(FixtureCompositeId.class, ";"));
assertThrows(PlatformException.class, () -> getCodec().fromUnqualified(FixtureCompositeId.class, "foo"));
assertThrows(PlatformException.class, () -> getCodec().fromUnqualified(FixtureCompositeId.class, "foo;" + TEST_UUID + ";foo"));
assertThrows(PlatformException.class, () -> getCodec().fromUnqualified(FixtureCompositeWithAllTypesId.class, ";"));
assertThrows(PlatformException.class, () -> getCodec().fromUnqualified(FixtureCompositeWithAllTypesId.class, ";;;"));
}

@Test(expected = PlatformException.class)
Expand Down Expand Up @@ -506,6 +593,30 @@ public static FixtureCompositeWithNullValuesId of(FixtureStringId c1, FixtureUuI
}
}

@IdTypeName("scout.FixtureCompositeWithAllTypesId")
protected static final class FixtureCompositeWithAllTypesId extends AbstractCompositeId {
private static final long serialVersionUID = 1L;

private FixtureCompositeWithAllTypesId(FixtureStringId c1, FixtureUuId c2, FixtureLongId c3, FixtureIntegerId c4, FixtureDateId c5, FixtureLocaleId c6) {
super(c1, c2, c3, c4, c5, c6);
}

@RawTypes
public static FixtureCompositeWithAllTypesId of(String c1, UUID c2, Long c3, Integer c4, Date c5, Locale c6) {
if (StringUtility.isNullOrEmpty(c1) && c2 == null && c3 == null && c4 == null && c5 == null && c6 == null) {
return null;
}
return new FixtureCompositeWithAllTypesId(FixtureStringId.of(c1), FixtureUuId.of(c2), FixtureLongId.of(c3), FixtureIntegerId.of(c4), FixtureDateId.of(c5), FixtureLocaleId.of(c6));
}

public static FixtureCompositeWithAllTypesId of(FixtureStringId c1, FixtureUuId c2, FixtureLongId c3, FixtureIntegerId c4, FixtureDateId c5, FixtureLocaleId c6) {
if (c1 == null && c2 == null) {
return null;
}
return new FixtureCompositeWithAllTypesId(c1, c2, c3, c4, c5, c6);
}
}

@IdTypeName("scout.FixtureLocaleId")
protected static final class FixtureLocaleId extends AbstractRootId<Locale> {
private static final long serialVersionUID = 1L;
Expand Down
Expand Up @@ -124,6 +124,11 @@ public void testCompositeIdByComponents_NullValue() {
List<? extends IId> id2Components = id2.unwrap();
assertEquals("abc", id2Components.get(0).unwrap());
assertNull(id2Components.get(1));

FixtureCompositeWithNullValuesId id3 = BEANS.get(IdFactory.class).createInternal(FixtureCompositeWithNullValuesId.class, null, UUID.fromString("144a0317-8cb5-40b2-981f-1fae0781715f"));
List<? extends IId> id3Components = id3.unwrap();
assertNull(id3Components.get(0));
assertEquals(UUID.fromString("144a0317-8cb5-40b2-981f-1fae0781715f"), id3Components.get(1).unwrap());
}

@Test
Expand Down
Expand Up @@ -97,6 +97,7 @@ else if (id instanceof ICompositeId) {
List<? extends IId> components = ((ICompositeId) id).unwrap();
return components.stream()
.map(this::toUnqualified)
.map(s -> s == null ? "" : s) // empty string if component is null just in case of composite id
.collect(Collectors.joining(";"));
}
return handleToUnqualifiedUnknownIdType(id);
Expand Down Expand Up @@ -246,7 +247,13 @@ protected Object[] parseComponents(Class<? extends IId> idClass, String[] rawCom
throw new PlatformException("Missing raw type mapper for wrapped type {}, id type {}", type, idClass);
}
try {
components[i] = mapper.apply(rawComponents[i]);
String raw = rawComponents[i];
if (StringUtility.isNullOrEmpty(raw)) {
components[i] = null;
}
else {
components[i] = mapper.apply(raw);
}
}
catch (Exception e) {
throw new PlatformException("Failed to parse component value={}, rawType={}, idType={}", rawComponents[i], type.getName(), idClass.getName(), e);
Expand Down

0 comments on commit 29b1318

Please sign in to comment.