Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CelMutableCreateMap #294

Merged
merged 1 commit into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions common/src/main/java/dev/cel/common/ast/CelMutableExpr.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ public CelMutableCreateStruct createStruct() {
return (CelMutableCreateStruct) exprValue;
}

public CelMutableCreateMap createMap() {
checkExprKind(Kind.CREATE_MAP);
return (CelMutableCreateMap) exprValue;
}

public void setConstant(CelConstant constant) {
this.exprKind = ExprKind.Kind.CONSTANT;
this.exprValue = checkNotNull(constant);
Expand Down Expand Up @@ -118,6 +123,11 @@ public void setCreateStruct(CelMutableCreateStruct createStruct) {
this.exprValue = checkNotNull(createStruct);
}

public void setCreateMap(CelMutableCreateMap createMap) {
this.exprKind = ExprKind.Kind.CREATE_MAP;
this.exprValue = checkNotNull(createMap);
}

/** A mutable identifier expression. */
public static final class CelMutableIdent {
private String name = "";
Expand Down Expand Up @@ -549,6 +559,145 @@ private CelMutableCreateStruct(String messageName, List<CelMutableCreateStruct.E
}
}

/**
* A mutable map creation expression.
*
* <p>Maps are constructed as `{'key_name': 'value'}`.
*/
public static final class CelMutableCreateMap {
private List<CelMutableCreateMap.Entry> entries;

public List<CelMutableCreateMap.Entry> entries() {
return entries;
}

public void setEntries(List<CelMutableCreateMap.Entry> entries) {
this.entries = checkNotNull(entries);
}

public void setEntry(int index, CelMutableCreateMap.Entry entry) {
checkArgument(index >= 0 && index < entries().size());
entries.set(index, checkNotNull(entry));
}

/** Represents an entry of the map */
public static final class Entry {
private long id;
private CelMutableExpr key;
private CelMutableExpr value;
private boolean optionalEntry;

public long id() {
return id;
}

public void setId(long id) {
this.id = id;
}

public CelMutableExpr key() {
return key;
}

public void setKey(CelMutableExpr key) {
this.key = checkNotNull(key);
}

public CelMutableExpr value() {
return value;
}

public void setValue(CelMutableExpr value) {
this.value = checkNotNull(value);
}

public boolean optionalEntry() {
return optionalEntry;
}

public void setOptionalEntry(boolean optionalEntry) {
this.optionalEntry = optionalEntry;
}

@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Entry) {
Entry that = (Entry) obj;
return this.id == that.id()
&& this.key.equals(that.key())
&& this.value.equals(that.value())
&& this.optionalEntry == that.optionalEntry();
}
return false;
}

@Override
public int hashCode() {
int h = 1;
h *= 1000003;
h ^= (int) ((id >>> 32) ^ id);
h *= 1000003;
h ^= key.hashCode();
h *= 1000003;
h ^= value.hashCode();
h *= 1000003;
h ^= optionalEntry ? 1231 : 1237;
return h;
}

public static Entry create(CelMutableExpr key, CelMutableExpr value) {
return create(0, key, value, false);
}

public static Entry create(long id, CelMutableExpr key, CelMutableExpr value) {
return create(id, key, value, false);
}

public static Entry create(
long id, CelMutableExpr key, CelMutableExpr value, boolean optionalEntry) {
return new Entry(id, key, value, optionalEntry);
}

private Entry(long id, CelMutableExpr key, CelMutableExpr value, boolean optionalEntry) {
this.id = id;
this.key = checkNotNull(key);
this.value = checkNotNull(value);
this.optionalEntry = optionalEntry;
}
}

@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof CelMutableCreateMap) {
CelMutableCreateMap that = (CelMutableCreateMap) obj;
return this.entries.equals(that.entries());
}
return false;
}

@Override
public int hashCode() {
int h = 1;
h *= 1000003;
h ^= entries.hashCode();
return h;
}

public static CelMutableCreateMap create(List<CelMutableCreateMap.Entry> entries) {
return new CelMutableCreateMap(new ArrayList<>(entries));
}

