diff --git a/stroom-analytics/stroom-analytics-impl/src/main/java/stroom/analytics/impl/AbstractAnalyticFieldListConsumer.java b/stroom-analytics/stroom-analytics-impl/src/main/java/stroom/analytics/impl/AbstractAnalyticFieldListConsumer.java
index 03a3dd1648f..42441491a23 100644
--- a/stroom-analytics/stroom-analytics-impl/src/main/java/stroom/analytics/impl/AbstractAnalyticFieldListConsumer.java
+++ b/stroom-analytics/stroom-analytics-impl/src/main/java/stroom/analytics/impl/AbstractAnalyticFieldListConsumer.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.analytics.impl;
import stroom.query.api.v2.SearchRequest;
diff --git a/stroom-annotation/stroom-annotation-impl-db/src/main/java/stroom/annotation/impl/db/AnnotationDaoImpl.java b/stroom-annotation/stroom-annotation-impl-db/src/main/java/stroom/annotation/impl/db/AnnotationDaoImpl.java
index 054842a29b7..33ee5e6ea4c 100644
--- a/stroom-annotation/stroom-annotation-impl-db/src/main/java/stroom/annotation/impl/db/AnnotationDaoImpl.java
+++ b/stroom-annotation/stroom-annotation-impl-db/src/main/java/stroom/annotation/impl/db/AnnotationDaoImpl.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.annotation.impl.db;
import stroom.annotation.api.AnnotationFields;
diff --git a/stroom-annotation/stroom-annotation-impl/src/main/java/stroom/annotation/impl/AnnotationReceiverDecoratorFactory.java b/stroom-annotation/stroom-annotation-impl/src/main/java/stroom/annotation/impl/AnnotationReceiverDecoratorFactory.java
index cf8f692d4d5..a397914a438 100644
--- a/stroom-annotation/stroom-annotation-impl/src/main/java/stroom/annotation/impl/AnnotationReceiverDecoratorFactory.java
+++ b/stroom-annotation/stroom-annotation-impl/src/main/java/stroom/annotation/impl/AnnotationReceiverDecoratorFactory.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.annotation.impl;
import stroom.annotation.api.AnnotationFields;
diff --git a/stroom-app/src/test/java/stroom/search/TestQueuesWithTaskContext.java b/stroom-app/src/test/java/stroom/search/TestQueuesWithTaskContext.java
index 0578575f7b4..a24d23b37cd 100644
--- a/stroom-app/src/test/java/stroom/search/TestQueuesWithTaskContext.java
+++ b/stroom-app/src/test/java/stroom/search/TestQueuesWithTaskContext.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.search;
import stroom.query.language.functions.Val;
@@ -114,8 +130,8 @@ void testTaskContext() {
} else {
try {
queue.put(new Event(1, id, Val.of(
- ValString.create("test"),
- ValString.create("test"))));
+ ValString.create("test"),
+ ValString.create("test"))));
} catch (CompleteException e) {
throw new RuntimeException(e);
}
diff --git a/stroom-index/stroom-index-impl-db/src/main/java/stroom/index/impl/db/IndexShardDaoImpl.java b/stroom-index/stroom-index-impl-db/src/main/java/stroom/index/impl/db/IndexShardDaoImpl.java
index 1fdf3f0fa97..9737c4974f3 100644
--- a/stroom-index/stroom-index-impl-db/src/main/java/stroom/index/impl/db/IndexShardDaoImpl.java
+++ b/stroom-index/stroom-index-impl-db/src/main/java/stroom/index/impl/db/IndexShardDaoImpl.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.index.impl.db;
import stroom.db.util.ExpressionMapper;
diff --git a/stroom-index/stroom-index-lucene553/src/main/java/stroom/index/lucene553/Lucene553ShardSearcher.java b/stroom-index/stroom-index-lucene553/src/main/java/stroom/index/lucene553/Lucene553ShardSearcher.java
index b81c0e87402..acb5eea11a1 100644
--- a/stroom-index/stroom-index-lucene553/src/main/java/stroom/index/lucene553/Lucene553ShardSearcher.java
+++ b/stroom-index/stroom-index-lucene553/src/main/java/stroom/index/lucene553/Lucene553ShardSearcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Crown Copyright
+ * Copyright 2016-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stroom-index/stroom-index-lucene980/src/main/java/stroom/index/lucene980/Lucene980ShardSearcher.java b/stroom-index/stroom-index-lucene980/src/main/java/stroom/index/lucene980/Lucene980ShardSearcher.java
index 2d99193208c..1b5553ba2ac 100644
--- a/stroom-index/stroom-index-lucene980/src/main/java/stroom/index/lucene980/Lucene980ShardSearcher.java
+++ b/stroom-index/stroom-index-lucene980/src/main/java/stroom/index/lucene980/Lucene980ShardSearcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Crown Copyright
+ * Copyright 2016-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stroom-meta/stroom-meta-impl-db/src/main/java/stroom/meta/impl/db/MetaDaoImpl.java b/stroom-meta/stroom-meta-impl-db/src/main/java/stroom/meta/impl/db/MetaDaoImpl.java
index 4186bd5f7d4..3558b3777d0 100644
--- a/stroom-meta/stroom-meta-impl-db/src/main/java/stroom/meta/impl/db/MetaDaoImpl.java
+++ b/stroom-meta/stroom-meta-impl-db/src/main/java/stroom/meta/impl/db/MetaDaoImpl.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.meta.impl.db;
import stroom.data.retention.api.DataRetentionConfig;
diff --git a/stroom-query/stroom-query-api/src/main/java/stroom/query/api/v2/ParamUtil.java b/stroom-query/stroom-query-api/src/main/java/stroom/query/api/v2/ParamUtil.java
index 9a9c1524ae9..fbf10cc8439 100644
--- a/stroom-query/stroom-query-api/src/main/java/stroom/query/api/v2/ParamUtil.java
+++ b/stroom-query/stroom-query-api/src/main/java/stroom/query/api/v2/ParamUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Crown Copyright
+ * Copyright 2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ public static List parse(final String string) {
}
final String trimmed = string.trim();
- if (trimmed.length() == 0) {
+ if (trimmed.isEmpty()) {
return Collections.emptyList();
}
diff --git a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/FlatResultCreator.java b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/FlatResultCreator.java
index 4c3773feeb1..71965520a75 100644
--- a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/FlatResultCreator.java
+++ b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/FlatResultCreator.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/MapDataStore.java b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/MapDataStore.java
index 1a3919a054f..4b0530b4e46 100644
--- a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/MapDataStore.java
+++ b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/MapDataStore.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -132,7 +132,7 @@ public void accept(final Val[] values) {
final boolean[] groupIndices = groupIndicesByDepth[depth];
final boolean[] valueIndices = valueIndicesByDepth[depth];
- Val[] groupValues = Val.empty();
+ Val[] groupValues = Val.emptyArray();
if (groupSize > 0) {
groupValues = new Val[groupSize];
}
diff --git a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/StoredValueKeyFactoryImpl.java b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/StoredValueKeyFactoryImpl.java
index 1ede89ed318..634e2b71e2d 100644
--- a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/StoredValueKeyFactoryImpl.java
+++ b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/StoredValueKeyFactoryImpl.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.query.common.v2;
import stroom.query.language.functions.Generator;
@@ -61,7 +77,7 @@ public Val[] getGroupValues(final int depth, final StoredValues storedValues) {
}
return values;
}
- return Val.empty();
+ return Val.emptyArray();
}
@Override
diff --git a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/AbstractDataStoreTest.java b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/AbstractDataStoreTest.java
index 2e43e48ce46..5d18337d985 100644
--- a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/AbstractDataStoreTest.java
+++ b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/AbstractDataStoreTest.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbDataStore.java b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbDataStore.java
index 497b52f6e85..88c5c433e9d 100644
--- a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbDataStore.java
+++ b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbDataStore.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbRowKeyFactoryFactory.java b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbRowKeyFactoryFactory.java
index 2ba86996cbe..b76faeaeeeb 100644
--- a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbRowKeyFactoryFactory.java
+++ b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbRowKeyFactoryFactory.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.query.common.v2;
import stroom.bytebuffer.impl6.ByteBufferFactory;
diff --git a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValHasher.java b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValHasher.java
index f7ad01a0e33..2fa06c1d79f 100644
--- a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValHasher.java
+++ b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValHasher.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.query.common.v2;
import stroom.query.language.functions.Val;
diff --git a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValueSerialisation.java b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValueSerialisation.java
index 87154596a09..ff5d5dcfffd 100644
--- a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValueSerialisation.java
+++ b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValueSerialisation.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.query.common.v2;
import stroom.bytebuffer.impl6.ByteBufferFactory;
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractFunction.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractFunction.java
index c9e23a72325..54a9ff4be05 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractFunction.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractFunction.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -39,7 +39,7 @@ abstract class AbstractFunction implements Function, Appendable {
@Override
public void setParams(final Param[] params) throws ParseException {
if (params.length < minParams || params.length > maxParams) {
- throw new ExpressionException("Invalid number of parameters supplied for '" + name + "' + function");
+ throw new ParseException("Invalid number of parameters supplied for '" + name + "' + function", 0);
}
this.params = params;
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractIncludeExclude.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractIncludeExclude.java
index 59d48f4e9ec..5714d1464b1 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractIncludeExclude.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractIncludeExclude.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@ public void setParams(final Param[] params) throws ParseException {
boolean found = false;
for (int i = 1; i < params.length && !found; i++) {
final String regex = params[i].toString();
- if (regex.length() == 0) {
+ if (regex.isEmpty()) {
throw new ParseException(
"An empty regex has been defined for argument of '" + name + "' function", 0);
}
@@ -78,7 +78,7 @@ public void setParams(final Param[] params) throws ParseException {
if (params[i] instanceof Val) {
// Test regex is valid.
final String regex = params[i].toString();
- if (regex.length() == 0) {
+ if (regex.isEmpty()) {
throw new ParseException(
"An empty regex has been defined for argument of '" + name + "' function", 0);
}
@@ -106,6 +106,10 @@ public boolean hasAggregate() {
abstract boolean inverse();
+
+ // --------------------------------------------------------------------------------
+
+
abstract static class AbstractGen extends AbstractManyChildGenerator {
AbstractGen(final Generator[] childGenerators) {
@@ -127,7 +131,7 @@ public Val eval(final StoredValues storedValues, final Supplier child
final Val v = childGenerators[i].eval(storedValues, childDataSupplier);
if (v.type().isValue()) {
final String regex = v.toString();
- if (regex.length() > 0) {
+ if (!regex.isEmpty()) {
final Pattern pattern = PatternCache.get(regex);
if (pattern.matcher(value).matches()) {
found = true;
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractManyChildFunction.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractManyChildFunction.java
index c4556c378b8..809abc2d2fa 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractManyChildFunction.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractManyChildFunction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Crown Copyright
+ * Copyright 2016-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,12 +35,9 @@ public void setParams(final Param[] params) throws ParseException {
functions = new Function[params.length];
for (int i = 0; i < params.length; i++) {
final Param param = params[i];
- if (param instanceof Function) {
- final Function func = (Function) param;
- functions[i] = func;
- } else {
- functions[i] = new StaticValueFunction((Val) param);
- }
+ functions[i] = param instanceof final Function func
+ ? func
+ : new StaticValueFunction((Val) param);
}
}
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractStringFunction.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractStringFunction.java
index d9d2144929a..f9b5ae61928 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractStringFunction.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractStringFunction.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -71,11 +71,19 @@ public boolean requiresChildData() {
abstract Operation getOperation();
+
+ // --------------------------------------------------------------------------------
+
+
interface Operation {
String apply(String value);
}
+
+ // --------------------------------------------------------------------------------
+
+
private static final class Gen extends AbstractSingleChildGenerator {
private final Operation operation;
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Contains.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Contains.java
index a470c4b6d5f..9f5fe5672cc 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Contains.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Contains.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -93,6 +93,10 @@ public boolean hasAggregate() {
return super.hasAggregate();
}
+
+ // --------------------------------------------------------------------------------
+
+
private static final class Gen extends AbstractManyChildGenerator {
Gen(final Generator[] childGenerators) {
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Count.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Count.java
index 14590dc7e0e..b191090eda6 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Count.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Count.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -62,6 +62,10 @@ public boolean hasAggregate() {
return isAggregate();
}
+
+ // --------------------------------------------------------------------------------
+
+
private static final class Gen extends AbstractNoChildGenerator {
private final CountReference countReference;
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/CountUnique.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/CountUnique.java
index d9c9acd072a..4d7da5dd11f 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/CountUnique.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/CountUnique.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Crown Copyright
+ * Copyright 2018-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
@FunctionDef(
name = CountUnique.NAME,
commonCategory = FunctionCategory.AGGREGATE,
- commonReturnType = ValLong.class,
+ commonReturnType = ValInteger.class,
commonReturnDescription = "The number of unique values",
signatures = {
@FunctionSignature(
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Decode.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Decode.java
index 6ca0a94df1c..88ef086a50b 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Decode.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Decode.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -94,7 +94,7 @@ public void setParams(final Param[] params) throws ParseException {
String newValue = params[params.length - 1].toString();
for (int i = 1; i < params.length - 1; i += 2) {
final String regex = params[i].toString();
- if (regex.length() == 0) {
+ if (regex.isEmpty()) {
throw new ParseException(
"An empty regex has been defined for argument of '" + name + "' function", 0);
}
@@ -113,7 +113,7 @@ public void setParams(final Param[] params) throws ParseException {
if (params[i] instanceof Val) {
// Test regex is valid.
final String regex = params[i].toString();
- if (regex.length() == 0) {
+ if (regex.isEmpty()) {
throw new ParseException(
"An empty regex has been defined for argument of '" + name + "' function", 0);
}
@@ -144,6 +144,10 @@ public boolean hasAggregate() {
return super.hasAggregate();
}
+
+ // --------------------------------------------------------------------------------
+
+
private static final class Gen extends AbstractManyChildGenerator {
Gen(final Generator[] childGenerators) {
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Hash.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Hash.java
index b42d264cc4a..662f638e92f 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Hash.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Hash.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,12 +18,13 @@
import stroom.query.language.functions.ref.StoredValues;
import stroom.query.language.token.Param;
-
-import com.google.common.io.BaseEncoding;
+import stroom.util.NullSafe;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
+import java.util.HexFormat;
+import java.util.Objects;
import java.util.function.Supplier;
@SuppressWarnings("unused") //Used by FunctionFactory
@@ -70,107 +71,155 @@
name = "salt",
description = "The salt value to create the hash with.",
argType = ValString.class)})})
-class Hash extends AbstractFunction {
+class Hash extends AbstractManyChildFunction {
static final String NAME = "hash";
static final String DEFAULT_ALGORITHM = "SHA-256";
+ static final MessageDigest DEFAULT_ALGORITHM_DIGEST;
+ static final Function DEFAULT_ALGORITHM_FUNC = StaticValueFunction.of(DEFAULT_ALGORITHM);
- private String algorithm = DEFAULT_ALGORITHM;
- private String salt;
-
- private Generator gen;
- private Function function;
- private boolean hasAggregate;
+ private static final HexFormat HEX_FORMAT = HexFormat.of().withLowerCase();
- public Hash(final String name) {
- super(name, 1, 3);
+ static {
+ try {
+ DEFAULT_ALGORITHM_DIGEST = MessageDigest.getInstance(DEFAULT_ALGORITHM);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
}
- private static String hash(final String value,
- final String algorithm,
- final String salt) throws NoSuchAlgorithmException {
- // Create MessageDigest object.
- final MessageDigest digest = MessageDigest.getInstance(algorithm);
- if (salt != null) {
- digest.update(salt.getBytes());
- }
+ private Generator generator;
+ private MessageDigest messageDigest;
- final byte[] arr = digest.digest(value.getBytes());
+ private boolean simple;
- // TODO: 30/01/2023 In Java17+ use HexFormat class
- return BaseEncoding.base16()
- .lowerCase()
- .encode(arr);
+ public Hash(final String name) {
+ super(name, 1, 3);
}
@Override
public void setParams(final Param[] params) throws ParseException {
super.setParams(params);
+ final int paramCount = params.length;
- if (params.length >= 2) {
- algorithm = ParamParseUtil.parseStringParam(params, 1, name);
- if (algorithm == null) {
- algorithm = DEFAULT_ALGORITHM;
- }
+ if (paramCount < 1) {
+ throw new ParseException("Expected to get at least one argument to '" + name + "' function", 0);
}
- if (params.length >= 3) {
- salt = ParamParseUtil.parseStringParam(params, 2, name);
+
+ if (paramCount > 3) {
+ throw new ParseException("Expected to get at most three arguments to '" + name + "' function", 0);
}
- try {
- // Test that the algorithm is a valid one.
- MessageDigest.getInstance(algorithm);
+ // See if this is a purely static computation.
+ simple = ParamParseUtil.supportsStaticComputation(params);
- final Param param = params[0];
- if (param instanceof Function) {
- function = (Function) param;
- hasAggregate = function.hasAggregate();
+ if (simple) {
+ // All static values, however unlikely
+ final String valueToHash = ParamParseUtil.parseStringParam(params, 0, name);
+ String algorithm = paramCount >= 2
+ ? ParamParseUtil.parseStringParam(params, 1, name)
+ : null;
+ algorithm = Objects.requireNonNullElse(algorithm, DEFAULT_ALGORITHM);
+ final String salt = paramCount == 3
+ ? ParamParseUtil.parseStringParam(params, 2, name)
+ : null;
- } else {
- final String string = param.toString();
- if (string == null) {
- throw new ParseException("Unable to convert first argument of '" + name + "' function to string",
- 0);
+ try {
+ final MessageDigest messageDigest = Objects.equals(algorithm, DEFAULT_ALGORITHM)
+ ? DEFAULT_ALGORITHM_DIGEST
+ : MessageDigest.getInstance(algorithm);
+ generator = StaticValueFunction.of(hash(valueToHash, messageDigest, salt))
+ .createGenerator();
+ } catch (NoSuchAlgorithmException e) {
+ throw new ParseException("Second argument of '" + name + "' function '" + algorithm
+ + "' is not a valid hash algorithm name.", 0);
+ }
+ } else {
+ // If we have a static algorithm param, then get the digest to hold on the
+ // generator, so we don't need to get it for each row.
+ if (paramCount >= 2) {
+ final Param algoParam = params[1];
+ if (algoParam instanceof Val val) {
+ final String algo = val.toString();
+ messageDigest = verifyAndGetAlgorithm(algo);
}
- gen = new StaticValueFunction(ValString.create(hash(string, algorithm, salt))).createGenerator();
}
- } catch (final NoSuchAlgorithmException e) {
+ }
+ }
+
+ private static String hash(final String value,
+ final String algorithm,
+ final String salt) throws ParseException {
+ MessageDigest digest = algorithm != null
+ ? verifyAndGetAlgorithm(algorithm)
+ : DEFAULT_ALGORITHM_DIGEST;
+ return hash(value, digest, salt);
+ }
+
+ private static String hash(final String value,
+ final MessageDigest messageDigest,
+ final String salt) {
+ final MessageDigest digest = Objects.requireNonNullElse(messageDigest, DEFAULT_ALGORITHM_DIGEST);
+ digest.reset();
+ if (salt != null) {
+ digest.update(salt.getBytes());
+ }
+ final byte[] arr = digest.digest(value.getBytes());
+ return HEX_FORMAT.formatHex(arr);
+ }
+
+ private static MessageDigest verifyAndGetAlgorithm(final String algorithm) throws ParseException {
+ try {
+ return MessageDigest.getInstance(algorithm);
+ } catch (NoSuchAlgorithmException e) {
throw new ParseException(e.getMessage(), 0);
}
}
@Override
public Generator createGenerator() {
- if (gen != null) {
- return gen;
+ if (generator != null) {
+ return generator;
}
-
- final Generator childGenerator = function.createGenerator();
- return new Gen(childGenerator, algorithm, salt);
+ return super.createGenerator();
}
@Override
public boolean hasAggregate() {
- return hasAggregate;
+ if (simple) {
+ return false;
+ }
+ return super.hasAggregate();
+ }
+
+ @Override
+ protected Generator createGenerator(final Generator[] childGenerators) {
+ return new ManyChildGenerator(childGenerators, messageDigest);
}
@Override
public boolean requiresChildData() {
- if (function != null) {
- return function.requiresChildData();
- }
return super.requiresChildData();
}
- private static final class Gen extends AbstractSingleChildGenerator {
- private final String algorithm;
+ // --------------------------------------------------------------------------------
+
+
+ /**
+ * For cases where the algorithm and salt are both static
+ */
+ private static final class SingleChildGenerator extends AbstractSingleChildGenerator {
+
+ private final MessageDigest messageDigest;
private final String salt;
- Gen(final Generator childGenerator, final String algorithm, final String salt) {
+ SingleChildGenerator(final Generator childGenerator,
+ final MessageDigest messageDigest,
+ final String salt) {
super(childGenerator);
- this.algorithm = algorithm;
+ this.messageDigest = messageDigest;
this.salt = salt;
}
@@ -187,8 +236,71 @@ public Val eval(final StoredValues storedValues, final Supplier child
}
try {
- return ValString.create(hash(val.toString(), algorithm, salt));
- } catch (final NoSuchAlgorithmException | RuntimeException e) {
+ return ValString.create(hash(val.toString(), messageDigest, salt));
+ } catch (final RuntimeException e) {
+ return ValErr.create(e.getMessage());
+ }
+ }
+ }
+
+
+ // --------------------------------------------------------------------------------
+
+
+ private static final class ManyChildGenerator extends AbstractManyChildGenerator {
+
+ private MessageDigest messageDigest = DEFAULT_ALGORITHM_DIGEST;
+
+ ManyChildGenerator(final Generator[] childGenerators,
+ final MessageDigest messageDigest) {
+ super(childGenerators);
+ this.messageDigest = messageDigest;
+ }
+
+ @Override
+ public Val eval(final StoredValues storedValues, final Supplier childDataSupplier) {
+
+ final Val valToHash = childGenerators[0].eval(storedValues, childDataSupplier);
+ if (!valToHash.type().isValue()) {
+ return ValErr.wrap(valToHash, "First argument of '" + Hash.NAME + "' is not a value.");
+ }
+
+ final Val algo;
+ if (childGenerators.length > 1) {
+ algo = childGenerators[1].eval(storedValues, childDataSupplier);
+ if (Val.isNull(algo)) {
+ messageDigest = DEFAULT_ALGORITHM_DIGEST;
+ } else if (!algo.type().isValue()) {
+ return ValErr.wrap(algo, "Second argument of '" + Hash.NAME + "' is not a value.");
+ }
+ } else {
+ algo = ValNull.INSTANCE;
+ }
+
+ final Val salt;
+ if (childGenerators.length > 2) {
+ salt = childGenerators[2].eval(storedValues, childDataSupplier);
+ if (!salt.type().isValue()) {
+ return ValErr.wrap(salt, "Third argument of '" + Hash.NAME + "' is not a value.");
+ }
+ } else {
+ salt = ValNull.INSTANCE;
+ }
+
+ try {
+ if (messageDigest != null) {
+ return ValString.create(hash(
+ NullSafe.get(valToHash, Val::toString),
+ messageDigest,
+ NullSafe.get(salt, Val::toString)));
+ } else {
+ return ValString.create(hash(
+ NullSafe.get(valToHash, Val::toString),
+ NullSafe.getOrElse(algo, Val::toString, DEFAULT_ALGORITHM),
+ NullSafe.get(salt, Val::toString)));
+ }
+
+ } catch (final RuntimeException | ParseException e) {
return ValErr.create(e.getMessage());
}
}
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ParamParseUtil.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ParamParseUtil.java
index a622e153d45..38d5a6fd8c9 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ParamParseUtil.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ParamParseUtil.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.query.language.functions;
import stroom.query.language.token.Param;
@@ -77,4 +93,18 @@ private static String getPos(int pos) {
}
return String.valueOf(pos);
}
+
+ public static boolean supportsStaticComputation(final Param... params) {
+ // See if this is a static computation.
+ boolean simple = true;
+ if (params != null) {
+ for (Param param : params) {
+ if (!(param instanceof Val)) {
+ simple = false;
+ break;
+ }
+ }
+ }
+ return simple;
+ }
}
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/StaticValueFunction.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/StaticValueFunction.java
index cb0c6325a31..a94b170b50c 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/StaticValueFunction.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/StaticValueFunction.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -32,6 +32,14 @@ public StaticValueFunction(final Val value) {
this.gen = new StaticValueGen(value);
}
+ public static StaticValueFunction of(final Val value) {
+ return new StaticValueFunction(value);
+ }
+
+ public static StaticValueFunction of(final String value) {
+ return new StaticValueFunction(ValString.create(value));
+ }
+
@Override
public void setParams(final Param[] params) {
// Ignore
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Val.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Val.java
index 0d5439b454e..484add4379c 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Val.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Val.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Crown Copyright
+ * Copyright 2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -95,6 +95,8 @@ default boolean hasNumericValue() {
*/
Comparator getDefaultComparator(final boolean isCaseSensitive);
+ // TODO rename of( to arrayOf( to make it a bit more clear you are getting an array back
+ // Best done on master as it affects a lot of files
static Val[] of(final Val... values) {
return values;
}
@@ -115,7 +117,7 @@ static Val[] of(final double... d) {
return Val.of(result);
}
- static Val[] empty() {
+ static Val[] emptyArray() {
return EMPTY_VALUES;
}
@@ -152,6 +154,21 @@ static Val nullSafeCreate(final T1 value,
}
}
+ static Val requireNonNullElse(final Val val, final Val other) {
+ if (val != null && !val.type().isNull()) {
+ return val;
+ } else {
+ return other;
+ }
+ }
+
+ static boolean isNull(final Val val) {
+ return val == null
+ || val == ValNull.INSTANCE
+ || Objects.equals(ValNull.INSTANCE, val)
+ || val.type().isNull();
+ }
+
/**
* Create a {@link Val} of the appropriate subclass for the java
* type passed, e.g.
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValSerialiser.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValSerialiser.java
index d2a4bf44e31..754c611c475 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValSerialiser.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValSerialiser.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.query.language.functions;
import stroom.query.language.functions.ref.DataReader;
@@ -68,7 +84,7 @@ public static void write(final DataWriter writer, final Val val) {
}
public static Val[] readArray(final DataReader reader) {
- Val[] values = Val.empty();
+ Val[] values = Val.emptyArray();
final int valueCount = reader.readByteUnsigned();
if (valueCount > 0) {
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValString.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValString.java
index 8b511c5883a..75aed99694a 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValString.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValString.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Crown Copyright
+ * Copyright 2018-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ public final class ValString implements Val {
ValComparators.GENERIC_CASE_INSENSITIVE_COMPARATOR);
public static final Type TYPE = Type.STRING;
- static final ValString EMPTY = new ValString("");
+ public static final ValString EMPTY = new ValString("");
private final String value;
// Permanent lazy cache of the slightly costly conversion to long/double
diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/token/TokenType.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/token/TokenType.java
index eb665be5525..d0123221137 100644
--- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/token/TokenType.java
+++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/token/TokenType.java
@@ -237,7 +237,7 @@ public enum TokenType {
});
KEYWORDS_VALID_AFTER = Collections.unmodifiableMap(new EnumMap<>(validNextKeywords));
- LOGGER.debug("KEYWORDS:\n{}",
+ LOGGER.trace("KEYWORDS:\n{}",
ALL_KEYWORDS.stream()
.map(keyword -> {
return LogUtil.message("""
diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractExpressionParserTest.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractExpressionParserTest.java
index be341ea65fb..b09e1e734b4 100644
--- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractExpressionParserTest.java
+++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractExpressionParserTest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.query.language.functions;
import stroom.query.language.functions.ref.KryoDataReader;
@@ -195,25 +211,25 @@ protected void testSelectors(final String expression,
protected void compute(final String expression,
final Val[] values,
- final Consumer consumer) {
+ final ValAssertion consumer) {
compute(expression, 1, values, consumer);
}
protected void compute(final String expression,
- final Consumer consumer) {
+ final ValAssertion consumer) {
compute(expression, 1, consumer);
}
protected void compute(final String expression,
final int valueCount,
- final Consumer consumer) {
+ final ValAssertion consumer) {
createExpression(expression, valueCount, exp -> {
final ValueReferenceIndex valueReferenceIndex = new ValueReferenceIndex();
exp.addValueReferences(valueReferenceIndex);
final StoredValues storedValues = valueReferenceIndex.createStoredValues();
final Generator gen = exp.createGenerator();
final Val out = gen.eval(storedValues, null);
- consumer.accept(out);
+ consumer.actual(out);
testKryo(valueReferenceIndex, gen, storedValues);
});
}
@@ -221,7 +237,7 @@ protected void compute(final String expression,
protected void compute(final String expression,
final int valueCount,
final Val[] values,
- final Consumer consumer) {
+ final ValAssertion valAssertion) {
createExpression(expression, valueCount, exp -> {
final ValueReferenceIndex valueReferenceIndex = new ValueReferenceIndex();
exp.addValueReferences(valueReferenceIndex);
@@ -229,7 +245,7 @@ protected void compute(final String expression,
final Generator gen = exp.createGenerator();
gen.set(values, storedValues);
final Val out = gen.eval(storedValues, null);
- consumer.accept(out);
+ valAssertion.actual(out);
testKryo(valueReferenceIndex, gen, storedValues);
});
}
diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractFunctionTest.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractFunctionTest.java
index 45ed08d14c6..1390bbea9ab 100644
--- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractFunctionTest.java
+++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractFunctionTest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.query.language.functions;
import stroom.query.language.functions.ref.StoredValues;
diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParser.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParser.java
index 4009032e650..793615fe3f9 100644
--- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParser.java
+++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParser.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -20,7 +20,6 @@
import io.vavr.Tuple;
import org.assertj.core.api.Assertions;
-import org.assertj.core.data.Offset;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestFactory;
@@ -97,7 +96,7 @@ void testMatch1() {
void testMatch2() {
createGenerator("match('this', 'that')", (gen, storedValues) -> {
final Val out = gen.eval(storedValues, null);
- assertThat(out.toBoolean()).isFalse();
+ ValAssertions.valFalse().actual(out);
});
}
@@ -105,161 +104,160 @@ void testMatch2() {
void testMatch3() {
compute("match(${val1}, 'this')",
Val.of("this"),
- out -> assertThat(out.toBoolean()).isTrue());
+ ValAssertions.valTrue());
}
@Test
void testMatch4() {
compute("match(${val1}, 'that')",
Val.of("this"),
- out -> assertThat(out.toBoolean()).isFalse());
+ ValAssertions.valFalse());
}
@Test
void testTrue() {
compute("true()",
- out -> assertThat(out.toBoolean()).isTrue());
+ ValAssertions.valTrue());
}
@Test
void testFalse() {
compute("false()",
- out -> assertThat(out.toBoolean()).isFalse());
+ ValAssertions.valFalse());
}
@Test
void testNull() {
- compute("null()",
- out -> assertThat(out).isInstanceOf(ValNull.class));
+ compute("null()", ValAssertions.valNull());
}
@Test
void testErr() {
compute("err()",
- out -> assertThat(out).isInstanceOf(ValErr.class));
+ ValAssertions.valErr());
}
@Test
void testNotTrue() {
compute("not(true())",
- out -> assertThat(out.toBoolean()).isFalse());
+ ValAssertions.valFalse());
}
@Test
void testNotFalse() {
compute("not(false())",
- out -> assertThat(out.toBoolean()).isTrue());
+ ValAssertions.valTrue());
}
@Test
void testAnd1() {
compute("and(false(), false())",
- out -> assertThat(out.toBoolean()).isFalse());
+ ValAssertions.valFalse());
}
@Test
void testAnd2() {
compute("and(false(), true())",
- out -> assertThat(out.toBoolean()).isFalse());
+ ValAssertions.valFalse());
}
@Test
void testAnd3() {
compute("and(true(), true())",
- out -> assertThat(out.toBoolean()).isTrue());
+ ValAssertions.valTrue());
}
@Test
void testOr1() {
compute("or(false(), false())",
- out -> assertThat(out.toBoolean()).isFalse());
+ ValAssertions.valFalse());
}
@Test
void testOr2() {
compute("or(false(), true())",
- out -> assertThat(out.toBoolean()).isTrue());
+ ValAssertions.valTrue());
}
@Test
void testOr3() {
compute("or(true(), true())",
- out -> assertThat(out.toBoolean()).isTrue());
+ ValAssertions.valTrue());
}
@Test
void testIf1() {
compute("if(true(), 'this', 'that')",
- out -> assertThat(out.toString()).isEqualTo("this"));
+ ValAssertions.valString("this"));
}
@Test
void testIf2() {
compute("if(false(), 'this', 'that')",
- out -> assertThat(out.toString()).isEqualTo("that"));
+ ValAssertions.valString("that"));
}
@Test
void testIf3() {
compute("if(${val1}, 'this', 'that')",
Val.of("true"),
- out -> assertThat(out.toString()).isEqualTo("this"));
+ ValAssertions.valString("this"));
}
@Test
void testIf4() {
compute("if(${val1}, 'this', 'that')",
Val.of("false"),
- out -> assertThat(out.toString()).isEqualTo("that"));
+ ValAssertions.valString("that"));
}
@Test
void testIf5() {
compute("if(match(${val1}, 'foo'), 'this', 'that')",
Val.of("foo"),
- out -> assertThat(out.toString()).isEqualTo("this"));
+ ValAssertions.valString("this"));
}
@Test
void testIf6() {
compute("if(match(${val1}, 'foo'), 'this', 'that')",
Val.of("bar"),
- out -> assertThat(out.toString()).isEqualTo("that"));
+ ValAssertions.valString("that"));
}
@Test
void testNotIf() {
compute("if(not(${val1}), 'this', 'that')",
Val.of("false"),
- out -> assertThat(out.toString()).isEqualTo("this"));
+ ValAssertions.valString("this"));
}
@Test
void testIf_nullHandling() {
compute("if(${val1}=null(), true(), false())",
Val.of(ValNull.INSTANCE),
- out -> assertThat(out.type().isError()).isTrue());
+ ValAssertions.valErr());
}
@Test
void testReplace1() {
compute("replace('this', 'is', 'at')",
Val.of(3D),
- out -> assertThat(out.toString()).isEqualTo("that"));
+ ValAssertions.valString("that"));
}
@Test
void testReplace2() {
compute("replace(${val1}, 'is', 'at')",
Val.of("this"),
- out -> assertThat(out.toString()).isEqualTo("that"));
+ ValAssertions.valString("that"));
}
@Test
void testConcat1() {
compute("concat('this', ' is ', 'it')",
Val.of(3D),
- out -> assertThat(out.toString()).isEqualTo("this is it"));
+ ValAssertions.valString("this is it"));
}
@@ -267,28 +265,28 @@ void testConcat1() {
void testConcat1Plus() {
compute("'this'+' is '+'it'",
Val.of(3D),
- out -> assertThat(out.toString()).isEqualTo("this is it"));
+ ValAssertions.valString("this is it"));
}
@Test
void testConcat2() {
compute("concat(${val1}, ' is ', 'it')",
Val.of("this"),
- out -> assertThat(out.toString()).isEqualTo("this is it"));
+ ValAssertions.valString("this is it"));
}
@Test
void testConcatSingle1() {
compute("concat(${val1})",
Val.of("this"),
- out -> assertThat(out.toString()).isEqualTo("this"));
+ ValAssertions.valString("this"));
}
@Test
void testConcatSingle2() {
compute("concat('hello')",
Val.of("this"),
- out -> assertThat(out.toString()).isEqualTo("hello"));
+ ValAssertions.valString("hello"));
}
@Test
@@ -296,7 +294,7 @@ void testConcatNUll() {
compute("concat(${val1}, ${val2})",
2,
Val.of(ValNull.INSTANCE, ValNull.INSTANCE),
- out -> assertThat(out.toString()).isEqualTo(""));
+ ValAssertions.valString(""));
}
@Test
@@ -304,7 +302,7 @@ void testConcatNullPlus1() {
compute("${val1}+${val2}",
2,
Val.of(ValNull.INSTANCE, ValNull.INSTANCE),
- out -> assertThat(out).isEqualTo(ValNull.INSTANCE));
+ ValAssertions.valNull());
}
@Test
@@ -312,7 +310,7 @@ void testConcatNullPlus2() {
compute("${val1}+${val2}+'test'",
2,
Val.of(ValNull.INSTANCE, ValNull.INSTANCE),
- out -> assertThat(out.toString()).isEqualTo("test"));
+ ValAssertions.valString("test"));
}
@Test
@@ -320,7 +318,7 @@ void testConcatNullPlus3() {
compute("${val1}+${val2}+''",
2,
Val.of(ValNull.INSTANCE, ValNull.INSTANCE),
- out -> assertThat(out.toString()).isEqualTo(""));
+ ValAssertions.valString(""));
}
@Test
@@ -328,7 +326,7 @@ void testConcatBooleanPlus1() {
compute("${val1}+${val2}",
2,
Val.of(ValBoolean.TRUE, ValBoolean.TRUE),
- out -> assertThat(out.toString()).isEqualTo("2"));
+ ValAssertions.valDouble(2));
}
@Test
@@ -336,16 +334,15 @@ void testConcatBooleanPlus2() {
compute("${val1}+${val2}+''",
2,
Val.of(ValBoolean.TRUE, ValBoolean.TRUE),
- out -> assertThat(out.toString()).isEqualTo("2"));
+ ValAssertions.valString("2"));
}
-
@Test
void testConcatBooleanPlus3() {
compute("${val1}+${val2}+'test'",
2,
Val.of(ValBoolean.TRUE, ValBoolean.TRUE),
- out -> assertThat(out.toString()).isEqualTo("2test"));
+ ValAssertions.valString("2test"));
}
@Test
@@ -353,7 +350,7 @@ void testConcatBooleanPlus4() {
compute("${val1}+'test'+${val2}",
2,
Val.of(ValBoolean.TRUE, ValBoolean.TRUE),
- out -> assertThat(out.toString()).isEqualTo("truetesttrue"));
+ ValAssertions.valString("truetesttrue"));
}
@@ -361,239 +358,238 @@ void testConcatBooleanPlus4() {
void testStaticString1() {
compute("'hello'",
Val.of("this"),
- out -> assertThat(out.toString()).isEqualTo("hello"));
+ ValAssertions.valString("hello"));
}
@Test
void testStaticString2() {
compute("'[Click Here](http://www.somehost.com/somepath){DIALOG}'",
Val.of("this"),
- out -> assertThat(out.toString())
- .isEqualTo("[Click Here](http://www.somehost.com/somepath){DIALOG}"));
+ ValAssertions.valString("[Click Here](http://www.somehost.com/somepath){DIALOG}"));
}
@Test
void testStaticNumber() {
compute("50",
Val.of("this"),
- out -> assertThat(out.toString()).isEqualTo("50"));
+ ValAssertions.valDouble(50));
}
@Test
void testStringLength1() {
compute("stringLength(${val1})",
Val.of("this"),
- out -> assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D)));
+ ValAssertions.valInteger(4));
}
@Test
void testSubstring1() {
compute("substring(${val1}, 1, 2)",
Val.of("this"),
- out -> assertThat(out.toString()).isEqualTo("h"));
+ ValAssertions.valString("h"));
}
@Test
void testSubstring3() {
compute("substring(${val1}, 2, 99)",
Val.of("his"),
- out -> assertThat(out.toString()).isEqualTo("s"));
+ ValAssertions.valString("s"));
}
@Test
void testSubstring4() {
compute("substring(${val1}, 1+1, 99-1)",
Val.of("his"),
- out -> assertThat(out.toString()).isEqualTo("s"));
+ ValAssertions.valString("s"));
}
@Test
void testSubstring5() {
compute("substring(${val1}, 2+5, 99-1)",
Val.of("his"),
- out -> assertThat(out.toString()).isEmpty());
+ ValAssertions.valStringEmpty());
}
@Test
void testSubstringBefore1() {
compute("substringBefore(${val1}, '-')",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("aa"));
+ ValAssertions.valString("aa"));
}
@Test
void testSubstringBefore2() {
compute("substringBefore(${val1}, 'a')",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEmpty());
+ ValAssertions.valStringEmpty());
}
@Test
void testSubstringBefore3() {
compute("substringBefore(${val1}, 'b')",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("aa-"));
+ ValAssertions.valString("aa-"));
}
@Test
void testSubstringBefore4() {
compute("substringBefore(${val1}, 'q')",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEmpty());
+ ValAssertions.valStringEmpty());
}
@Test
void testSubstringAfter1() {
compute("substringAfter(${val1}, '-')",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("bb"));
+ ValAssertions.valString("bb"));
}
@Test
void testSubstringAfter2() {
compute("substringAfter(${val1}, 'a')",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("a-bb"));
+ ValAssertions.valString("a-bb"));
}
@Test
void testSubstringAfter3() {
compute("substringAfter(${val1}, 'b')",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("b"));
+ ValAssertions.valString("b"));
}
@Test
void testSubstringAfter4() {
compute("substringAfter(${val1}, 'q')",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEmpty());
+ ValAssertions.valStringEmpty());
}
@Test
void testIndexOf() {
compute("indexOf(${val1}, '-')",
Val.of("aa-bb"),
- out -> assertThat(out.toInteger().intValue()).isEqualTo(2));
+ ValAssertions.valInteger(2));
}
@Test
void testIndexOf1() {
compute("substring(${val1}, indexOf(${val1}, '-'), stringLength(${val1}))",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("-bb"));
+ ValAssertions.valString("-bb"));
}
@Test
void testIndexOf2() {
compute("substring(${val1}, indexOf(${val1}, 'a'), stringLength(${val1}))",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("aa-bb"));
+ ValAssertions.valString("aa-bb"));
}
@Test
void testIndexOf3() {
compute("substring(${val1}, indexOf(${val1}, 'b'), stringLength(${val1}))",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("bb"));
+ ValAssertions.valString("bb"));
}
@Test
void testIndexOf4() {
compute("substring(${val1}, indexOf(${val1}, 'q'), stringLength(${val1}))",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo(""));
+ ValAssertions.valString(""));
}
@Test
void testLastIndexOf1() {
compute("substring(${val1}, lastIndexOf(${val1}, '-'), stringLength(${val1}))",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("-bb"));
+ ValAssertions.valString("-bb"));
}
@Test
void testLastIndexOf2() {
compute("substring(${val1}, lastIndexOf(${val1}, 'a'), stringLength(${val1}))",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("a-bb"));
+ ValAssertions.valString("a-bb"));
}
@Test
void testLastIndexOf3() {
compute("substring(${val1}, lastIndexOf(${val1}, 'b'), stringLength(${val1}))",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo("b"));
+ ValAssertions.valString("b"));
}
@Test
void testLastIndexOf4() {
compute("substring(${val1}, lastIndexOf(${val1}, 'q'), stringLength(${val1}))",
Val.of("aa-bb"),
- out -> assertThat(out.toString()).isEqualTo(""));
+ ValAssertions.valStringEmpty());
}
@Test
void testDecode1() {
compute("decode(${val1}, 'hullo', 'hello', 'goodbye')",
Val.of("hullo"),
- out -> assertThat(out.toString()).isEqualTo("hello"));
+ ValAssertions.valString("hello"));
}
@Test
void testDecode2() {
compute("decode(${val1}, 'h.+o', 'hello', 'goodbye')",
Val.of("hullo"),
- out -> assertThat(out.toString()).isEqualTo("hello"));
+ ValAssertions.valString("hello"));
}
@Test
void testInclude1() {
compute("include(${val1}, 'this', 'that')",
Val.of("this"),
- out -> assertThat(out.toString()).isEqualTo("this"));
+ ValAssertions.valString("this"));
}
@Test
void testInclude2() {
compute("include(${val1}, 'this', 'that')",
Val.of("that"),
- out -> assertThat(out.toString()).isEqualTo("that"));
+ ValAssertions.valString("that"));
}
@Test
void testInclude3() {
compute("include(${val1}, 'this', 'that')",
Val.of("other"),
- out -> assertThat(out.toString()).isNull());
+ ValAssertions.valNull());
}
@Test
void testExclude1() {
compute("exclude(${val1}, 'this', 'that')",
Val.of("this"),
- out -> assertThat(out.toString()).isNull());
+ ValAssertions.valNull());
}
@Test
void testExclude2() {
compute("exclude(${val1}, 'this', 'that')",
Val.of("that"),
- out -> assertThat(out.toString()).isNull());
+ ValAssertions.valNull());
}
@Test
void testExclude3() {
compute("exclude(${val1}, 'this', 'that')",
Val.of("other"),
- out -> assertThat(out.toString()).isEqualTo("other"));
+ ValAssertions.valString("other"));
}
@Test
void testEncodeUrl() {
compute("encodeUrl('https://www.somesite.com:8080/this/path?query=string')",
Val.of(""),
- out -> assertThat(out.toString()).isEqualTo(
+ ValAssertions.valString(
"https%3A%2F%2Fwww.somesite.com%3A8080%2Fthis%2Fpath%3Fquery%3Dstring"));
}
@@ -601,117 +597,112 @@ void testEncodeUrl() {
void testDecodeUrl() {
compute("decodeUrl('https%3A%2F%2Fwww.somesite.com%3A8080%2Fthis%2Fpath%3Fquery%3Dstring')",
Val.of(""),
- out -> assertThat(out.toString())
- .isEqualTo("https://www.somesite.com:8080/this/path?query=string"));
+ ValAssertions.valString("https://www.somesite.com:8080/this/path?query=string"));
}
@Test
void testEquals1() {
compute("equals(${val1}, 'plop')",
Val.of("plop"),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
void testEquals2() {
compute("equals(${val1}, ${val1})",
Val.of("plop"),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
void testEquals3() {
compute("equals(${val1}, 'plip')",
Val.of("plop"),
- out -> assertThat(out.toString()).isEqualTo("false"));
+ ValAssertions.valFalse());
}
@Test
void testEquals4() {
compute("equals(${val1}, ${val2})", 2, Val.of("plop", "plip"),
- out -> assertThat(out.toString()).isEqualTo("false"));
+ ValAssertions.valFalse());
}
@Test
void testEquals5() {
compute("equals(${val1}, ${val2})", 2, Val.of("plop", "plop"),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
void testEquals6() {
compute("${val1}=${val2}", 2, Val.of("plop", "plop"),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
void testEqualsNull1() {
compute("${val1}=null()",
Val.of(ValNull.INSTANCE),
- out -> assertThat(out.type().isError()).isTrue());
+ ValAssertions.valErr());
}
@Test
void testEqualsNull2() {
compute("${val1}=null()",
Val.of("plop"),
- out -> assertThat(out.type().isError()).isTrue());
+ ValAssertions.valErr());
}
@Test
void testEqualsNull3() {
compute("null()=null()",
Val.of("plop"),
- out -> assertThat(out.type().isError()).isTrue());
+ ValAssertions.valErr());
}
@Test
void testEqualsNull4() {
compute("if(${val1}=null(), true(), false())",
Val.of(ValNull.INSTANCE),
- out -> assertThat(out.type().isError()).isTrue());
+ ValAssertions.valErr());
}
@Test
void testIsNull1() {
compute("isNull(${val1})",
Val.of(ValNull.INSTANCE),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
void testIsNull2() {
compute("isNull(${val1})",
Val.of("plop"),
- out -> assertThat(out.toString()).isEqualTo("false"));
+ ValAssertions.valFalse());
}
@Test
void testIsNull3() {
compute("isNull(null())",
Val.of("plop"),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
void testIsNull4() {
compute("if(isNull(${val1}), true(), false())",
Val.of(ValNull.INSTANCE),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
void testLessThan1() {
- compute("lessThan(1, 0)",
- 2,
- out -> assertThat(out.toString()).isEqualTo("false"));
+ compute("lessThan(1, 0)", 2, ValAssertions.valFalse());
}
@Test
void testLessThan2() {
- compute("lessThan(1, 1)",
- 2,
- out -> assertThat(out.toString()).isEqualTo("false"));
+ compute("lessThan(1, 1)", 2, ValAssertions.valFalse());
}
@Test
@@ -719,7 +710,7 @@ void testLessThan3() {
compute("lessThan(${val1}, ${val2})",
2,
Val.of(1D, 2D),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
@@ -727,7 +718,7 @@ void testLessThan4() {
compute("lessThan(${val1}, ${val2})",
2,
Val.of("fred", "fred"),
- out -> assertThat(out.toString()).isEqualTo("false"));
+ ValAssertions.valFalse());
}
@Test
@@ -735,7 +726,7 @@ void testLessThan5() {
compute("lessThan(${val1}, ${val2})",
2,
Val.of("fred", "fred1"),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
@@ -743,21 +734,21 @@ void testLessThan6() {
compute("lessThan(${val1}, ${val2})",
2,
Val.of("fred1", "fred"),
- out -> assertThat(out.toString()).isEqualTo("false"));
+ ValAssertions.valFalse());
}
@Test
void testLessThanOrEqualTo1() {
compute("lessThanOrEqualTo(1, 0)",
2,
- out -> assertThat(out.toString()).isEqualTo("false"));
+ ValAssertions.valFalse());
}
@Test
void testLessThanOrEqualTo2() {
compute("lessThanOrEqualTo(1, 1)",
2,
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
@@ -765,7 +756,7 @@ void testLessThanOrEqualTo3() {
compute("lessThanOrEqualTo(${val1}, ${val2})",
2,
Val.of(1D, 2D),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
@@ -773,7 +764,7 @@ void testLessThanOrEqualTo3_mk2() {
compute("(${val1}<=${val2})",
2,
Val.of(1D, 2D),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
@@ -781,7 +772,7 @@ void testLessThanOrEqualTo4() {
compute("lessThanOrEqualTo(${val1}, ${val2})",
2,
Val.of("fred", "fred"),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
@@ -789,7 +780,7 @@ void testLessThanOrEqualTo5() {
compute("lessThanOrEqualTo(${val1}, ${val2})",
2,
Val.of("fred", "fred1"),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
@@ -797,7 +788,7 @@ void testLessThanOrEqualTo6() {
compute("lessThanOrEqualTo(${val1}, ${val2})",
2,
Val.of("fred1", "fred"),
- out -> assertThat(out.toString()).isEqualTo("false"));
+ ValAssertions.valFalse());
}
@Test
@@ -805,7 +796,7 @@ void testGreaterThanOrEqualTo1() {
compute("greaterThanOrEqualTo(${val1}, ${val2})",
2,
Val.of(2D, 1D),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@Test
@@ -813,7 +804,7 @@ void testGreaterThanOrEqualTo1_mk2() {
compute("(${val1}>=${val2})",
2,
Val.of(2D, 1D),
- out -> assertThat(out.toString()).isEqualTo("true"));
+ ValAssertions.valTrue());
}
@TestFactory
@@ -1107,33 +1098,134 @@ Stream testBooleanExpressions() {
void testSubstring2() {
compute("substring(${val1}, 0, 99)",
Val.of("this"),
- out -> assertThat(out.toString()).isEqualTo("this"));
+ ValAssertions.valString("this"));
+ }
+
+ @Test
+ void testContains() {
+ compute("contains(${val1}, ${val2})", Val.of("foobar", "foo"), ValAssertions.valTrue());
+ }
+
+ @Test
+ void testHash_static1() {
+ compute("hash('foo')",
+ null,
+ ValAssertions.valString(
+ "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"));
+ }
+
+ @Test
+ void testHash_static2() {
+ compute("hash('foo', 'MD5')",
+ null,
+ ValAssertions.valString(
+ "acbd18db4cc2f85cedef654fccc4a4d8"));
+ }
+
+ @Test
+ void testHash_static3() {
+ compute("hash('foo', 'MD5', 'some salt')",
+ null,
+ ValAssertions.valString(
+ "c58c215b43ef3b3480c0d0f770ec1b57"));
}
@Test
void testHash1() {
compute("hash(${val1})",
Val.of("test"),
- out -> assertThat(out.toString()).isEqualTo(
+ ValAssertions.valString(
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"));
}
@Test
void testHash2() {
- compute("hash(${val1}, 'SHA-512')",
- Val.of("test"),
- out -> assertThat(out.toString()).isEqualTo(
+ compute("hash(${val1}, ${val2})",
+ Val.of("test", "SHA-512"),
+ ValAssertions.valString(
"ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"));
}
@Test
void testHash3() {
- compute("hash(${val1}, 'SHA-512', 'mysalt')",
- Val.of("test"),
- out -> assertThat(out.toString()).isEqualTo(
+ compute("hash(${val1}, ${val2}, ${val3})",
+ Val.of("test", "SHA-512", "mysalt"),
+ ValAssertions.valString(
"af2910d4d8acf3fcf9683d3ca4425327cb1b4b48bc690f566e27b0e0144c17af82066cf6af14d3a30312ed9df671e0e24b1c66ed3973d1a7836899d75c4d6bb8"));
}
+ @Test
+ void testHash4() {
+ compute("hash(${val1})",
+ Val.of(123),
+ ValAssertions.valString(
+ "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"));
+ }
+
+ @Test
+ void testHash5() {
+ compute("hash(${val1}, ${val2}, ${val3})",
+ Val.of(ValLong.create(123), ValString.create("SHA-256"), ValLong.create(456)),
+ ValAssertions.valString(
+ "c1cf024576e9c756b252bd5035efc64c72c17affe236909ded190d266a5bfdf1"));
+ }
+
+ @Test
+ void testHash6() {
+ compute("hash(${val1})",
+ Val.of(ValErr.create("bad things happened")),
+ ValAssertions.valErrContainsIgnoreCase("bad things"));
+ }
+
+ @Test
+ void testHash7() {
+ compute("hash(${val1}, ${val2})",
+ Val.of("test", "BAD ALGO"),
+ ValAssertions.valErrContainsIgnoreCase("BAD ALGO", "digest"));
+ }
+
+ @Test
+ void testHash8() {
+ Assertions.assertThatThrownBy(() -> {
+ compute("hash()",
+ null,
+ null);
+ }).isInstanceOf(TokenException.class);
+ }
+
+ @Test
+ void testHash9() {
+ Assertions.assertThatThrownBy(() -> {
+ compute("hash(${val1}, ${val2}, ${val3}, ${val4)",
+ Val.of("test", "SHA-512", "mysalt", "BAD PARAM"),
+ null);
+ }).isInstanceOf(TokenException.class);
+ }
+
+ @Test
+ void testHash10() {
+ compute("hash(${val1}, concat('SHA-', ${val2}))",
+ Val.of(ValString.create("test"), ValLong.create(256)),
+ ValAssertions.valString(
+ "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"));
+ }
+
+ @Test
+ void testHash11() {
+ compute("hash(${val1}, 'MD5', ${val2})",
+ Val.of("test", "mysalt"),
+ ValAssertions.valString(
+ "ea43fd72fb05dd2cb8e186abd56afc47"));
+ }
+
+ @Test
+ void testHash12() {
+ compute("hash(${val1}, ${val2}, 'mysalt')",
+ Val.of("test", "MD5"),
+ ValAssertions.valString(
+ "ea43fd72fb05dd2cb8e186abd56afc47"));
+ }
+
@Test
void testJoining1() {
createGenerator("joining(${val1}, ',')", (gen, storedValues) -> {
@@ -1142,7 +1234,7 @@ void testJoining1() {
gen.set(Val.of("three"), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toString()).isEqualTo("one,two,three");
+ ValAssertions.valString("one,two,three").actual(out);
});
}
@@ -1154,7 +1246,7 @@ void testJoining2() {
gen.set(Val.of("three"), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toString()).isEqualTo("onetwothree");
+ ValAssertions.valString("onetwothree").actual(out);
});
}
@@ -1165,13 +1257,13 @@ void testCount() {
gen.set(Val.of(133D), storedValues);
Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(2D, Offset.offset(0D));
+ ValAssertions.valLong(2).actual(out);
gen.set(Val.of(11D), storedValues);
gen.set(Val.of(122D), storedValues);
out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D));
+ ValAssertions.valLong(4).actual(out);
});
}
@@ -1185,7 +1277,7 @@ void testCountGroups() {
createChildDataSupplier(List.of(storedValues, storedValues));
Val out = gen.eval(storedValues, childDataSupplier);
- assertThat(out.toInteger()).isEqualTo(2);
+ ValAssertions.valLong(2).actual(out);
});
}
@@ -1196,13 +1288,13 @@ void testCountUnique() {
gen.set(Val.of(133D), storedValues);
Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(2D, Offset.offset(0D));
+ ValAssertions.valInteger(2).actual(out);
gen.set(Val.of(11D), storedValues);
gen.set(Val.of(122D), storedValues);
out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(3D, Offset.offset(0D));
+ ValAssertions.valInteger(3).actual(out);
});
}
@@ -1213,13 +1305,13 @@ void testCountUniqueStaticValue() {
gen.set(Val.of(133D), storedValues);
Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(1D, Offset.offset(0D));
+ ValAssertions.valInteger(1).actual(out);
gen.set(Val.of(11D), storedValues);
gen.set(Val.of(122D), storedValues);
out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(1D, Offset.offset(0D));
+ ValAssertions.valInteger(1).actual(out);
});
}
@@ -1227,14 +1319,14 @@ void testCountUniqueStaticValue() {
void testAdd1() {
compute("3+4",
Val.of(1D),
- out -> assertThat(out.toDouble()).isEqualTo(7D, Offset.offset(0D)));
+ ValAssertions.valDouble(7D));
}
@Test
void testAdd2() {
compute("3+4+5",
Val.of(1D),
- out -> assertThat(out.toDouble()).isEqualTo(12D, Offset.offset(0D)));
+ ValAssertions.valDouble(12D));
}
@Test
@@ -1244,13 +1336,13 @@ void testAdd3() {
gen.set(Val.of(1D), storedValues);
Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D));
+ ValAssertions.valDouble(4D).actual(out);
gen.set(Val.of(1D), storedValues);
gen.set(Val.of(1D), storedValues);
out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(6D, Offset.offset(0D));
+ ValAssertions.valDouble(6D).actual(out);
});
}
@@ -1258,7 +1350,7 @@ void testAdd3() {
void testSubtract1() {
compute("3-4",
Val.of(1D),
- out -> assertThat(out.toDouble()).isEqualTo(-1D, Offset.offset(0D)));
+ ValAssertions.valDouble(-1D));
}
@Test
@@ -1268,13 +1360,13 @@ void testSubtract2() {
gen.set(Val.of(1D), storedValues);
Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(0D, Offset.offset(0D));
+ ValAssertions.valDouble(0D).actual(out);
gen.set(Val.of(1D), storedValues);
gen.set(Val.of(1D), storedValues);
out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(-2D, Offset.offset(0D));
+ ValAssertions.valDouble(-2D).actual(out);
});
}
@@ -1282,7 +1374,7 @@ void testSubtract2() {
void testMultiply1() {
compute("3*4",
Val.of(1D),
- out -> assertThat(out.toDouble()).isEqualTo(12D, Offset.offset(0D)));
+ ValAssertions.valDouble(12D));
}
@Test
@@ -1292,23 +1384,20 @@ void testMultiply2() {
gen.set(Val.of(1D), storedValues);
Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D));
+ ValAssertions.valDouble(4D).actual(out);
gen.set(Val.of(1D), storedValues);
gen.set(Val.of(1D), storedValues);
out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(8D, Offset.offset(0D));
+ ValAssertions.valDouble(8D).actual(out);
});
}
@Test
void testDivide1() {
compute("8/4",
- out -> {
-// gen.set(getVal(1D));
- assertThat(out.toDouble()).isEqualTo(2D, Offset.offset(0D));
- });
+ ValAssertions.valDouble(2D));
}
@Test
@@ -1318,13 +1407,13 @@ void testDivide2() {
gen.set(Val.of(1D), storedValues);
Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D));
+ ValAssertions.valDouble(4D).actual(out);
gen.set(Val.of(1D), storedValues);
gen.set(Val.of(1D), storedValues);
out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(2D, Offset.offset(0D));
+ ValAssertions.valDouble(2D).actual(out);
});
}
@@ -1340,21 +1429,21 @@ void testDivide_byZero() {
void testFloorNum1() {
compute("floor(8.4234)",
Val.of(1D),
- out -> assertThat(out.toDouble()).isEqualTo(8D, Offset.offset(0D)));
+ ValAssertions.valDouble(8D));
}
@Test
void testFloorNum2() {
compute("floor(8.5234)",
Val.of(1D),
- out -> assertThat(out.toDouble()).isEqualTo(8D, Offset.offset(0D)));
+ ValAssertions.valDouble(8D));
}
@Test
void testFloorNum3() {
compute("floor(${val1})",
Val.of(1.34D),
- out -> assertThat(out.toDouble()).isEqualTo(1D, Offset.offset(0D)));
+ ValAssertions.valDouble(1D));
}
@Test
@@ -1364,7 +1453,7 @@ void testFloorNum4() {
gen.set(Val.of(1.8655D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(3D, Offset.offset(0D));
+ ValAssertions.valDouble(3D).actual(out);
});
}
@@ -1375,7 +1464,7 @@ void testFloorNum5() {
gen.set(Val.of(1.8655D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(3.8D, Offset.offset(0D));
+ ValAssertions.valDouble(3.8D).actual(out);
});
}
@@ -1386,7 +1475,7 @@ void testFloorNum6() {
gen.set(Val.of(1.8655D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(3.86D, Offset.offset(0D));
+ ValAssertions.valDouble(3.86D).actual(out);
});
}
@@ -1394,21 +1483,21 @@ void testFloorNum6() {
void testCeilNum1() {
compute("ceiling(8.4234)",
Val.of(1D),
- out -> assertThat(out.toDouble()).isEqualTo(9D, Offset.offset(0D)));
+ ValAssertions.valDouble(9D));
}
@Test
void testCeilNum2() {
compute("ceiling(8.5234)",
Val.of(1D),
- out -> assertThat(out.toDouble()).isEqualTo(9D, Offset.offset(0D)));
+ ValAssertions.valDouble(9D));
}
@Test
void testCeilNum3() {
compute("ceiling(${val1})",
Val.of(1.34D),
- out -> assertThat(out.toDouble()).isEqualTo(2D, Offset.offset(0D)));
+ ValAssertions.valDouble(2D));
}
@Test
@@ -1418,7 +1507,7 @@ void testCeilNum4() {
gen.set(Val.of(1.8655D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D));
+ ValAssertions.valDouble(4D).actual(out);
});
}
@@ -1429,7 +1518,7 @@ void testCeilNum5() {
gen.set(Val.of(1.8655D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(3.9D, Offset.offset(0D));
+ ValAssertions.valDouble(3.9D).actual(out);
});
}
@@ -1440,7 +1529,7 @@ void testCeilNum6() {
gen.set(Val.of(1.8655D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(3.87D, Offset.offset(0D));
+ ValAssertions.valDouble(3.87D).actual(out);
});
}
@@ -1448,21 +1537,21 @@ void testCeilNum6() {
void testRoundNum1() {
compute("round(8.4234)",
Val.of(1D),
- out -> assertThat(out.toDouble()).isEqualTo(8D, Offset.offset(0D)));
+ ValAssertions.valDouble(8D));
}
@Test
void testRoundNum2() {
compute("round(8.5234)",
Val.of(1D),
- out -> assertThat(out.toDouble()).isEqualTo(9D, Offset.offset(0D)));
+ ValAssertions.valDouble(9D));
}
@Test
void testRoundNum3() {
compute("round(${val1})",
Val.of(1.34D),
- out -> assertThat(out.toDouble()).isEqualTo(1D, Offset.offset(0D)));
+ ValAssertions.valDouble(1D));
}
@Test
@@ -1472,7 +1561,7 @@ void testRoundNum4() {
gen.set(Val.of(1.8655D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D));
+ ValAssertions.valDouble(4D).actual(out);
});
}
@@ -1483,7 +1572,7 @@ void testRoundNum5() {
gen.set(Val.of(1.8655D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(3.9D, Offset.offset(0D));
+ ValAssertions.valDouble(3.9D).actual(out);
});
}
@@ -1494,7 +1583,7 @@ void testRoundNum6() {
gen.set(Val.of(1.8655D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toDouble()).isEqualTo(3.87D, Offset.offset(0D));
+ ValAssertions.valDouble(3.87D).actual(out);
});
}
@@ -1504,7 +1593,8 @@ void testDuration1() {
gen.set(Val.of(1.34D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toLong()).isEqualTo(DateUtil.parseNormalDateTimeString("2014-02-22T11:12:12.888Z"));
+ ValAssertions.valDate("2014-02-22T11:12:12.888Z")
+ .actual(out);
});
}
@@ -1514,7 +1604,8 @@ void testDuration2() {
gen.set(Val.of(1.34D), storedValues);
final Val out = gen.eval(storedValues, null);
- assertThat(out.toLong()).isEqualTo(DateUtil.parseNormalDateTimeString("2014-02-22T12:12:15.888Z"));
+ ValAssertions.valDate("2014-02-22T12:12:15.888Z")
+ .actual(out);
});
}
@@ -1543,11 +1634,9 @@ void testDuration2() {
roundYear, 2014-02-22T12:12:12.888Z, 2014-01-01T00:00:00.000Z
""")
void testTime(final String expr, final String input, final String expectedResult) {
- final double expectedMs = DateUtil.parseNormalDateTimeString(expectedResult);
+ final long expectedMs = DateUtil.parseNormalDateTimeString(expectedResult);
final String expression = expr + "(${val1})";
- compute(expression,
- Val.of(input),
- out -> assertThat(out.toDouble()).isEqualTo(expectedMs, Offset.offset(0D)));
+ compute(expression, Val.of(input), ValAssertions.valDate(expectedMs));
}
@TestFactory
@@ -1562,9 +1651,7 @@ Stream testBODMAS() {
.map(testCase -> DynamicTest.dynamicTest(testCase.toString(), () ->
compute(testCase.expression,
testCase.inputValues,
- out -> assertThat(out.toDouble())
- .isEqualTo(testCase.expectedResult.toDouble(),
- Offset.offset(0D)))));
+ ValAssertions.valDouble(testCase.expectedResult.toDouble()))));
}
@TestFactory
@@ -1643,14 +1730,14 @@ Stream testCasts() {
void testMappedValues1() {
compute("param('testkey')",
Val.of("100"),
- out -> assertThat(out).isEqualTo(ValString.create("testvalue")));
+ ValAssertions.valString("testvalue"));
}
@Test
void testMappedValues2() {
compute("params()",
Val.of("100"),
- out -> assertThat(out).isEqualTo(ValString.create("testkey=\"testvalue\"")));
+ ValAssertions.valString("testkey=\"testvalue\""));
}
@TestFactory
diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserAggregates.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserAggregates.java
index b4eee14a464..0dba7b03933 100644
--- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserAggregates.java
+++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserAggregates.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserLinks.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserLinks.java
index 4f31881c850..1de1774e8ea 100644
--- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserLinks.java
+++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserLinks.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserUris.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserUris.java
index cdfc7fc98a0..4c5c92da5cc 100644
--- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserUris.java
+++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserUris.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2017 Crown Copyright
+ * Copyright 2017-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestHash.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestHash.java
index 5cee9e969f9..ac439ae314b 100644
--- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestHash.java
+++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestHash.java
@@ -1,7 +1,31 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.query.language.functions;
+import org.junit.jupiter.api.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HexFormat;
import java.util.stream.Stream;
+import static org.assertj.core.api.Assertions.assertThat;
+
class TestHash extends AbstractFunctionTest {
@Override
@@ -38,7 +62,8 @@ Stream getTestCases() {
ValString.create("sha-256")),
TestCase.of(
"sha512_noSalt",
- ValString.create("ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"),
+ ValString.create(
+ "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"),
ValString.create("test"),
ValString.create("sha-512")),
TestCase.of(
@@ -61,10 +86,36 @@ Stream getTestCases() {
ValString.create("haveSomeSalt")),
TestCase.of(
"sha512_withSalt",
- ValString.create("7559c1cac090b47296f8d8ab5835202821a0024d113b3c4636648d5dce22213ebc3464bb4003890bc763ad2b4c14a5cf4f84241441aefe140d30d8600e5e2520"),
+ ValString.create(
+ "7559c1cac090b47296f8d8ab5835202821a0024d113b3c4636648d5dce22213ebc3464bb4003890bc763ad2b4c14a5cf4f84241441aefe140d30d8600e5e2520"),
+ ValString.create("test"),
+ ValString.create("sha-512"),
+ ValString.create("haveSomeSalt")),
+ TestCase.of(
+ "md5_withSalt",
+ ValString.create(
+ "7559c1cac090b47296f8d8ab5835202821a0024d113b3c4636648d5dce22213ebc3464bb4003890bc763ad2b4c14a5cf4f84241441aefe140d30d8600e5e2520"),
ValString.create("test"),
ValString.create("sha-512"),
ValString.create("haveSomeSalt"))
);
}
+
+ /**
+ * Just make sure digest resetting works.
+ */
+ @Test
+ void testHash() throws NoSuchAlgorithmException {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ digest.update("salt".getBytes(StandardCharsets.UTF_8));
+ String hex1 = HexFormat.of().formatHex(digest.digest("foo".getBytes(StandardCharsets.UTF_8)));
+
+ digest.reset();
+
+ digest.update("salt".getBytes(StandardCharsets.UTF_8));
+ String hex2 = HexFormat.of().formatHex(digest.digest("foo".getBytes(StandardCharsets.UTF_8)));
+
+ assertThat(hex2)
+ .isEqualTo(hex1);
+ }
}
diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertion.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertion.java
new file mode 100644
index 00000000000..ac866dec51b
--- /dev/null
+++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertion.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package stroom.query.language.functions;
+
+/**
+ * An assertion of a {@link Val}
+ */
+@FunctionalInterface
+public interface ValAssertion {
+
+ /**
+ * The actual or output {@link Val} for the assertion to test.
+ */
+ void actual(Val actual);
+}
diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertions.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertions.java
new file mode 100644
index 00000000000..4b5f0d01c83
--- /dev/null
+++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertions.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package stroom.query.language.functions;
+
+import org.assertj.core.api.Assertions;
+
+import java.time.Instant;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Various methods for asserting a {@link Val} value.
+ */
+public class ValAssertions {
+
+ public static final ValAssertion VAL_NULL_ASSERTION = (Val actual) -> {
+ Assertions.assertThat(actual)
+ .isInstanceOf(ValNull.class);
+ Assertions.assertThat((ValNull) actual)
+ .isSameAs(ValNull.INSTANCE);
+ };
+
+ public static final ValAssertion VAL_ERR_ASSERTION = (Val actual) ->
+ Assertions.assertThat(actual)
+ .isInstanceOf(ValErr.class);
+
+ public static final ValAssertion VAL_TRUE_ASSERTION = (Val actual) ->
+ Assertions.assertThat(actual)
+ .isInstanceOf(ValBoolean.class)
+ .isSameAs(ValBoolean.TRUE)
+ .extracting(Val::toBoolean)
+ .isEqualTo(true);
+
+ public static final ValAssertion VAL_FALSE_ASSERTION = (Val actual) ->
+ Assertions.assertThat(actual)
+ .isInstanceOf(ValBoolean.class)
+ .isSameAs(ValBoolean.FALSE)
+ .extracting(Val::toBoolean)
+ .isEqualTo(false);
+
+ public static final ValAssertion VAL_EMPTY_STRING_ASSERTION = (Val actual) ->
+ assertThat(actual)
+ .isInstanceOf(ValString.class)
+ .isSameAs(ValString.EMPTY)
+ .extracting(Val::toString)
+ .isEqualTo("");
+
+ private ValAssertions() {
+ }
+
+ public static ValAssertion valTrue() {
+ return VAL_TRUE_ASSERTION;
+ }
+
+ public static ValAssertion valFalse() {
+ return VAL_FALSE_ASSERTION;
+ }
+
+ public static ValAssertion valNull() {
+ return VAL_NULL_ASSERTION;
+ }
+
+ public static ValAssertion valErr() {
+ return VAL_ERR_ASSERTION;
+ }
+
+ /**
+ * @param expectedSubStrings sub-strings that are expected to appear in the error message in any order.
+ */
+ public static ValAssertion valErrContainsIgnoreCase(final String... expectedSubStrings) {
+ return (Val actual) -> {
+ Assertions.assertThat(actual)
+ .isInstanceOf(ValErr.class);
+
+ for (final String expectedSubString : expectedSubStrings) {
+ Assertions.assertThat(actual.toString())
+ .containsIgnoringCase(expectedSubString);
+ }
+ };
+ }
+
+ public static ValAssertion valString(final String expected) {
+ return (Val actual) ->
+ Assertions.assertThat(actual)
+ .isEqualTo(ValString.create(expected));
+ }
+
+ public static ValAssertion valStringEmpty() {
+ return VAL_EMPTY_STRING_ASSERTION;
+ }
+
+ public static ValAssertion valDouble(final double expected) {
+ return (Val out) ->
+ Assertions.assertThat(out)
+ .isEqualTo(ValDouble.create(expected))
+ .extracting(Val::toDouble)
+ .isEqualTo(expected);
+ }
+
+ public static ValAssertion valFloat(final float expected) {
+ return (Val out) ->
+ Assertions.assertThat(out)
+ .isEqualTo(ValFloat.create(expected))
+ .extracting(Val::toFloat)
+ .isEqualTo(expected);
+ }
+
+ public static ValAssertion valInteger(final int expected) {
+ return (Val out) ->
+ Assertions.assertThat(out)
+ .isEqualTo(ValInteger.create(expected))
+ .extracting(Val::toInteger)
+ .isEqualTo(expected);
+ }
+
+ public static ValAssertion valLong(final long expected) {
+ return (Val out) ->
+ Assertions.assertThat(out)
+ .isEqualTo(ValLong.create(expected))
+ .extracting(Val::toLong)
+ .isEqualTo(expected);
+ }
+
+ public static ValAssertion valDate(final long expectedEpochMs) {
+ return (Val out) ->
+ Assertions.assertThat(out)
+ .isInstanceOf(ValDate.class)
+ .extracting(Val::toLong)
+ .isEqualTo(expectedEpochMs);
+ }
+
+ public static ValAssertion valDate(final String expectedNormalDateTimeString) {
+ return valDate(DateUtil.parseNormalDateTimeString(expectedNormalDateTimeString));
+ }
+
+ public static ValAssertion valDate(final Instant expectedInstant) {
+ return valDate(expectedInstant.toEpochMilli());
+ }
+
+ /**
+ * No type checking, just that {@link Val#toString()} is equal to expected.
+ */
+ public static ValAssertion valAsString(final String expected) {
+ return (Val out) ->
+ Assertions.assertThat(out.toString())
+ .isEqualTo(expected);
+ }
+}
diff --git a/stroom-search/stroom-search-elastic/src/main/java/stroom/search/elastic/search/ElasticSearchTaskHandler.java b/stroom-search/stroom-search-elastic/src/main/java/stroom/search/elastic/search/ElasticSearchTaskHandler.java
index d5b21532d94..9d13591d357 100644
--- a/stroom-search/stroom-search-elastic/src/main/java/stroom/search/elastic/search/ElasticSearchTaskHandler.java
+++ b/stroom-search/stroom-search-elastic/src/main/java/stroom/search/elastic/search/ElasticSearchTaskHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Crown Copyright
+ * Copyright 2016-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -248,8 +248,8 @@ private void searchSlice(final ElasticIndexDoc elasticIndex,
taskContext.info(() -> LogUtil.message("Processed {} hits", totalHits));
final ScrollResponse scrollResponse = elasticClient.scroll(s -> s
- .scrollId(scrollId)
- .scroll(scrollTime),
+ .scrollId(scrollId)
+ .scroll(scrollTime),
ObjectNode.class
);
diff --git a/stroom-search/stroom-search-extraction/src/main/java/stroom/search/extraction/StandardFieldListConsumer.java b/stroom-search/stroom-search-extraction/src/main/java/stroom/search/extraction/StandardFieldListConsumer.java
index baf6d79772c..4d713f3d85c 100644
--- a/stroom-search/stroom-search-extraction/src/main/java/stroom/search/extraction/StandardFieldListConsumer.java
+++ b/stroom-search/stroom-search-extraction/src/main/java/stroom/search/extraction/StandardFieldListConsumer.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.search.extraction;
import stroom.query.api.v2.QueryKey;
diff --git a/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestQueues.java b/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestQueues.java
index f54c0d63728..aa1e2a70bdf 100644
--- a/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestQueues.java
+++ b/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestQueues.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.search.impl;
import stroom.query.api.v2.QueryKey;
diff --git a/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestSearchResultCreation.java b/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestSearchResultCreation.java
index 5baa0dc8ece..ffa100e14b1 100644
--- a/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestSearchResultCreation.java
+++ b/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestSearchResultCreation.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.search.impl;
import stroom.bytebuffer.impl6.ByteBufferFactoryImpl;
diff --git a/stroom-search/stroom-search-solr/src/main/java/stroom/search/solr/search/SolrSearchTaskHandler.java b/stroom-search/stroom-search-solr/src/main/java/stroom/search/solr/search/SolrSearchTaskHandler.java
index e3ee787949c..5103baa45f2 100644
--- a/stroom-search/stroom-search-solr/src/main/java/stroom/search/solr/search/SolrSearchTaskHandler.java
+++ b/stroom-search/stroom-search-solr/src/main/java/stroom/search/solr/search/SolrSearchTaskHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Crown Copyright
+ * Copyright 2016-2024 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SearchHelper.java b/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SearchHelper.java
index 77179d3f48a..9b5506871ca 100644
--- a/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SearchHelper.java
+++ b/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SearchHelper.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.state.impl.dao;
import stroom.entity.shared.ExpressionCriteria;
diff --git a/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SessionDao.java b/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SessionDao.java
index 25be5b8d501..e0c394881b9 100644
--- a/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SessionDao.java
+++ b/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SessionDao.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 Crown Copyright
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package stroom.state.impl.dao;
import stroom.entity.shared.ExpressionCriteria;
@@ -40,7 +56,6 @@
import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.literal;
import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.selectFrom;
import static com.datastax.oss.driver.api.querybuilder.SchemaBuilder.createTable;
-import static com.datastax.oss.driver.api.querybuilder.SchemaBuilder.dropTable;
public class SessionDao extends AbstractStateDao {
diff --git a/unreleased_changes/20241011_111802_755__4444.md b/unreleased_changes/20241011_111802_755__4444.md
new file mode 100644
index 00000000000..238f38ea4e0
--- /dev/null
+++ b/unreleased_changes/20241011_111802_755__4444.md
@@ -0,0 +1,24 @@
+* Issue **#4444** : Change the `hash()` expression function to allow the `algorithm` and `salt` arguments to be the result of functions, e.g. `hash(${field1}, concat('SHA-', ${algoLen}), ${salt})`.
+
+
+```sh
+# ********************************************************************************
+# Issue title: hash() function salt parameter will only accept a simple string
+# Issue link: https://github.com/gchq/stroom/issues/4444
+# ********************************************************************************
+
+# ONLY the top line will be included as a change entry in the CHANGELOG.
+# The entry should be in GitHub flavour markdown and should be written on a SINGLE
+# line with no hard breaks. You can have multiple change files for a single GitHub issue.
+# The entry should be written in the imperative mood, i.e. 'Fix nasty bug' rather than
+# 'Fixed nasty bug'.
+#
+# Examples of acceptable entries are:
+#
+#
+# * Issue **123** : Fix bug with an associated GitHub issue in this repository
+#
+# * Issue **namespace/other-repo#456** : Fix bug with an associated GitHub issue in another repository
+#
+# * Fix bug with no associated GitHub issue.
+```