Skip to content

Commit 16c2364

Browse files
Introduce Values to support expressions (#409)
## What is the goal of this PR? Introduce the 'Value' type, which is returned as the result of an expression's computation. This change follows from typedb/typeql#260, which outlines the capabilities of the new expression syntax. Values (representing any of Long, Double, Boolean, String, or DateTime) are returned as part of `ConceptMap` answers and are subtypes of `Concept` for the time being. Their main API is made of the `.getValue()` method and `.getValueType()` method, along with all the standard safe downcasting methods to convert a `Concept` into a `Value`, using `Concept.isValue()` and `Concept.asValue()`. We also move the import location of `ValueType` from being nested in `AttributeType` to `Concept`. ## What are the changes implemented in this PR? * Introduces the `Value` concept and the required `ValueImpl` that implements it * Refactor `ValueType` to no longer live within `AttributeType` - now it exists in `Concept.ValueType` * Updates the test framework for tests involving values, including the new `ExpressionTest` behaviour scenarios, which we also add to CI
1 parent 220d30d commit 16c2364

23 files changed

+751
-200
lines changed

.factory/automation.yml

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ build:
125125
bazel run @vaticle_dependencies//distribution/artifact:create-netrc
126126
.factory/test-core.sh //test/behaviour/typeql/language/match/... --test_output=errors
127127
.factory/test-core.sh //test/behaviour/typeql/language/get/... --test_output=errors
128+
.factory/test-core.sh //test/behaviour/typeql/language/expression/... --test_output=errors
128129
test-behaviour-match-cluster:
129130
image: vaticle-ubuntu-22.04
130131
dependencies:
@@ -136,6 +137,7 @@ build:
136137
bazel run @vaticle_dependencies//distribution/artifact:create-netrc
137138
.factory/test-cluster.sh //test/behaviour/typeql/language/match/... --test_output=errors
138139
.factory/test-cluster.sh //test/behaviour/typeql/language/get/... --test_output=errors
140+
.factory/test-core.sh //test/behaviour/typeql/language/expression/... --test_output=errors
139141
test-behaviour-writable-core:
140142
image: vaticle-ubuntu-22.04
141143
dependencies:

api/concept/Concept.java

+83
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import com.eclipsesource.json.JsonObject;
2525
import com.vaticle.typedb.client.api.TypeDBTransaction;
26+
import com.vaticle.typedb.client.api.concept.value.Value;
2627
import com.vaticle.typedb.client.api.concept.thing.Attribute;
2728
import com.vaticle.typedb.client.api.concept.thing.Entity;
2829
import com.vaticle.typedb.client.api.concept.thing.Relation;
@@ -33,8 +34,13 @@
3334
import com.vaticle.typedb.client.api.concept.type.RoleType;
3435
import com.vaticle.typedb.client.api.concept.type.ThingType;
3536
import com.vaticle.typedb.client.api.concept.type.Type;
37+
import com.vaticle.typedb.client.common.exception.TypeDBClientException;
38+
import com.vaticle.typedb.protocol.ConceptProto;
3639

3740
import javax.annotation.CheckReturnValue;
41+
import java.time.LocalDateTime;
42+
43+
import static com.vaticle.typedb.client.common.exception.ErrorMessage.Concept.BAD_VALUE_TYPE;
3844

3945
public interface Concept {
4046

@@ -88,6 +94,11 @@ default boolean isRelation() {
8894
return false;
8995
}
9096

97+
@CheckReturnValue
98+
default boolean isValue() {
99+
return false;
100+
}
101+
91102
@CheckReturnValue
92103
Type asType();
93104

@@ -118,6 +129,9 @@ default boolean isRelation() {
118129
@CheckReturnValue
119130
Relation asRelation();
120131

132+
@CheckReturnValue
133+
Value<?> asValue();
134+
121135
@CheckReturnValue
122136
Remote asRemote(TypeDBTransaction transaction);
123137

@@ -174,4 +188,73 @@ interface Remote extends Concept {
174188
@CheckReturnValue
175189
Attribute.Remote<?> asAttribute();
176190
}
191+
192+
enum ValueType {
193+
194+
OBJECT(Object.class),
195+
BOOLEAN(AttributeType.Boolean.class),
196+
LONG(AttributeType.Long.class),
197+
DOUBLE(AttributeType.Double.class),
198+
STRING(AttributeType.String.class),
199+
DATETIME(LocalDateTime.class);
200+
201+
private final Class<?> valueClass;
202+
203+
ValueType(Class<?> valueClass) {
204+
this.valueClass = valueClass;
205+
}
206+
207+
@CheckReturnValue
208+
public static ValueType of(ConceptProto.ValueType valueType) {
209+
switch (valueType) {
210+
case BOOLEAN:
211+
return BOOLEAN;
212+
case LONG:
213+
return LONG;
214+
case DOUBLE:
215+
return DOUBLE;
216+
case STRING:
217+
return STRING;
218+
case DATETIME:
219+
return DATETIME;
220+
default:
221+
throw new TypeDBClientException(BAD_VALUE_TYPE, valueType);
222+
}
223+
}
224+
225+
@CheckReturnValue
226+
public static ValueType of(Class<?> valueClass) {
227+
for (ValueType t : ValueType.values()) {
228+
if (t.valueClass == valueClass) {
229+
return t;
230+
}
231+
}
232+
throw new TypeDBClientException(BAD_VALUE_TYPE);
233+
}
234+
235+
@CheckReturnValue
236+
public Class<?> valueClass() {
237+
return valueClass;
238+
}
239+
240+
@CheckReturnValue
241+
public ConceptProto.ValueType proto() {
242+
switch (this) {
243+
case OBJECT:
244+
return ConceptProto.ValueType.OBJECT;
245+
case BOOLEAN:
246+
return ConceptProto.ValueType.BOOLEAN;
247+
case LONG:
248+
return ConceptProto.ValueType.LONG;
249+
case DOUBLE:
250+
return ConceptProto.ValueType.DOUBLE;
251+
case STRING:
252+
return ConceptProto.ValueType.STRING;
253+
case DATETIME:
254+
return ConceptProto.ValueType.DATETIME;
255+
default:
256+
return ConceptProto.ValueType.UNRECOGNIZED;
257+
}
258+
}
259+
}
177260
}

api/concept/type/AttributeType.java

-69
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323

2424
import com.vaticle.typedb.client.api.TypeDBTransaction;
2525
import com.vaticle.typedb.client.api.concept.thing.Attribute;
26-
import com.vaticle.typedb.client.common.exception.TypeDBClientException;
27-
import com.vaticle.typedb.protocol.ConceptProto;
2826
import com.vaticle.typeql.lang.common.TypeQLToken;
2927

3028
import javax.annotation.CheckReturnValue;
@@ -33,8 +31,6 @@
3331
import java.util.Set;
3432
import java.util.stream.Stream;
3533

36-
import static com.vaticle.typedb.client.common.exception.ErrorMessage.Concept.BAD_VALUE_TYPE;
37-
3834
public interface AttributeType extends ThingType {
3935

4036
@CheckReturnValue
@@ -92,71 +88,6 @@ default boolean isDateTime() {
9288
@CheckReturnValue
9389
AttributeType.DateTime asDateTime();
9490

95-
enum ValueType {
96-
97-
OBJECT(Object.class, false, false),
98-
BOOLEAN(Boolean.class, true, false),
99-
LONG(Long.class, true, true),
100-
DOUBLE(Double.class, true, false),
101-
STRING(String.class, true, true),
102-
DATETIME(LocalDateTime.class, true, true);
103-
104-
private final Class<?> valueClass;
105-
private final boolean isWritable;
106-
private final boolean isKeyable;
107-
108-
ValueType(Class<?> valueClass, boolean isWritable, boolean isKeyable) {
109-
this.valueClass = valueClass;
110-
this.isWritable = isWritable;
111-
this.isKeyable = isKeyable;
112-
}
113-
114-
@CheckReturnValue
115-
public static ValueType of(Class<?> valueClass) {
116-
for (ValueType t : ValueType.values()) {
117-
if (t.valueClass == valueClass) {
118-
return t;
119-
}
120-
}
121-
throw new TypeDBClientException(BAD_VALUE_TYPE);
122-
}
123-
124-
@CheckReturnValue
125-
public Class<?> valueClass() {
126-
return valueClass;
127-
}
128-
129-
@CheckReturnValue
130-
public boolean isWritable() {
131-
return isWritable;
132-
}
133-
134-
@CheckReturnValue
135-
public boolean isKeyable() {
136-
return isKeyable;
137-
}
138-
139-
@CheckReturnValue
140-
public ConceptProto.AttributeType.ValueType proto() {
141-
switch (this) {
142-
case OBJECT:
143-
return ConceptProto.AttributeType.ValueType.OBJECT;
144-
case BOOLEAN:
145-
return ConceptProto.AttributeType.ValueType.BOOLEAN;
146-
case LONG:
147-
return ConceptProto.AttributeType.ValueType.LONG;
148-
case DOUBLE:
149-
return ConceptProto.AttributeType.ValueType.DOUBLE;
150-
case STRING:
151-
return ConceptProto.AttributeType.ValueType.STRING;
152-
case DATETIME:
153-
return ConceptProto.AttributeType.ValueType.DATETIME;
154-
default:
155-
return ConceptProto.AttributeType.ValueType.UNRECOGNIZED;
156-
}
157-
}
158-
}
159-
16091
interface Remote extends ThingType.Remote, AttributeType {
16192

16293
void setSupertype(AttributeType attributeType);

api/concept/type/ThingType.java

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
import com.vaticle.typedb.client.api.TypeDBTransaction;
2525
import com.vaticle.typedb.client.api.concept.thing.Thing;
26-
import com.vaticle.typedb.client.api.concept.type.AttributeType.ValueType;
2726
import com.vaticle.typeql.lang.common.TypeQLToken;
2827

2928
import javax.annotation.CheckReturnValue;

api/concept/type/Type.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
import com.vaticle.typedb.client.api.concept.Concept;
2828
import com.vaticle.typedb.client.common.Label;
2929

30-
import java.util.stream.Stream;
3130
import javax.annotation.CheckReturnValue;
3231
import javax.annotation.Nullable;
32+
import java.util.stream.Stream;
3333

3434
public interface Type extends Concept {
3535

api/concept/value/Value.java

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* Copyright (C) 2022 Vaticle
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
package com.vaticle.typedb.client.api.concept.value;
23+
24+
import com.eclipsesource.json.Json;
25+
import com.eclipsesource.json.JsonObject;
26+
import com.eclipsesource.json.JsonValue;
27+
import com.vaticle.typedb.client.api.concept.Concept;
28+
import com.vaticle.typedb.client.api.concept.type.Type;
29+
import com.vaticle.typedb.client.common.exception.TypeDBClientException;
30+
31+
import javax.annotation.CheckReturnValue;
32+
33+
import static com.vaticle.typedb.client.api.concept.thing.Attribute.ISO_LOCAL_DATE_TIME_MILLIS;
34+
import static com.vaticle.typedb.client.common.exception.ErrorMessage.Internal.ILLEGAL_STATE;
35+
36+
public interface Value<VALUE> extends Concept {
37+
38+
@CheckReturnValue
39+
Type.ValueType getValueType();
40+
41+
@CheckReturnValue
42+
VALUE getValue();
43+
44+
@Override
45+
@CheckReturnValue
46+
default boolean isValue() {
47+
return true;
48+
}
49+
50+
@CheckReturnValue
51+
default boolean isBoolean() {
52+
return false;
53+
}
54+
55+
@CheckReturnValue
56+
default boolean isLong() {
57+
return false;
58+
}
59+
60+
@CheckReturnValue
61+
default boolean isDouble() {
62+
return false;
63+
}
64+
65+
@CheckReturnValue
66+
default boolean isString() {
67+
return false;
68+
}
69+
70+
@CheckReturnValue
71+
default boolean isDateTime() {
72+
return false;
73+
}
74+
75+
@CheckReturnValue
76+
Value<java.lang.Boolean> asBoolean();
77+
78+
@CheckReturnValue
79+
Value<java.lang.Long> asLong();
80+
81+
@CheckReturnValue
82+
Value<java.lang.Double> asDouble();
83+
84+
@CheckReturnValue
85+
Value<java.lang.String> asString();
86+
87+
@CheckReturnValue
88+
Value<java.time.LocalDateTime> asDateTime();
89+
90+
@Override
91+
default JsonObject toJSON() {
92+
JsonValue value;
93+
switch (getValueType()) {
94+
case BOOLEAN:
95+
value = Json.value(asBoolean().getValue());
96+
break;
97+
case LONG:
98+
value = Json.value(asLong().getValue());
99+
break;
100+
case DOUBLE:
101+
value = Json.value(asDouble().getValue());
102+
break;
103+
case STRING:
104+
value = Json.value(asString().getValue());
105+
break;
106+
case DATETIME:
107+
value = Json.value(asDateTime().getValue().format(ISO_LOCAL_DATE_TIME_MILLIS));
108+
break;
109+
default:
110+
throw new TypeDBClientException(ILLEGAL_STATE);
111+
}
112+
return Json.object()
113+
.add("value_type", getValueType().name().toLowerCase())
114+
.add("value", value);
115+
}
116+
117+
interface Boolean extends Value<java.lang.Boolean> {
118+
@Override
119+
@CheckReturnValue
120+
default boolean isBoolean() {
121+
return true;
122+
}
123+
}
124+
125+
interface Long extends Value<java.lang.Long> {
126+
@Override
127+
@CheckReturnValue
128+
default boolean isLong() {
129+
return true;
130+
}
131+
}
132+
133+
interface Double extends Value<java.lang.Double> {
134+
@Override
135+
@CheckReturnValue
136+
default boolean isDouble() {
137+
return true;
138+
}
139+
}
140+
141+
interface String extends Value<java.lang.String> {
142+
@Override
143+
@CheckReturnValue
144+
default boolean isString() {
145+
return true;
146+
}
147+
}
148+
149+
interface DateTime extends Value<java.time.LocalDateTime> {
150+
@Override
151+
@CheckReturnValue
152+
default boolean isDateTime() {
153+
return true;
154+
}
155+
}
156+
}

0 commit comments

Comments
 (0)