private CelMutableCreateMap(List<CelMutableCreateMap.Entry> entries) {
this.entries = checkNotNull(entries);
}
}

public static CelMutableExpr ofNotSet() {
return ofNotSet(0L);
}
Expand Down Expand Up @@ -605,6 +754,14 @@ public static CelMutableExpr ofCreateStruct(long id, CelMutableCreateStruct muta
return new CelMutableExpr(id, mutableCreateStruct);
}

public static CelMutableExpr ofCreateMap(CelMutableCreateMap mutableCreateMap) {
return ofCreateMap(0, mutableCreateMap);
}

public static CelMutableExpr ofCreateMap(long id, CelMutableCreateMap mutableCreateMap) {
return new CelMutableExpr(id, mutableCreateMap);
}

private CelMutableExpr(long id, CelConstant mutableConstant) {
this.id = id;
setConstant(mutableConstant);
Expand Down Expand Up @@ -635,6 +792,11 @@ private CelMutableExpr(long id, CelMutableCreateStruct mutableCreateStruct) {
setCreateStruct(mutableCreateStruct);
}

private CelMutableExpr(long id, CelMutableCreateMap mutableCreateMap) {
this.id = id;
setCreateMap(mutableCreateMap);
}

private CelMutableExpr(long id) {
this();
this.id = id;
Expand Down Expand Up @@ -662,6 +824,7 @@ private Object exprValue() {
case CREATE_STRUCT:
return createStruct();
case CREATE_MAP:
return createMap();
case COMPREHENSION:
// fall-through (not implemented yet)
}
Expand Down
111 changes: 110 additions & 1 deletion common/src/test/java/dev/cel/common/ast/CelMutableExprTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import dev.cel.common.ast.CelExpr.ExprKind.Kind;
import dev.cel.common.ast.CelMutableExpr.CelMutableCall;
import dev.cel.common.ast.CelMutableExpr.CelMutableCreateList;
import dev.cel.common.ast.CelMutableExpr.CelMutableCreateMap;
import dev.cel.common.ast.CelMutableExpr.CelMutableCreateStruct;
import dev.cel.common.ast.CelMutableExpr.CelMutableIdent;
import dev.cel.common.ast.CelMutableExpr.CelMutableSelect;
Expand Down Expand Up @@ -373,6 +374,81 @@ public void mutableCreateStructEntry_setters() {
2L, "field2", CelMutableExpr.ofConstant(CelConstant.ofValue("value2")), true));
}

@Test
public void ofCreateMap() {
CelMutableExpr mutableExpr =
CelMutableExpr.ofCreateMap(CelMutableCreateMap.create(ImmutableList.of()));

assertThat(mutableExpr.id()).isEqualTo(0L);
assertThat(mutableExpr.createMap().entries()).isEmpty();
}

@Test
public void ofCreateMap_withId() {
CelMutableExpr mutableExpr =
CelMutableExpr.ofCreateMap(
9L,
CelMutableCreateMap.create(
ImmutableList.of(
CelMutableCreateMap.Entry.create(
10L,
CelMutableExpr.ofConstant(CelConstant.ofValue("key")),
CelMutableExpr.ofConstant(CelConstant.ofValue("value")),
/* optionalEntry= */ true))));

assertThat(mutableExpr.id()).isEqualTo(9L);
assertThat(mutableExpr.createMap().entries())
.containsExactly(
CelMutableCreateMap.Entry.create(
10L,
CelMutableExpr.ofConstant(CelConstant.ofValue("key")),
CelMutableExpr.ofConstant(CelConstant.ofValue("value")),
/* optionalEntry= */ true));
}

@Test
public void mutableCreateMap_setEntryAtIndex() {
CelMutableCreateMap createMap =
CelMutableCreateMap.create(
ImmutableList.of(
CelMutableCreateMap.Entry.create(
10L,
CelMutableExpr.ofConstant(CelConstant.ofValue("key")),
CelMutableExpr.ofConstant(CelConstant.ofValue("value")))));
CelMutableCreateMap.Entry newEntry =
CelMutableCreateMap.Entry.create(
2L,
CelMutableExpr.ofConstant(CelConstant.ofValue("key2")),
CelMutableExpr.ofConstant(CelConstant.ofValue("value2")),
/* optionalEntry= */ true);

createMap.setEntry(0, newEntry);

assertThat(createMap.entries()).containsExactly(newEntry);
}

@Test
public void mutableCreateMapEntry_setters() {
CelMutableCreateMap.Entry createMapEntry =
CelMutableCreateMap.Entry.create(
1L,
CelMutableExpr.ofConstant(CelConstant.ofValue("key")),
CelMutableExpr.ofConstant(CelConstant.ofValue("value")));

createMapEntry.setId(2L);
createMapEntry.setKey(CelMutableExpr.ofConstant(CelConstant.ofValue("key2")));
createMapEntry.setValue(CelMutableExpr.ofConstant(CelConstant.ofValue("value2")));
createMapEntry.setOptionalEntry(true);

assertThat(createMapEntry)
.isEqualTo(
CelMutableCreateMap.Entry.create(
2L,
CelMutableExpr.ofConstant(CelConstant.ofValue("key2")),
CelMutableExpr.ofConstant(CelConstant.ofValue("value2")),
true));
}

@Test
public void equalityTest() {
new EqualsTester()
Expand Down Expand Up @@ -441,6 +517,23 @@ public void equalityTest() {
"field",
CelMutableExpr.ofConstant(CelConstant.ofValue("value")),
/* optionalEntry= */ true)))))
.addEqualityGroup(
CelMutableExpr.ofCreateMap(CelMutableCreateMap.create(ImmutableList.of())))
.addEqualityGroup(
CelMutableCreateMap.create(
ImmutableList.of(
CelMutableCreateMap.Entry.create(
9L,
CelMutableExpr.ofConstant(CelConstant.ofValue("key")),
CelMutableExpr.ofConstant(CelConstant.ofValue("value")),
/* optionalEntry= */ true))),
CelMutableCreateMap.create(
ImmutableList.of(
CelMutableCreateMap.Entry.create(
9L,
CelMutableExpr.ofConstant(CelConstant.ofValue("key")),
CelMutableExpr.ofConstant(CelConstant.ofValue("value")),
/* optionalEntry= */ true))))
.testEquals();
}

Expand All @@ -454,7 +547,9 @@ private enum MutableExprKindTestCase {
CREATE_LIST(CelMutableExpr.ofCreateList(CelMutableCreateList.create())),
CREATE_STRUCT(
CelMutableExpr.ofCreateStruct(
CelMutableCreateStruct.create("message", ImmutableList.of())));
CelMutableCreateStruct.create("message", ImmutableList.of()))),
CREATE_MAP(CelMutableExpr.ofCreateMap(CelMutableCreateMap.create(ImmutableList.of()))),
;

private final CelMutableExpr mutableExpr;

Expand Down Expand Up @@ -487,6 +582,9 @@ public void getExprValue_invalidKind_throws(@TestParameter MutableExprKindTestCa
if (!testCaseKind.equals(Kind.CREATE_STRUCT)) {
assertThrows(IllegalArgumentException.class, testCase.mutableExpr::createStruct);
}
if (!testCaseKind.equals(Kind.CREATE_MAP)) {
assertThrows(IllegalArgumentException.class, testCase.mutableExpr::createMap);
}
}

@SuppressWarnings("Immutable") // Mutable by design
Expand Down Expand Up @@ -526,6 +624,17 @@ private enum HashCodeTestCase {
CelMutableExpr.ofConstant(CelConstant.ofValue("value")),
/* optionalEntry= */ true)))),
2064611987),
CREATE_MAP(
CelMutableExpr.ofCreateMap(
8L,
CelMutableCreateMap.create(
ImmutableList.of(
CelMutableCreateMap.Entry.create(
9L,
CelMutableExpr.ofConstant(CelConstant.ofValue("key")),
CelMutableExpr.ofConstant(CelConstant.ofValue("value")),
/* optionalEntry= */ true)))),
1260717292),
;

private final CelMutableExpr mutableExpr;
Expand Down
Loading