- * This specifier will check if a string instance is a valid Elide Argument Name.
- *
- */
-public class ElideArgumentNameFormatAttr extends AbstractFormatAttribute {
-
- public static final String FORMAT_NAME = "elideArgumentName";
- public static final String NAME_KEY = "elideArgumentName.error.name";
- public static final String NAME_MSG = "Argument name [%s] is not allowed. Argument name cannot be 'grain'.";
- public static final String FORMAT_KEY = "elideArgumentName.error.format";
- public static final String FORMAT_MSG = "Argument name [%s] is not allowed. Name must start with an alphabetic "
- + "character and can include alaphabets, numbers and '_' only.";
-
- public ElideArgumentNameFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!ElideNameFormatAttr.NAME_FORMAT_REGEX.matcher(input).matches()) {
- report.error(newMsg(data, bundle, FORMAT_KEY).putArgument("value", input));
- }
-
- if (input.equalsIgnoreCase("grain")) {
- report.error(newMsg(data, bundle, NAME_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideCardinalityFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideCardinalityFormatAttr.java
deleted file mode 100644
index 13343e39d7..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideCardinalityFormatAttr.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code elideCardiality} format attribute.
- *
- * This specifier will check if a string instance is one of {@code Tiny, Small, Medium, Large, Huge}.
- *
- */
-public class ElideCardinalityFormatAttr extends AbstractFormatAttribute {
- private static final Pattern CARDINALITY_PATTERN = Pattern.compile("^(?i)(Tiny|Small|Medium|Large|Huge)$");
-
- public static final String FORMAT_NAME = "elideCardiality";
- public static final String TYPE_KEY = "elideCardiality.error.enum";
- public static final String TYPE_MSG = "Cardinality type [%s] is not allowed. Supported value is one of "
- + "[Tiny, Small, Medium, Large, Huge].";
-
- public ElideCardinalityFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!CARDINALITY_PATTERN.matcher(input).matches()) {
- report.error(newMsg(data, bundle, TYPE_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideFieldNameFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideFieldNameFormatAttr.java
deleted file mode 100644
index 6c98c0eb9b..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideFieldNameFormatAttr.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code elideFieldName} format attribute.
- *
- * This specifier will check if a string instance is a valid Elide Field Name.
- *
- */
-public class ElideFieldNameFormatAttr extends AbstractFormatAttribute {
- private static final Pattern FIELD_NAME_FORMAT_REGEX = Pattern.compile("^[a-z][0-9A-Za-z_]*$");
- private static final Set RESERVED_KEYWORDS_FOR_COLUMN_NAME = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
-
- static {
- RESERVED_KEYWORDS_FOR_COLUMN_NAME.add("id");
- RESERVED_KEYWORDS_FOR_COLUMN_NAME.add("sql");
- }
-
- public static final String FORMAT_NAME = "elideFieldName";
- public static final String NAME_KEY = "elideFieldName.error.name";
- public static final String NAME_MSG =
- "Field name [%s] is not allowed. Field name cannot be one of " + RESERVED_KEYWORDS_FOR_COLUMN_NAME;
- public static final String FORMAT_KEY = "elideFieldName.error.format";
- public static final String FORMAT_MSG = "Field name [%s] is not allowed. Field name must start with "
- + "lower case alphabet and can include alaphabets, numbers and '_' only.";
-
- public ElideFieldNameFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!FIELD_NAME_FORMAT_REGEX.matcher(input).matches()) {
- report.error(newMsg(data, bundle, FORMAT_KEY).putArgument("value", input));
- }
-
- if (RESERVED_KEYWORDS_FOR_COLUMN_NAME.contains(input)) {
- report.error(newMsg(data, bundle, NAME_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideFieldTypeFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideFieldTypeFormatAttr.java
deleted file mode 100644
index 4c7584dd35..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideFieldTypeFormatAttr.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code elideFieldType} format attribute.
- *
- * This specifier will check if a string instance is one of {@code Integer, Decimal, Money, Text, Coordinate, Boolean}.
- *
- */
-public class ElideFieldTypeFormatAttr extends AbstractFormatAttribute {
- public static final Pattern FIELD_TYPE_PATTERN =
- Pattern.compile("^(?i)(Integer|Decimal|Money|Text|Coordinate|Boolean|Enum_Text|Enum_Ordinal)$");
-
- public static final String FORMAT_NAME = "elideFieldType";
- public static final String TYPE_KEY = "elideFieldType.error.enum";
- public static final String TYPE_MSG = "Field type [%s] is not allowed. Supported value is one of "
- + "[Integer, Decimal, Money, Text, Coordinate, Boolean, Enum_Text, Enum_Ordinal].";
-
- public ElideFieldTypeFormatAttr() {
- this(FORMAT_NAME);
- }
-
- public ElideFieldTypeFormatAttr(String formatName) {
- super(formatName, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!FIELD_TYPE_PATTERN.matcher(input).matches()) {
- report.error(newMsg(data, bundle, TYPE_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideGrainTypeFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideGrainTypeFormatAttr.java
deleted file mode 100644
index e3bb8215c8..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideGrainTypeFormatAttr.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code elideGrainType} format attribute.
- *
- * This specifier will check if a string instance is one of
- * {@code Second, Minute, Hour, Day, IsoWeek, Week, Month, Quarter, Year}.
- *
- */
-public class ElideGrainTypeFormatAttr extends AbstractFormatAttribute {
- private static final Pattern GRAIN_TYPE_PATTERN =
- Pattern.compile("^(?i)(Second|Minute|Hour|Day|IsoWeek|Week|Month|Quarter|Year)$");
-
- public static final String FORMAT_NAME = "elideGrainType";
- public static final String TYPE_KEY = "elideGrainType.error.enum";
- public static final String TYPE_MSG = "Grain type [%s] is not allowed. Supported value is one of "
- + "[Second, Minute, Hour, Day, IsoWeek, Week, Month, Quarter, Year].";
-
- public ElideGrainTypeFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!GRAIN_TYPE_PATTERN.matcher(input).matches()) {
- report.error(newMsg(data, bundle, TYPE_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideJDBCUrlFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideJDBCUrlFormatAttr.java
deleted file mode 100644
index 9cb8275942..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideJDBCUrlFormatAttr.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-/**
- * Format specifier for {@code elideJdbcUrl} format attribute.
- *
- * This specifier will check if a string instance is a valid JDBC url.
- *
- */
-public class ElideJDBCUrlFormatAttr extends AbstractFormatAttribute {
-
- public static final String FORMAT_NAME = "elideJdbcUrl";
- public static final String FORMAT_KEY = "elideJdbcUrl.error.format";
- public static final String FORMAT_MSG = "Input value [%s] is not a valid JDBC url, it must start with 'jdbc:'.";
-
- public ElideJDBCUrlFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!input.startsWith("jdbc:")) {
- report.error(newMsg(data, bundle, FORMAT_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideJoinKindFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideJoinKindFormatAttr.java
deleted file mode 100644
index a45212fdd4..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideJoinKindFormatAttr.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code elideJoinKind} format attribute.
- *
- * This specifier will check if a string instance is one of {@code ToOne, ToMany}.
- *
- */
-public class ElideJoinKindFormatAttr extends AbstractFormatAttribute {
- private static final Pattern JOIN_KIND_PATTERN = Pattern.compile("^(?i)(ToOne|ToMany)$");
-
- public static final String FORMAT_NAME = "elideJoinKind";
- public static final String TYPE_KEY = "elideJoinKind.error.enum";
- public static final String TYPE_MSG = "Join kind [%s] is not allowed. Supported value is one of [ToOne, ToMany].";
-
- public ElideJoinKindFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!JOIN_KIND_PATTERN.matcher(input).matches()) {
- report.error(newMsg(data, bundle, TYPE_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideJoinTypeFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideJoinTypeFormatAttr.java
deleted file mode 100644
index 0200e4ed40..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideJoinTypeFormatAttr.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code elideJoinType} format attribute.
- *
- * This specifier will check if a string instance is one of {@code left, inner, full, cross}.
- *
- */
-public class ElideJoinTypeFormatAttr extends AbstractFormatAttribute {
- private static final Pattern JOIN_TYPE_PATTERN = Pattern.compile("^(?i)(left|inner|full|cross)$");
-
- public static final String FORMAT_NAME = "elideJoinType";
- public static final String TYPE_KEY = "elideJoinType.error.enum";
- public static final String TYPE_MSG =
- "Join type [%s] is not allowed. Supported value is one of [left, inner, full, cross].";
-
- public ElideJoinTypeFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!JOIN_TYPE_PATTERN.matcher(input).matches()) {
- report.error(newMsg(data, bundle, TYPE_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideNameFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideNameFormatAttr.java
deleted file mode 100644
index 5d60adb495..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideNameFormatAttr.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code elideName} format attribute.
- *
- * This specifier will check if a string instance is a valid Elide Name.
- *
- */
-public class ElideNameFormatAttr extends AbstractFormatAttribute {
- public static final Pattern NAME_FORMAT_REGEX = Pattern.compile("^[A-Za-z][0-9A-Za-z_]*$");
-
- public static final String FORMAT_NAME = "elideName";
- public static final String FORMAT_KEY = "elideName.error.format";
- public static final String FORMAT_MSG =
- "Name [%s] is not allowed. Name must start with an alphabetic character and can include "
- + "alaphabets, numbers and '_' only.";
-
- public ElideNameFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!NAME_FORMAT_REGEX.matcher(input).matches()) {
- report.error(newMsg(data, bundle, FORMAT_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideNamespaceNameFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideNamespaceNameFormatAttr.java
deleted file mode 100644
index 6ecfc0a84a..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideNamespaceNameFormatAttr.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.Locale;
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code elideNamespaceName} format attribute.
- *
- * This specifier will check if a string instance is a valid Elide Name.
- *
- */
-public class ElideNamespaceNameFormatAttr extends AbstractFormatAttribute {
- public static final Pattern NAME_FORMAT_REGEX = ElideNameFormatAttr.NAME_FORMAT_REGEX;
-
- public static final String FORMAT_NAME = "elideNamespaceName";
- public static final String FORMAT_KEY = "elideNamespaceName.error.format";
- public static final String FORMAT_ADDITIONAL_KEY = "elideNamespaceName.error.additional";
- public static final String FORMAT_KEY_MSG =
- "Name [%s] is not allowed. Name must start with an alphabetic character and can include "
- + "alaphabets, numbers and '_' only.";
- public static final String FORMAT_ADDITIONAL_KEY_MSG =
- "Name [%s] clashes with the 'default' namespace. Either change the case or pick a different namespace "
- + "name.";
- public static final String DEFAULT_NAME = "default";
-
- public ElideNamespaceNameFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!NAME_FORMAT_REGEX.matcher(input).matches()) {
- report.error(newMsg(data, bundle, FORMAT_KEY).putArgument("value", input));
- }
-
- if (!input.equals(DEFAULT_NAME) && input.toLowerCase(Locale.ENGLISH).equals(DEFAULT_NAME)) {
- report.error(newMsg(data, bundle, FORMAT_ADDITIONAL_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideRSQLFilterFormat.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideRSQLFilterFormat.java
new file mode 100644
index 0000000000..bf89606459
--- /dev/null
+++ b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideRSQLFilterFormat.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2020, Yahoo Inc.
+ * Licensed under the Apache License, Version 2.0
+ * See LICENSE file in project root for terms.
+ */
+package com.yahoo.elide.modelconfig.jsonformats;
+
+import static com.yahoo.elide.core.filter.dialect.RSQLFilterDialect.getDefaultOperatorsWithIsnull;
+
+import com.networknt.schema.ExecutionContext;
+import com.networknt.schema.Format;
+
+import cz.jirutka.rsql.parser.RSQLParser;
+import cz.jirutka.rsql.parser.RSQLParserException;
+
+/**
+ * Format specifier for {@code elideRSQLFilter} format attribute.
+ *
+ * This specifier will check if a string instance is a valid RSQL filter.
+ *
+ */
+public class ElideRSQLFilterFormat implements Format {
+
+ public static final String NAME = "elideRSQLFilter";
+ public static final String ERROR_MESSAGE_DESCRIPTION = "{0}: does not match the elideRSQLFilter pattern "
+ + "is not a valid RSQL filter expression."
+ + " Please visit page https://elide.io/pages/guide/v5/11-graphql.html#operators for samples.";
+
+ @Override
+ public boolean matches(ExecutionContext executionContext, String value) {
+ try {
+ new RSQLParser(getDefaultOperatorsWithIsnull()).parse(value);
+ } catch (RSQLParserException e) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public String getMessageKey() {
+ return ERROR_MESSAGE_DESCRIPTION;
+ }
+}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideRSQLFilterFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideRSQLFilterFormatAttr.java
deleted file mode 100644
index 4d9934cd5e..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideRSQLFilterFormatAttr.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import static com.yahoo.elide.core.filter.dialect.RSQLFilterDialect.getDefaultOperatorsWithIsnull;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import cz.jirutka.rsql.parser.RSQLParser;
-import cz.jirutka.rsql.parser.RSQLParserException;
-
-/**
- * Format specifier for {@code elideRSQLFilter} format attribute.
- *
- * This specifier will check if a string instance is a valid RSQL filter.
- *
- */
-public class ElideRSQLFilterFormatAttr extends AbstractFormatAttribute {
-
- public static final String FORMAT_NAME = "elideRSQLFilter";
- public static final String FORMAT_KEY = "elideRSQLFilter.error.format";
- public static final String FORMAT_MSG = "Input value[%s] is not a valid RSQL filter expression. Please visit page "
- + "https://elide.io/pages/guide/v5/11-graphql.html#operators for samples.";
-
- public ElideRSQLFilterFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- try {
- new RSQLParser(getDefaultOperatorsWithIsnull()).parse(input);
- } catch (RSQLParserException e) {
- report.error(newMsg(data, bundle, FORMAT_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideRoleFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideRoleFormatAttr.java
deleted file mode 100644
index e030391f22..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideRoleFormatAttr.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code elideRole} format attribute.
- *
- * This specifier will check if a string instance is a valid Elide role.
- *
- */
-public class ElideRoleFormatAttr extends AbstractFormatAttribute {
- private static final Pattern ROLE_FORMAT_REGEX = Pattern.compile("^[A-Za-z][0-9A-Za-z. ]*$");
-
- public static final String FORMAT_NAME = "elideRole";
- public static final String FORMAT_KEY = "elideRole.error.format";
- public static final String FORMAT_MSG =
- "Role [%s] is not allowed. Role must start with an alphabetic character and can include "
- + "alaphabets, numbers, spaces and '.' only.";
-
- public ElideRoleFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!ROLE_FORMAT_REGEX.matcher(input).matches()) {
- report.error(newMsg(data, bundle, FORMAT_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideTimeFieldTypeFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideTimeFieldTypeFormatAttr.java
deleted file mode 100644
index 6558d09ae5..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ElideTimeFieldTypeFormatAttr.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code elideTimeFieldType} format attribute.
- *
- * This specifier will check if a string instance is {@code Time}.
- *
- */
-public class ElideTimeFieldTypeFormatAttr extends AbstractFormatAttribute {
- private static final Pattern TIME_FIELD_TYPE_PATTERN = Pattern.compile("^(?i)(Time)$");
-
- public static final String FORMAT_NAME = "elideTimeFieldType";
- public static final String TYPE_KEY = "elideTimeFieldType.error.enum";
- public static final String TYPE_MSG = "Field type [%s] is not allowed. Field type must be "
- + "[Time] for any time dimension.";
-
- public ElideTimeFieldTypeFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!TIME_FIELD_TYPE_PATTERN.matcher(input).matches()) {
- report.error(newMsg(data, bundle, TYPE_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/JavaClassNameFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/JavaClassNameFormatAttr.java
deleted file mode 100644
index 268186d356..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/JavaClassNameFormatAttr.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code javaClassName} format attribute.
- *
- * This specifier will check if a string instance is a valid JAVA Class Name.
- *
- */
-public class JavaClassNameFormatAttr extends AbstractFormatAttribute {
- private static final String ID_PATTERN = "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*";
- public static final Pattern CLASS_NAME_FORMAT_PATTERN = Pattern.compile(ID_PATTERN + "(\\." + ID_PATTERN + ")*");
-
- public static final String FORMAT_NAME = "javaClassName";
- public static final String FORMAT_KEY = "javaClassName.error.format";
- public static final String FORMAT_MSG = "Input value[%s] is not a valid Java class name.";
-
- public JavaClassNameFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!CLASS_NAME_FORMAT_PATTERN.matcher(input).matches()) {
- report.error(newMsg(data, bundle, FORMAT_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/JavaClassNameWithExtFormatAttr.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/JavaClassNameWithExtFormatAttr.java
deleted file mode 100644
index d31255dfe5..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/JavaClassNameWithExtFormatAttr.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.format.AbstractFormatAttribute;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import java.util.regex.Pattern;
-
-/**
- * Format specifier for {@code javaClassNameWithExt} format attribute.
- *
- * This specifier will check if a string instance is a valid JAVA Class Name with {@code .class} extension.
- *
- */
-public class JavaClassNameWithExtFormatAttr extends AbstractFormatAttribute {
- private static final Pattern CLASS_NAME_FORMAT_PATTERN =
- Pattern.compile("^(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*\\.)+class$");
-
- public static final String FORMAT_NAME = "javaClassNameWithExt";
- public static final String FORMAT_KEY = "javaClassNameWithExt.error.format";
- public static final String FORMAT_MSG = "Input value[%s] is not a valid Java class name with .class extension.";
-
- public JavaClassNameWithExtFormatAttr() {
- super(FORMAT_NAME, NodeType.STRING);
- }
-
- @Override
- public void validate(final ProcessingReport report, final MessageBundle bundle, final FullData data)
- throws ProcessingException {
- final String input = data.getInstance().getNode().textValue();
-
- if (!CLASS_NAME_FORMAT_PATTERN.matcher(input).matches()) {
- report.error(newMsg(data, bundle, FORMAT_KEY).putArgument("value", input));
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateArgsPropertiesKeyword.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateArgsPropertiesKeyword.java
deleted file mode 100644
index 6b5b6041d7..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateArgsPropertiesKeyword.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2021, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jackson.jsonpointer.JsonPointer;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.keyword.syntax.checkers.AbstractSyntaxChecker;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.core.tree.SchemaTree;
-import com.github.fge.jsonschema.keyword.digest.AbstractDigester;
-import com.github.fge.jsonschema.library.Keyword;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import lombok.Getter;
-
-import java.util.Collection;
-
-/**
- * Creates custom keyword for {@code validateArgumentProperties}.
- */
-public class ValidateArgsPropertiesKeyword {
-
- @Getter
- private Keyword keyword;
-
- public ValidateArgsPropertiesKeyword() {
- keyword = Keyword.newBuilder(ValidateArgsPropertiesValidator.KEYWORD)
- .withSyntaxChecker(new ValidateArgsPropertiesSyntaxChecker())
- .withDigester(new ValidateArgsPropertiesDigester())
- .withValidatorClass(ValidateArgsPropertiesValidator.class)
- .freeze();
- }
-
- /**
- * Defines custom SyntaxChecker for {@code validateArgumentProperties}.
- */
- private class ValidateArgsPropertiesSyntaxChecker extends AbstractSyntaxChecker {
-
- public ValidateArgsPropertiesSyntaxChecker() {
- super(ValidateArgsPropertiesValidator.KEYWORD, NodeType.BOOLEAN);
- }
-
- @Override
- protected void checkValue(Collection pointers, MessageBundle bundle, ProcessingReport report,
- SchemaTree tree) throws ProcessingException {
- // AbstractSyntaxChecker has already verified that value is of type Boolean
- // No additional Checks Required
- }
- }
-
- /**
- * Defines custom Digester for {@code validateArgumentProperties}.
- */
- private class ValidateArgsPropertiesDigester extends AbstractDigester {
-
- public ValidateArgsPropertiesDigester() {
- super(ValidateArgsPropertiesValidator.KEYWORD, NodeType.OBJECT);
- }
-
- @Override
- public JsonNode digest(final JsonNode schema) {
- final ObjectNode node = FACTORY.objectNode();
- node.put(keyword, schema.get(keyword).asBoolean(true));
-
- return node;
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateArgsPropertiesValidator.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateArgsPropertiesValidator.java
deleted file mode 100644
index 98bbbc6750..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateArgsPropertiesValidator.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2021, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.processing.Processor;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.keyword.validator.AbstractKeywordValidator;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-import com.google.common.collect.Sets;
-
-import java.util.Set;
-
-/**
- * Defines custom Keyword Validator for {@code validateArgumentProperties}.
- *
- * This validator checks not both {@code tableSource} and {@code values} property is defined for any argument.
- *
- */
-public class ValidateArgsPropertiesValidator extends AbstractKeywordValidator {
-
- public static final String KEYWORD = "validateArgumentProperties";
- public static final String ATMOST_ONE_KEY = "validateArgumentProperties.error.atmostOne";
- public static final String ATMOST_ONE_MSG =
- "tableSource and values cannot both be defined for an argument. Choose One or None.";
-
- private boolean validate;
-
- public ValidateArgsPropertiesValidator(final JsonNode digest) {
- super(KEYWORD);
- validate = digest.get(keyword).booleanValue();
- }
-
- @Override
- public void validate(Processor processor, ProcessingReport report, MessageBundle bundle,
- FullData data) throws ProcessingException {
-
- if (validate) {
- JsonNode instance = data.getInstance().getNode();
- Set fields = Sets.newHashSet(instance.fieldNames());
-
- if (fields.contains("values") && fields.contains("tableSource")) {
- report.error(newMsg(data, bundle, ATMOST_ONE_KEY));
- }
-
- }
- }
-
- @Override
- public String toString() {
- return keyword;
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateDimPropertiesKeyword.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateDimPropertiesKeyword.java
deleted file mode 100644
index ae99cd1650..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateDimPropertiesKeyword.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jackson.jsonpointer.JsonPointer;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.keyword.syntax.checkers.AbstractSyntaxChecker;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.core.tree.SchemaTree;
-import com.github.fge.jsonschema.keyword.digest.AbstractDigester;
-import com.github.fge.jsonschema.library.Keyword;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import lombok.Getter;
-
-import java.util.Collection;
-
-/**
- * Creates custom keyword for {@code validateDimensionProperties}.
- */
-public class ValidateDimPropertiesKeyword {
-
- @Getter
- private Keyword keyword;
-
- public ValidateDimPropertiesKeyword() {
- keyword = Keyword.newBuilder(ValidateDimPropertiesValidator.KEYWORD)
- .withSyntaxChecker(new ValidateDimPropertiesSyntaxChecker())
- .withDigester(new ValidateDimPropertiesDigester())
- .withValidatorClass(ValidateDimPropertiesValidator.class)
- .freeze();
- }
-
- /**
- * Defines custom SyntaxChecker for {@code validateDimensionProperties}.
- */
- private class ValidateDimPropertiesSyntaxChecker extends AbstractSyntaxChecker {
-
- public ValidateDimPropertiesSyntaxChecker() {
- super(ValidateDimPropertiesValidator.KEYWORD, NodeType.BOOLEAN);
- }
-
- @Override
- protected void checkValue(Collection pointers, MessageBundle bundle, ProcessingReport report,
- SchemaTree tree) throws ProcessingException {
- // AbstractSyntaxChecker has already verified that value is of type Boolean
- // No additional Checks Required
- }
- }
-
- /**
- * Defines custom Digester for {@code validateDimensionProperties}.
- */
- private class ValidateDimPropertiesDigester extends AbstractDigester {
-
- public ValidateDimPropertiesDigester() {
- super(ValidateDimPropertiesValidator.KEYWORD, NodeType.OBJECT);
- }
-
- @Override
- public JsonNode digest(final JsonNode schema) {
- final ObjectNode node = FACTORY.objectNode();
- node.put(keyword, schema.get(keyword).asBoolean(true));
- return node;
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateDimPropertiesValidator.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateDimPropertiesValidator.java
deleted file mode 100644
index 718a1430f1..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateDimPropertiesValidator.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.processing.Processor;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.keyword.validator.AbstractKeywordValidator;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-
-import java.util.Set;
-
-/**
- * Defines custom Keyword Validator for {@code validateDimensionProperties}.
- *
- * This validator checks neither additional properties are defined for any dimension nor not both {@code tableSource}
- * and {@code values} property is defined for any dimension.
- *
- */
-public class ValidateDimPropertiesValidator extends AbstractKeywordValidator {
-
- public static final Set COMMON_DIM_PROPERTIES = ImmutableSet.of("name", "friendlyName",
- "description", "category", "hidden", "readAccess", "definition", "cardinality", "tags", "type",
- "arguments", "filterTemplate");
- private static final Set ADDITIONAL_DIM_PROPERTIES = ImmutableSet.of("values", "tableSource");
-
- public static final String KEYWORD = "validateDimensionProperties";
- public static final String ATMOST_ONE_KEY = "validateDimensionProperties.error.atmostOne";
- public static final String ATMOST_ONE_MSG =
- "tableSource and values cannot both be defined for a dimension. Choose One or None.";
- public static final String ADDITIONAL_KEY = "validateDimensionProperties.error.addtional";
- public static final String ADDITIONAL_MSG = "Properties: %s are not allowed for dimensions.";
-
- private boolean validate;
-
- public ValidateDimPropertiesValidator(final JsonNode digest) {
- super(KEYWORD);
- validate = digest.get(keyword).booleanValue();
- }
-
- @Override
- public void validate(Processor processor, ProcessingReport report, MessageBundle bundle,
- FullData data) throws ProcessingException {
-
- if (validate) {
- JsonNode instance = data.getInstance().getNode();
- Set fields = Sets.newHashSet(instance.fieldNames());
-
- if (fields.contains("values") && fields.contains("tableSource")) {
- report.error(newMsg(data, bundle, ATMOST_ONE_KEY));
- }
-
- fields.removeAll(COMMON_DIM_PROPERTIES);
- fields.removeAll(ADDITIONAL_DIM_PROPERTIES);
- if (!fields.isEmpty()) {
- report.error(newMsg(data, bundle, ADDITIONAL_KEY).putArgument("value", fields.toString()));
- }
- }
- }
-
- @Override
- public String toString() {
- return keyword;
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateTimeDimPropertiesKeyword.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateTimeDimPropertiesKeyword.java
deleted file mode 100644
index 7705380e15..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateTimeDimPropertiesKeyword.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.github.fge.jackson.NodeType;
-import com.github.fge.jackson.jsonpointer.JsonPointer;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.keyword.syntax.checkers.AbstractSyntaxChecker;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.core.tree.SchemaTree;
-import com.github.fge.jsonschema.keyword.digest.AbstractDigester;
-import com.github.fge.jsonschema.library.Keyword;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-
-import lombok.Getter;
-
-import java.util.Collection;
-
-/**
- * Creates custom keyword for {@code validateTimeDimensionProperties}.
- */
-public class ValidateTimeDimPropertiesKeyword {
-
- @Getter
- private Keyword keyword;
-
- public ValidateTimeDimPropertiesKeyword() {
- keyword = Keyword.newBuilder(ValidateTimeDimPropertiesValidator.KEYWORD)
- .withSyntaxChecker(new ValidateTimeDimPropertiesSyntaxChecker())
- .withDigester(new ValidateTimeDimPropertiesDigester())
- .withValidatorClass(ValidateTimeDimPropertiesValidator.class)
- .freeze();
- }
-
- /**
- * Defines custom SyntaxChecker for {@code validateTimeDimensionProperties}.
- */
- private class ValidateTimeDimPropertiesSyntaxChecker extends AbstractSyntaxChecker {
-
- public ValidateTimeDimPropertiesSyntaxChecker() {
- super(ValidateTimeDimPropertiesValidator.KEYWORD, NodeType.BOOLEAN);
- }
-
- @Override
- protected void checkValue(Collection pointers, MessageBundle bundle, ProcessingReport report,
- SchemaTree tree) throws ProcessingException {
- // AbstractSyntaxChecker has already verified that value is of type Boolean
- // No additional Checks Required
- }
- }
-
- /**
- * Defines custom Digester for {@code validateTimeDimensionProperties}.
- */
- private class ValidateTimeDimPropertiesDigester extends AbstractDigester {
-
- public ValidateTimeDimPropertiesDigester() {
- super(ValidateTimeDimPropertiesValidator.KEYWORD, NodeType.OBJECT);
- }
-
- @Override
- public JsonNode digest(final JsonNode schema) {
- final ObjectNode node = FACTORY.objectNode();
- node.put(keyword, schema.get(keyword).asBoolean(true));
- return node;
- }
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateTimeDimPropertiesValidator.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateTimeDimPropertiesValidator.java
deleted file mode 100644
index 1b4194875d..0000000000
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/jsonformats/ValidateTimeDimPropertiesValidator.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2020, Yahoo Inc.
- * Licensed under the Apache License, Version 2.0
- * See LICENSE file in project root for terms.
- */
-package com.yahoo.elide.modelconfig.jsonformats;
-
-import static com.yahoo.elide.modelconfig.jsonformats.ValidateDimPropertiesValidator.COMMON_DIM_PROPERTIES;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.processing.Processor;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.keyword.validator.AbstractKeywordValidator;
-import com.github.fge.jsonschema.processors.data.FullData;
-import com.github.fge.msgsimple.bundle.MessageBundle;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-
-import java.util.Set;
-
-/**
- * Defines custom Keyword Validator for {@code validateTimeDimensionProperties}.
- *
- * This validator checks no additional properties are defined for any time dimension.
- *
- */
-public class ValidateTimeDimPropertiesValidator extends AbstractKeywordValidator {
-
- private static final Set ADDITIONAL_TIME_DIM_PROPERTIES = ImmutableSet.of("grains");
-
- public static final String KEYWORD = "validateTimeDimensionProperties";
- public static final String ADDITIONAL_KEY = "validateTimeDimensionProperties.error.addtional";
- public static final String ADDITIONAL_MSG = "Properties: %s are not allowed for time dimensions.";
-
- private boolean validate;
-
- public ValidateTimeDimPropertiesValidator(final JsonNode digest) {
- super(KEYWORD);
- validate = digest.get(keyword).booleanValue();
- }
-
- @Override
- public void validate(Processor processor, ProcessingReport report, MessageBundle bundle,
- FullData data) throws ProcessingException {
-
- if (validate) {
- JsonNode instance = data.getInstance().getNode();
- Set fields = Sets.newHashSet(instance.fieldNames());
-
- fields.removeAll(COMMON_DIM_PROPERTIES);
- fields.removeAll(ADDITIONAL_TIME_DIM_PROPERTIES);
- if (!fields.isEmpty()) {
- report.error(newMsg(data, bundle, ADDITIONAL_KEY).putArgument("value", fields.toString()));
- }
- }
- }
-
- @Override
- public String toString() {
- return keyword;
- }
-}
diff --git a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/validator/DynamicConfigValidator.java b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/validator/DynamicConfigValidator.java
index 72524e99a4..f71bc64501 100644
--- a/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/validator/DynamicConfigValidator.java
+++ b/elide-model-config/src/main/java/com/yahoo/elide/modelconfig/validator/DynamicConfigValidator.java
@@ -46,12 +46,11 @@
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
-import org.apache.commons.collections.CollectionUtils;
import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -69,7 +68,6 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
-@Slf4j
/**
* Util class to validate and parse the config files. Optionally compiles config files.
*/
@@ -81,11 +79,6 @@ public class DynamicConfigValidator implements DynamicConfiguration, Validator {
private static final String SQL_SPLIT_REGEX = "\\s+";
private static final String SEMI_COLON = ";";
private static final Pattern HANDLEBAR_REGEX = Pattern.compile("<%(.*?)%>");
- private static final String RESOURCES = "resources";
- private static final int RESOURCES_LENGTH = 9; //"resources".length()
- private static final String CLASSPATH_PATTERN = "classpath*:";
- private static final String FILEPATH_PATTERN = "file:";
- private static final String HJSON_EXTN = "**/*.hjson";
@Getter private final ElideTableConfig elideTableConfig = new ElideTableConfig();
@Getter private ElideSecurityConfig elideSecurityConfig;
@@ -323,7 +316,7 @@ public interface Inheritance {
}
private Map getInheritedMeasures(Table table, Map measures) {
- Inheritance action = () -> {
+ Inheritance> action = () -> {
table.getMeasures().forEach(measure -> {
if (!measures.containsKey(measure.getName())) {
measures.put(measure.getName(), measure);
@@ -337,7 +330,7 @@ private Map getInheritedMeasures(Table table, Map getInheritedDimensions(Table table, Map dimensions) {
- Inheritance action = () -> {
+ Inheritance> action = () -> {
table.getDimensions().forEach(dimension -> {
if (!dimensions.containsKey(dimension.getName())) {
dimensions.put(dimension.getName(), dimension);
@@ -351,7 +344,7 @@ private Map getInheritedDimensions(Table table, Map getInheritedJoins(Table table, Map joins) {
- Inheritance action = () -> {
+ Inheritance> action = () -> {
table.getJoins().forEach(join -> {
if (!joins.containsKey(join.getName())) {
joins.put(join.getName(), join);
@@ -364,42 +357,32 @@ private Map getInheritedJoins(Table table, Map joins
return joins;
}
- private T getInheritedAttribute(Inheritance action, T property) {
- return property == null ? (T) action.inherit() : property;
+ private T getInheritedAttribute(Inheritance action, T property) {
+ return property == null ? action.inherit() : property;
}
- private Collection getInheritedAttribute(Inheritance action, Collection property) {
- return CollectionUtils.isEmpty(property) ? (Collection) action.inherit() : property;
+ private > T getInheritedAttribute(Inheritance action, T property) {
+ return property == null || property.isEmpty() ? action.inherit() : property;
}
private String getInheritedSchema(Table table, String schema) {
- Inheritance action = table::getSchema;
-
- return getInheritedAttribute(action, schema);
+ return getInheritedAttribute(table::getSchema, schema);
}
private String getInheritedConnection(Table table, String connection) {
- Inheritance action = table::getDbConnectionName;
-
- return getInheritedAttribute(action, connection);
+ return getInheritedAttribute(table::getDbConnectionName, connection);
}
private String getInheritedSql(Table table, String sql) {
- Inheritance action = table::getSql;
-
- return getInheritedAttribute(action, sql);
+ return getInheritedAttribute(table::getSql, sql);
}
private String getInheritedTable(Table table, String tableName) {
- Inheritance action = table::getTable;
-
- return getInheritedAttribute(action, tableName);
+ return getInheritedAttribute(table::getTable, tableName);
}
private List getInheritedArguments(Table table, List arguments) {
- Inheritance action = table::getArguments;
-
- return (List) getInheritedAttribute(action, arguments);
+ return getInheritedAttribute(table::getArguments, arguments);
}
/**
@@ -418,7 +401,7 @@ private Map readVariableConfig(Config config, Map resourceM
return DynamicConfigHelpers.stringToElideSecurityPojo(entry.getKey(),
content, this.modelVariables, schemaValidator);
} catch (IOException e) {
- throw new IllegalStateException(e);
+ throw new UncheckedIOException(e.getMessage(), e);
}
})
.findAny()
@@ -465,7 +448,7 @@ private Set readDbConfig(Map resourceMap) {
return DynamicConfigHelpers.stringToElideDBConfigPojo(entry.getKey(),
content, this.dbVariables, schemaValidator);
} catch (IOException e) {
- throw new IllegalStateException(e);
+ throw new UncheckedIOException(e.getMessage(), e);
}
})
.flatMap(dbconfig -> dbconfig.getDbconfigs().stream())
@@ -490,7 +473,7 @@ private Set readNamespaceConfig(Map resourc
return DynamicConfigHelpers.stringToElideNamespaceConfigPojo(fileName,
content, this.modelVariables, schemaValidator);
} catch (IOException e) {
- throw new IllegalStateException(e);
+ throw new UncheckedIOException(e.getMessage(), e);
}
})
.flatMap(namespaceconfig -> namespaceconfig.getNamespaceconfigs().stream())
@@ -513,7 +496,7 @@ private Set readTableConfig(Map resourceMap) {
return DynamicConfigHelpers.stringToElideTablePojo(entry.getKey(),
content, this.modelVariables, schemaValidator);
} catch (IOException e) {
- throw new IllegalStateException(e);
+ throw new UncheckedIOException(e.getMessage(), e);
}
})
.flatMap(table -> table.getTables().stream())
@@ -604,7 +587,7 @@ private boolean validateNamespaceConfig() {
extractChecksFromExpr(namespace.getReadAccess(), extractedChecks, visitor);
}
- validateChecks(extractedChecks, Collections.EMPTY_SET);
+ validateChecks(extractedChecks, Collections.emptySet());
return true;
}
diff --git a/elide-model-config/src/main/resources/elideDBConfigSchema.json b/elide-model-config/src/main/resources/elideDBConfigSchema.json
index 371cbc2627..ce3d6a7d46 100644
--- a/elide-model-config/src/main/resources/elideDBConfigSchema.json
+++ b/elide-model-config/src/main/resources/elideDBConfigSchema.json
@@ -1,5 +1,28 @@
{
- "$schema": "https://json-schema.org/draft-04/schema#",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$defs": {
+ "elideName" : {
+ "type": "string",
+ "pattern": "^[A-Za-z][0-9A-Za-z_]*$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideName pattern must start with an alphabetic character and can include alphabets, numbers and ''_'' only."
+ }
+ },
+ "elideJdbcUrl" : {
+ "type": "string",
+ "pattern": "^(jdbc:).*$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideJdbcUrl pattern must start with ''jdbc:''."
+ }
+ },
+ "javaClassName" : {
+ "type": "string",
+ "pattern": "^(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)+(\\.\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)*$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the javaClassName pattern is not a valid Java class name."
+ }
+ }
+ },
"type": "object",
"title": "Elide DB Config Root Schema",
"description": "Elide database connection config json/hjson schema",
@@ -28,28 +51,25 @@
"additionalProperties": false,
"properties": {
"name": {
- "type": "string",
"title": "DB Connection Name",
"description": "Name of the database connection. This will be used for the persistent unit name.",
- "format": "elideName",
+ "$ref": "#/$defs/elideName",
"examples": [
"MySQLConnection"
]
},
"url": {
- "type": "string",
"title": "JDBC URL",
"description": "JDBC URL for the database connection i.e. javax.persistence.jdbc.URL",
- "format": "elideJdbcUrl",
+ "$ref": "#/$defs/elideJdbcUrl",
"examples": [
"jdbc:mysql://localhost/elide?serverTimezone=UTC"
]
},
"driver": {
- "type": "string",
"title": "JDBC Driver Name",
"description": "JDBC Driver for the database connection i.e. javax.persistence.jdbc.driver",
- "format": "javaClassName",
+ "$ref": "#/$defs/javaClassName",
"examples": [
"com.mysql.jdbc.Driver"
]
@@ -63,10 +83,9 @@
]
},
"dialect": {
- "type": "string",
"title": "Elide Dialect",
"description": "The Elide Dialect to use for query generation.",
- "format": "javaClassName",
+ "$ref": "#/$defs/javaClassName",
"examples": [
"com.yahoo.elide.datastores.aggregation.queryengines.sql.dialects.impl.H2Dialect"
]
diff --git a/elide-model-config/src/main/resources/elideNamespaceConfigSchema.json b/elide-model-config/src/main/resources/elideNamespaceConfigSchema.json
index 98ff167149..ac859c0551 100644
--- a/elide-model-config/src/main/resources/elideNamespaceConfigSchema.json
+++ b/elide-model-config/src/main/resources/elideNamespaceConfigSchema.json
@@ -1,5 +1,14 @@
{
- "$schema": "https://json-schema.org/draft-04/schema#",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$defs": {
+ "elideNamespaceName" : {
+ "type": "string",
+ "pattern": "^default$|^(?!(?i)default$)^[A-Za-z][0-9A-Za-z_]*$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideNamespaceName pattern must start with an alphabetic character and can include alphabets, numbers and ''_'' only and must not clash with the ''default'' namespace."
+ }
+ }
+ },
"type": "object",
"title": "Elide Namespace Config Root Schema",
"description": "Elide Namespace config json/hjson schema",
@@ -24,10 +33,9 @@
"additionalProperties": false,
"properties": {
"name": {
- "type": "string",
"title": "Namespace Name",
"description": "Name of the Namespace. This can used for grouping the tables by subject area.",
- "format": "elideNamespaceName",
+ "$ref": "#/$defs/elideNamespaceName",
"examples": [
"MyNamespace"
]
diff --git a/elide-model-config/src/main/resources/elideSecuritySchema.json b/elide-model-config/src/main/resources/elideSecuritySchema.json
index fa27e55313..d64c4f9f5f 100644
--- a/elide-model-config/src/main/resources/elideSecuritySchema.json
+++ b/elide-model-config/src/main/resources/elideSecuritySchema.json
@@ -1,5 +1,14 @@
{
- "$schema": "https://json-schema.org/draft-04/schema#",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$defs": {
+ "elideRole" : {
+ "type": "string",
+ "pattern": "^[A-Za-z][0-9A-Za-z. ]*$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideRole pattern must start with an alphabetic character and can include alphabets, numbers, spaces and ''.'' only."
+ }
+ }
+ },
"description": "Elide Security config json/hjson schema",
"type": "object",
"properties": {
@@ -9,8 +18,7 @@
"type": "array",
"uniqueItems": true,
"items": {
- "type": "string",
- "format": "elideRole"
+ "$ref": "#/$defs/elideRole"
}
},
"rules": {
diff --git a/elide-model-config/src/main/resources/elideTableSchema.json b/elide-model-config/src/main/resources/elideTableSchema.json
index e3eb50549e..ab52b75b7f 100644
--- a/elide-model-config/src/main/resources/elideTableSchema.json
+++ b/elide-model-config/src/main/resources/elideTableSchema.json
@@ -1,6 +1,90 @@
{
- "$schema": "https://json-schema.org/draft-04/schema#",
- "definitions": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$defs": {
+ "elideArgumentName" : {
+ "type": "string",
+ "pattern": "^(?!(?i)grain$)^[A-Za-z][0-9A-Za-z_]*$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideArgumentName pattern must start with an alphabetic character and can include alphabets, numbers and ''_'' only and cannot be ''grain''."
+ }
+ },
+ "elideFieldType" : {
+ "type": "string",
+ "pattern": "^(?i)(Integer|Decimal|Money|Text|Coordinate|Boolean|Enum_Text|Enum_Ordinal)$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideFieldType pattern must be one of [Integer, Decimal, Money, Text, Coordinate, Boolean, Enum_Text, Enum_Ordinal]."
+ }
+ },
+ "elideFieldName" : {
+ "type": "string",
+ "pattern": "^(?!(?i)(id|sql)$)^[a-z][0-9A-Za-z_]*$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideFieldName pattern must start with lower case alphabet and can include alphabets, numbers and ''_'' only and cannot be one of [id, sql]"
+ }
+ },
+ "elideName" : {
+ "type": "string",
+ "pattern": "^[A-Za-z][0-9A-Za-z_]*$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideName pattern must start with an alphabetic character and can include alphabets, numbers and ''_'' only."
+ }
+ },
+ "elideNamespaceName" : {
+ "type": "string",
+ "pattern": "^default$|^(?!(?i)default$)^[A-Za-z][0-9A-Za-z_]*$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideNamespaceName pattern must start with an alphabetic character and can include alphabets, numbers and ''_'' only and must not clash with the ''default'' namespace."
+ }
+ },
+ "elideJoinType" : {
+ "type": "string",
+ "pattern": "^(?i)(left|inner|full|cross)$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideJoinType pattern must be one of [left, inner, full, cross]."
+ }
+ },
+ "elideJoinKind" : {
+ "type": "string",
+ "pattern": "^(?i)(ToOne|ToMany)$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideJoinKind pattern must be one of [ToOne, ToMany]."
+ }
+ },
+ "javaClassName" : {
+ "type": "string",
+ "pattern": "^(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)+(\\.\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)*$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the javaClassName pattern is not a valid Java class name."
+ }
+ },
+ "javaClassNameWithExt" : {
+ "type": "string",
+ "pattern": "^(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)+(\\.\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)*class$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the javaClassNameWithExt pattern is not a valid Java class name with .class extension."
+ }
+ },
+ "elideCardinality" : {
+ "type": "string",
+ "pattern": "^(?i)(Tiny|Small|Medium|Large|Huge)$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideCardinality pattern must be one of [Tiny, Small, Medium, Large, Huge]."
+ }
+ },
+ "elideTimeFieldType" : {
+ "type": "string",
+ "pattern": "^(?i)(Time)$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideTimeFieldType pattern must be [Time] for any time dimension."
+ }
+ },
+ "elideGrainType" : {
+ "type": "string",
+ "pattern": "^(?i)(Second|Minute|Hour|Day|IsoWeek|Week|Month|Quarter|Year)$",
+ "errorMessage": {
+ "pattern": "{0}: does not match the elideGrainType pattern must be one of [Second, Minute, Hour, Day, IsoWeek, Week, Month, Quarter, Year]."
+ }
+ },
"argument" : {
"title" : "Arguments",
"description" : "Arguments are supported for table, measures and dimensions.",
@@ -8,9 +92,8 @@
"properties": {
"name": {
"title": "Argument name",
- "description": "Name must start with an alphabetic character and can include alaphabets, numbers and '_' only.",
- "type": "string",
- "format": "elideArgumentName"
+ "description": "Name must start with an alphabetic character and can include alphabets, numbers and '_' only.",
+ "$ref": "#/$defs/elideArgumentName"
},
"description": {
"title": "Argument description",
@@ -20,8 +103,7 @@
"type": {
"title": "Argument type",
"description": "Must be one of Integer, Decimal, Money, Text, Coordinate, Boolean",
- "type": "string",
- "format": "elideFieldType"
+ "$ref": "#/$defs/elideFieldType"
},
"values": {
"title": "Argument values",
@@ -33,7 +115,7 @@
}
},
"tableSource": {
- "$ref": "#/definitions/tableSource"
+ "$ref": "#/$defs/tableSource"
},
"default": {
"title": "Default argument value",
@@ -50,8 +132,16 @@
"type",
"default"
],
- "validateArgumentProperties": true,
- "additionalProperties": false
+ "not": {
+ "required": [
+ "tableSource",
+ "values"
+ ]
+ },
+ "additionalProperties": false,
+ "errorMessage": {
+ "not": "{0}: tableSource and values cannot both be defined for an argument. Choose One or None."
+ }
},
"join": {
"title": "Join",
@@ -61,33 +151,28 @@
"name": {
"title": "Join name",
"description": "The name of the join relationship.",
- "type": "string",
- "format": "elideFieldName"
+ "$ref": "#/$defs/elideFieldName"
},
"namespace": {
"title": "Join Namespace",
"description": "Namespace for the Join.",
- "type": "string",
- "format": "elideNamespaceName",
+ "$ref": "#/$defs/elideNamespaceName",
"default": "default"
},
"to": {
"title": "Join table name",
"description": "The name of the table that is being joined to",
- "type": "string",
- "format": "elideName"
+ "$ref": "#/$defs/elideName"
},
"type": {
"title": "Type of Join",
"description": "Type of the join - left, inner, full or cross",
- "type": "string",
- "format": "elideJoinType"
+ "$ref": "#/$defs/elideJoinType"
},
"kind": {
"title": "Kind of Join",
"description": "Kind of the join - toOne or toMany",
- "type": "string",
- "format": "elideJoinKind"
+ "$ref": "#/$defs/elideJoinKind"
},
"definition": {
"title": "Join definition SQL",
@@ -109,21 +194,18 @@
"table": {
"title": "Source table",
"description": "The source table that contains the colum or argument values.",
- "type": "string",
- "format": "elideName"
+ "$ref": "#/$defs/elideName"
},
"namespace": {
"title": "Source table namespace",
"description": "Namespace for the source table.",
- "type": "string",
- "format": "elideNamespaceName",
+ "$ref": "#/$defs/elideNamespaceName",
"default": "default"
},
"column": {
"title": "Primary source table column name",
"description": "The column that provides a unique list of values for the given column or argument",
- "type": "string",
- "format": "elideFieldName"
+ "$ref": "#/$defs/elideFieldName"
},
"suggestionColumns": {
"title": "Secondary search columns",
@@ -131,8 +213,7 @@
"type": "array",
"uniqueItems": true,
"items": {
- "type": "string",
- "format": "elideFieldName"
+ "$ref": "#/$defs/elideFieldName"
}
}
},
@@ -150,8 +231,7 @@
"name": {
"title": "Metric name",
"description": "The name of the metric. This will be the same as the POJO field name.",
- "type": "string",
- "format": "elideFieldName"
+ "$ref": "#/$defs/elideFieldName"
},
"friendlyName": {
"title": "Metric friendly name",
@@ -188,14 +268,12 @@
"maker": {
"title": "Metric Projection Maker",
"description": "Registers a custom function to create a projection for this metric",
- "type": "string",
- "format": "javaClassName"
+ "$ref": "#/$defs/javaClassName"
},
"type": {
"title": "Measure field type",
"description": "The data type of the measure field",
- "type": "string",
- "format": "elideFieldType"
+ "$ref": "#/$defs/elideFieldType"
},
"tags": {
"title": "Measure tags",
@@ -211,7 +289,7 @@
"description": "An array of supported arguments for measure",
"type": "array",
"items": {
- "$ref": "#/definitions/argument"
+ "$ref": "#/$defs/argument"
}
},
"filterTemplate": {
@@ -247,8 +325,7 @@
"name": {
"title": "Dimension name",
"description": "The name of the dimension. This will be the same as the POJO field name.",
- "type": "string",
- "format": "elideFieldName"
+ "$ref": "#/$defs/elideFieldName"
},
"friendlyName": {
"title": "Dimension friendly name",
@@ -285,8 +362,7 @@
"cardinality": {
"title": "Dimension cardinality",
"description": "Dimension cardinality: (tiny, small, medium, large, huge). The relative sizes are decided by the table designer(s).",
- "type": "string",
- "format": "elideCardiality"
+ "$ref": "#/$defs/elideCardinality"
},
"tags": {
"title": "Dimension tags",
@@ -302,7 +378,7 @@
"description": "An array of supported arguments for dimensions",
"type": "array",
"items": {
- "$ref": "#/definitions/argument"
+ "$ref": "#/$defs/argument"
}
},
"filterTemplate": {
@@ -319,15 +395,14 @@
"type": "object",
"allOf": [
{
- "$ref": "#/definitions/dimensionRef"
+ "$ref": "#/$defs/dimensionRef"
},
{
"properties": {
"type": {
"title": "Dimension field type",
"description": "The data type of the dimension field",
- "type": "string",
- "format": "elideFieldType"
+ "$ref": "#/$defs/elideFieldType"
},
"values": {
"title": "Dimension values",
@@ -339,17 +414,42 @@
}
},
"tableSource": {
- "$ref": "#/definitions/tableSource"
+ "$ref": "#/$defs/tableSource"
}
}
}
],
- "validateDimensionProperties": true,
"required": [
"name",
"type",
"definition"
- ]
+ ],
+ "properties": {
+ "name": true,
+ "friendlyName": true,
+ "description": true,
+ "category": true,
+ "hidden": true,
+ "readAccess": true,
+ "definition": true,
+ "cardinality": true,
+ "tags": true,
+ "type": true,
+ "arguments": true,
+ "filterTemplate": true,
+ "values": true,
+ "tableSource": true
+ },
+ "additionalProperties": false,
+ "not": {
+ "required": [
+ "tableSource",
+ "values"
+ ]
+ },
+ "errorMessage": {
+ "not": "{0}: tableSource and values cannot both be defined for a dimension. Choose One or None."
+ }
},
"timeDimension": {
"title": "Time Dimension",
@@ -357,15 +457,14 @@
"type": "object",
"allOf": [
{
- "$ref": "#/definitions/dimensionRef"
+ "$ref": "#/$defs/dimensionRef"
},
{
"properties": {
"type": {
"title": "Dimension field type",
"description": "The data type of the dimension field",
- "type": "string",
- "format": "elideTimeFieldType"
+ "$ref": "#/$defs/elideTimeFieldType"
},
"grains" : {
"title" : "Time Dimension grains",
@@ -379,8 +478,7 @@
"type": {
"title": "Time granularity",
"description": "Indicates grain time granularity",
- "type": "string",
- "format": "elideGrainType"
+ "$ref": "#/$defs/elideGrainType"
},
"sql": {
"title": "Grain SQL",
@@ -395,12 +493,27 @@
}
}
],
- "validateTimeDimensionProperties": true,
"required": [
"name",
"type",
"definition"
- ]
+ ],
+ "properties": {
+ "name": true,
+ "friendlyName": true,
+ "description": true,
+ "category": true,
+ "hidden": true,
+ "readAccess": true,
+ "definition": true,
+ "cardinality": true,
+ "tags": true,
+ "type": true,
+ "arguments": true,
+ "filterTemplate": true,
+ "grains": true
+ },
+ "additionalProperties": false
}
},
"type": "object",
@@ -421,8 +534,7 @@
"name": {
"title": "Table Model Name",
"description": "The name of the model. This will be the same as the POJO class name.",
- "type": "string",
- "format": "elideName"
+ "$ref": "#/$defs/elideName"
},
"friendlyName": {
"title": "Table friendly name",
@@ -455,8 +567,7 @@
"cardinality": {
"title": "Table cardinality",
"description": "Table cardinality: (tiny, small, medium, large, huge). The relative sizes are decided by the table designer(s).",
- "type": "string",
- "format": "elideCardiality"
+ "$ref": "#/$defs/elideCardinality"
},
"readAccess": {
"title": "Table read access",
@@ -467,8 +578,7 @@
"namespace": {
"title": "Table Namespace",
"description": "Namespace for the table.",
- "type": "string",
- "format": "elideNamespaceName",
+ "$ref": "#/$defs/elideNamespaceName",
"default": "default"
},
"hints": {
@@ -485,7 +595,7 @@
"description": "Describes SQL joins to other tables for column references.",
"type": "array",
"items": {
- "$ref": "#/definitions/join"
+ "$ref": "#/$defs/join"
}
},
"measures": {
@@ -493,7 +603,7 @@
"description": "Zero or more metric definitions.",
"type": "array",
"items": {
- "$ref": "#/definitions/measure"
+ "$ref": "#/$defs/measure"
}
},
"dimensions": {
@@ -503,10 +613,10 @@
"items": {
"oneOf": [
{
- "$ref": "#/definitions/dimension"
+ "$ref": "#/$defs/dimension"
},
{
- "$ref": "#/definitions/timeDimension"
+ "$ref": "#/$defs/timeDimension"
}
]
}
@@ -525,7 +635,7 @@
"description": "An array of supported arguments for tables.",
"type": "array",
"items": {
- "$ref": "#/definitions/argument"
+ "$ref": "#/$defs/argument"
}
}
},
@@ -540,8 +650,7 @@
"dbConnectionName": {
"title": "DB Connection Name",
"description": "The database connection name for this model.",
- "type": "string",
- "format": "elideName"
+ "$ref": "#/$defs/elideName"
}
},
"required": [
@@ -555,14 +664,12 @@
"maker": {
"title": "Table SQL maker function",
"description": "JVM function to invoke to generate the SQL query which is used to populate the table.",
- "type": "string",
- "format": "javaClassName"
+ "$ref": "#/$defs/javaClassName"
},
"dbConnectionName": {
"title": "DB Connection Name",
"description": "The database connection name for this model.",
- "type": "string",
- "format": "elideName"
+ "$ref": "#/$defs/elideName"
}
},
"required": [
@@ -586,8 +693,7 @@
"dbConnectionName": {
"title": "DB Connection Name",
"description": "The database connection name for this model.",
- "type": "string",
- "format": "elideName"
+ "$ref": "#/$defs/elideName"
}
},
"required": [
@@ -601,8 +707,7 @@
"extend": {
"title": "Table Extends",
"description": "Extends another logical table.",
- "type": "string",
- "format": "elideName"
+ "$ref": "#/$defs/elideName"
}
},
"required": [
diff --git a/elide-model-config/src/main/resources/elideVariableSchema.json b/elide-model-config/src/main/resources/elideVariableSchema.json
index 3b8d46d1a8..c17110edb0 100644
--- a/elide-model-config/src/main/resources/elideVariableSchema.json
+++ b/elide-model-config/src/main/resources/elideVariableSchema.json
@@ -1,5 +1,5 @@
{
- "$schema": "https://json-schema.org/draft-04/schema#",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Elide Variable config json/hjson schema",
"type": "object",
"patternProperties": {
diff --git a/elide-model-config/src/test/java/com/yahoo/elide/modelconfig/DynamicConfigSchemaValidatorTest.java b/elide-model-config/src/test/java/com/yahoo/elide/modelconfig/DynamicConfigSchemaValidatorTest.java
index ad31cd445f..65c451c5c3 100644
--- a/elide-model-config/src/test/java/com/yahoo/elide/modelconfig/DynamicConfigSchemaValidatorTest.java
+++ b/elide-model-config/src/test/java/com/yahoo/elide/modelconfig/DynamicConfigSchemaValidatorTest.java
@@ -31,11 +31,15 @@ public void testValidSecuritySchemas() throws Exception {
@Test
public void testInvalidSecuritySchema() throws Exception {
String jsonConfig = loadHjsonFromClassPath("/validator/invalid_schema/security_invalid.hjson");
- Exception e = assertThrows(IllegalStateException.class,
+ Exception e = assertThrows(InvalidSchemaException.class,
() -> testClass.verifySchema(Config.SECURITY, jsonConfig, "security_invalid.hjson"));
- String expectedMessage = "Schema validation failed for: security_invalid.hjson\n"
- + "[ERROR]\n"
- + "object instance has properties which are not allowed by the schema: [\"cardinality\",\"description\",\"name\",\"schema$\",\"table\"]";
+ String expectedMessage = """
+ Schema validation failed for: security_invalid.hjson
+ : property 'name' is not defined in the schema and the schema does not allow additional properties
+ : property 'table' is not defined in the schema and the schema does not allow additional properties
+ : property 'schema$' is not defined in the schema and the schema does not allow additional properties
+ : property 'description' is not defined in the schema and the schema does not allow additional properties
+ : property 'cardinality' is not defined in the schema and the schema does not allow additional properties""";
assertEquals(expectedMessage.replaceAll("\n", System.lineSeparator()), e.getMessage());
}
@@ -48,13 +52,12 @@ public void testValidVariableSchema() throws Exception {
@Test
public void testInvalidVariableSchema() throws Exception {
String jsonConfig = loadHjsonFromClassPath("/validator/invalid_schema/variables_invalid.hjson");
- Exception e = assertThrows(IllegalStateException.class,
+ Exception e = assertThrows(InvalidSchemaException.class,
() -> testClass.verifySchema(Config.MODELVARIABLE, jsonConfig, "variables.hjson"));
- String expectedMessage = "Schema validation failed for: variables.hjson\n"
- + "[ERROR]\n"
- + "object instance has properties which are not allowed by the schema: [\"schema$\"]\n"
- + "[ERROR]\n"
- + "Instance[/cardinality] failed to validate against schema[/patternProperties/^([A-Za-z0-9_]+[.]?)+$]. instance type (null) does not match any allowed primitive type (allowed: [\"array\",\"boolean\",\"integer\",\"number\",\"object\",\"string\"])";
+ String expectedMessage = """
+ Schema validation failed for: variables.hjson
+ /cardinality: null found, [string, number, boolean, array, object] expected
+ : property 'schema$' is not defined in the schema and the schema does not allow additional properties""";
assertEquals(expectedMessage.replaceAll("\n", System.lineSeparator()), e.getMessage());
}
@@ -80,7 +83,7 @@ public void testValidTableSchema(String resource) throws Exception {
public void testInvalidTableSchema(String resource) throws Exception {
String jsonConfig = loadHjsonFromClassPath(resource);
String fileName = getFileName(resource);
- Exception e = assertThrows(IllegalStateException.class,
+ Exception e = assertThrows(InvalidSchemaException.class,
() -> testClass.verifySchema(Config.TABLE, jsonConfig, fileName));
assertTrue(e.getMessage().startsWith("Schema validation failed for: " + fileName));
}
@@ -91,61 +94,68 @@ public void testInvalidTableSchema(String resource) throws Exception {
public void testInvalidTableSchemaMultipleErrors(String resource) throws Exception {
String jsonConfig = loadHjsonFromClassPath(resource);
String fileName = getFileName(resource);
- Exception e = assertThrows(IllegalStateException.class,
+ Exception e = assertThrows(InvalidSchemaException.class,
() -> testClass.verifySchema(Config.TABLE, jsonConfig, fileName));
- String expectedMessage = "Schema validation failed for: table_schema_with_multiple_errors.hjson\n"
- + "[ERROR]\n"
- + "object instance has properties which are not allowed by the schema: [\"name\"]\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/arguments/0] failed to validate against schema[/definitions/argument]. object has missing required properties ([\"default\"])\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/arguments/0/type] failed to validate against schema[/definitions/argument/properties/type]. Field type [Number] is not allowed. Supported value is one of [Integer, Decimal, Money, Text, Coordinate, Boolean, Enum_Text, Enum_Ordinal].\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/arguments/1] failed to validate against schema[/definitions/argument]. object has missing required properties ([\"default\"])\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/arguments/1/name] failed to validate against schema[/definitions/argument/properties/name]. Argument name [Grain] is not allowed. Argument name cannot be 'grain'.\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/arguments/2] failed to validate against schema[/definitions/argument]. tableSource and values cannot both be defined for an argument. Choose One or None.\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/cardinality] failed to validate against schema[/properties/tables/items/properties/cardinality]. Cardinality type [Extra Large] is not allowed. Supported value is one of [Tiny, Small, Medium, Large, Huge].\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/dimensions/0] failed to validate against schema[/properties/tables/items/properties/dimensions/items]. instance failed to match exactly one schema (matched 0 out of 2)\n"
- + " Instance[/tables/0/dimensions/0] failed to validate against schema[/definitions/dimension]. instance failed to match all required schemas (matched only 0 out of 2)\n"
- + " Instance[/tables/0/dimensions/0/cardinality] failed to validate against schema[/definitions/dimensionRef/properties/cardinality]. Cardinality type [Extra small] is not allowed. Supported value is one of [Tiny, Small, Medium, Large, Huge].\n"
- + " Instance[/tables/0/dimensions/0/name] failed to validate against schema[/definitions/dimensionRef/properties/name]. Field name [id] is not allowed. Field name cannot be one of [id, sql]\n"
- + " Instance[/tables/0/dimensions/0/type] failed to validate against schema[/definitions/dimension/allOf/1/properties/type]. Field type [Float] is not allowed. Supported value is one of [Integer, Decimal, Money, Text, Coordinate, Boolean, Enum_Text, Enum_Ordinal].\n"
- + " Instance[/tables/0/dimensions/0] failed to validate against schema[/definitions/timeDimension]. instance failed to match all required schemas (matched only 0 out of 2)\n"
- + " Instance[/tables/0/dimensions/0/cardinality] failed to validate against schema[/definitions/dimensionRef/properties/cardinality]. Cardinality type [Extra small] is not allowed. Supported value is one of [Tiny, Small, Medium, Large, Huge].\n"
- + " Instance[/tables/0/dimensions/0/name] failed to validate against schema[/definitions/dimensionRef/properties/name]. Field name [id] is not allowed. Field name cannot be one of [id, sql]\n"
- + " Instance[/tables/0/dimensions/0/type] failed to validate against schema[/definitions/timeDimension/allOf/1/properties/type]. Field type [Float] is not allowed. Field type must be [Time] for any time dimension.\n"
- + " Instance[/tables/0/dimensions/0] failed to validate against schema[/definitions/timeDimension]. Properties: [tableSource] are not allowed for time dimensions.\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/dimensions/1] failed to validate against schema[/properties/tables/items/properties/dimensions/items]. instance failed to match exactly one schema (matched 0 out of 2)\n"
- + " Instance[/tables/0/dimensions/1] failed to validate against schema[/definitions/dimension]. instance failed to match all required schemas (matched only 1 out of 2)\n"
- + " Instance[/tables/0/dimensions/1/name] failed to validate against schema[/definitions/dimensionRef/properties/name]. Field name [_region] is not allowed. Field name must start with lower case alphabet and can include alaphabets, numbers and '_' only.\n"
- + " Instance[/tables/0/dimensions/1/tags] failed to validate against schema[/definitions/dimensionRef/properties/tags]. instance type (string) does not match any allowed primitive type (allowed: [\"array\"])\n"
- + " Instance[/tables/0/dimensions/1] failed to validate against schema[/definitions/dimension]. tableSource and values cannot both be defined for a dimension. Choose One or None.\n"
- + " Instance[/tables/0/dimensions/1] failed to validate against schema[/definitions/timeDimension]. instance failed to match all required schemas (matched only 0 out of 2)\n"
- + " Instance[/tables/0/dimensions/1/name] failed to validate against schema[/definitions/dimensionRef/properties/name]. Field name [_region] is not allowed. Field name must start with lower case alphabet and can include alaphabets, numbers and '_' only.\n"
- + " Instance[/tables/0/dimensions/1/tags] failed to validate against schema[/definitions/dimensionRef/properties/tags]. instance type (string) does not match any allowed primitive type (allowed: [\"array\"])\n"
- + " Instance[/tables/0/dimensions/1/type] failed to validate against schema[/definitions/timeDimension/allOf/1/properties/type]. Field type [Text] is not allowed. Field type must be [Time] for any time dimension.\n"
- + " Instance[/tables/0/dimensions/1] failed to validate against schema[/definitions/timeDimension]. Properties: [values, tableSource] are not allowed for time dimensions.\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/dimensions/2] failed to validate against schema[/properties/tables/items/properties/dimensions/items]. instance failed to match exactly one schema (matched 0 out of 2)\n"
- + " Instance[/tables/0/dimensions/2] failed to validate against schema[/definitions/dimension]. instance failed to match all required schemas (matched only 1 out of 2)\n"
- + " Instance[/tables/0/dimensions/2/type] failed to validate against schema[/definitions/dimension/allOf/1/properties/type]. Field type [TIMEX] is not allowed. Supported value is one of [Integer, Decimal, Money, Text, Coordinate, Boolean, Enum_Text, Enum_Ordinal].\n"
- + " Instance[/tables/0/dimensions/2] failed to validate against schema[/definitions/dimension]. Properties: [grains] are not allowed for dimensions.\n"
- + " Instance[/tables/0/dimensions/2] failed to validate against schema[/definitions/timeDimension]. instance failed to match all required schemas (matched only 1 out of 2)\n"
- + " Instance[/tables/0/dimensions/2/grains/0/type] failed to validate against schema[/definitions/timeDimension/allOf/1/properties/grains/items/properties/type]. Grain type [Days] is not allowed. Supported value is one of [Second, Minute, Hour, Day, IsoWeek, Week, Month, Quarter, Year].\n"
- + " Instance[/tables/0/dimensions/2/type] failed to validate against schema[/definitions/timeDimension/allOf/1/properties/type]. Field type [TIMEX] is not allowed. Field type must be [Time] for any time dimension.\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/filterTemplate] failed to validate against schema[/properties/tables/items/properties/filterTemplate]. Input value[countryIsoCode={{code}};startTime=={{start}}] is not a valid RSQL filter expression. Please visit page https://elide.io/pages/guide/v5/11-graphql.html#operators for samples.\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/measures/0] failed to validate against schema[/definitions/measure]. instance failed to match exactly one schema (matched 2 out of 2)\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/measures/0/maker] failed to validate against schema[/definitions/measure/properties/maker]. Input value[com.yahoo.elide.datastores.aggregation.query@DefaultMetricProjectionMaker.class] is not a valid Java class name.\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/name] failed to validate against schema[/properties/tables/items/properties/name]. Name [Country@10] is not allowed. Name must start with an alphabetic character and can include alaphabets, numbers and '_' only.";
+ String expectedMessage = """
+ Schema validation failed for: table_schema_with_multiple_errors.hjson
+ /tables/0/name: does not match the elideName pattern must start with an alphabetic character and can include alphabets, numbers and '_' only.
+ /tables/0/filterTemplate: does not match the elideRSQLFilter pattern is not a valid RSQL filter expression. Please visit page https://elide.io/pages/guide/v5/11-graphql.html#operators for samples.
+ /tables/0/cardinality: does not match the elideCardinality pattern must be one of [Tiny, Small, Medium, Large, Huge].
+ /tables/0/measures/0/maker: does not match the javaClassName pattern is not a valid Java class name.
+ /tables/0/measures/0: must be valid to one and only one schema, but 2 are valid with indexes '0, 1'
+ /tables/0/dimensions/0: must be valid to one and only one schema, but 0 are valid
+ /tables/0/dimensions/0/name: does not match the elideFieldName pattern must start with lower case alphabet and can include alphabets, numbers and '_' only and cannot be one of [id, sql]
+ /tables/0/dimensions/0/cardinality: does not match the elideCardinality pattern must be one of [Tiny, Small, Medium, Large, Huge].
+ /tables/0/dimensions/0/type: does not match the elideFieldType pattern must be one of [Integer, Decimal, Money, Text, Coordinate, Boolean, Enum_Text, Enum_Ordinal].
+ /tables/0/dimensions/0/name: does not match the elideFieldName pattern must start with lower case alphabet and can include alphabets, numbers and '_' only and cannot be one of [id, sql]
+ /tables/0/dimensions/0/cardinality: does not match the elideCardinality pattern must be one of [Tiny, Small, Medium, Large, Huge].
+ /tables/0/dimensions/0/type: does not match the elideTimeFieldType pattern must be [Time] for any time dimension.
+ /tables/0/dimensions/0: property 'tableSource' is not defined in the schema and the schema does not allow additional properties
+ /tables/0/dimensions/1: must be valid to one and only one schema, but 0 are valid
+ /tables/0/dimensions/1/name: does not match the elideFieldName pattern must start with lower case alphabet and can include alphabets, numbers and '_' only and cannot be one of [id, sql]
+ /tables/0/dimensions/1/tags: string found, array expected
+ /tables/0/dimensions/1: tableSource and values cannot both be defined for a dimension. Choose One or None.
+ /tables/0/dimensions/1/name: does not match the elideFieldName pattern must start with lower case alphabet and can include alphabets, numbers and '_' only and cannot be one of [id, sql]
+ /tables/0/dimensions/1/tags: string found, array expected
+ /tables/0/dimensions/1/type: does not match the elideTimeFieldType pattern must be [Time] for any time dimension.
+ /tables/0/dimensions/1: property 'values' is not defined in the schema and the schema does not allow additional properties
+ /tables/0/dimensions/1: property 'tableSource' is not defined in the schema and the schema does not allow additional properties
+ /tables/0/dimensions/2: must be valid to one and only one schema, but 0 are valid
+ /tables/0/dimensions/2/type: does not match the elideFieldType pattern must be one of [Integer, Decimal, Money, Text, Coordinate, Boolean, Enum_Text, Enum_Ordinal].
+ /tables/0/dimensions/2: property 'grains' is not defined in the schema and the schema does not allow additional properties
+ /tables/0/dimensions/2/type: does not match the elideTimeFieldType pattern must be [Time] for any time dimension.
+ /tables/0/dimensions/2/grains/0/type: does not match the elideGrainType pattern must be one of [Second, Minute, Hour, Day, IsoWeek, Week, Month, Quarter, Year].
+ /tables/0/arguments/0/type: does not match the elideFieldType pattern must be one of [Integer, Decimal, Money, Text, Coordinate, Boolean, Enum_Text, Enum_Ordinal].
+ /tables/0/arguments/0: required property 'default' not found
+ /tables/0/arguments/1/name: does not match the elideArgumentName pattern must start with an alphabetic character and can include alphabets, numbers and '_' only and cannot be 'grain'.
+ /tables/0/arguments/1: required property 'default' not found
+ /tables/0/arguments/2: tableSource and values cannot both be defined for an argument. Choose One or None.
+ : property 'name' is not defined in the schema and the schema does not allow additional properties""";
+
+ assertEquals(expectedMessage.replaceAll("\n", System.lineSeparator()), e.getMessage());
+ }
+
+ @DisplayName("Invalid Table config")
+ @ParameterizedTest
+ @ValueSource(strings = {"/validator/invalid_schema/table_schema_with_arguments.hjson"})
+ public void testInvalidTableSchemaArgument(String resource) throws Exception {
+ String jsonConfig = loadHjsonFromClassPath(resource);
+ String fileName = getFileName(resource);
+ Exception e = assertThrows(InvalidSchemaException.class,
+ () -> testClass.verifySchema(Config.TABLE, jsonConfig, fileName));
+ String expectedMessage = """
+ Schema validation failed for: table_schema_with_arguments.hjson
+ /tables/0/filterTemplate: does not match the elideRSQLFilter pattern is not a valid RSQL filter expression. Please visit page https://elide.io/pages/guide/v5/11-graphql.html#operators for samples.
+ /tables/0/cardinality: does not match the elideCardinality pattern must be one of [Tiny, Small, Medium, Large, Huge].
+ /tables/0/arguments/0: tableSource and values cannot both be defined for an argument. Choose One or None.
+ /tables/0: must be valid to one and only one schema, but 0 are valid
+ /tables/0: required property 'sql' not found
+ /tables/0: required property 'dimensions' not found
+ /tables/0: required property 'maker' not found
+ /tables/0: required property 'dimensions' not found
+ /tables/0: required property 'dimensions' not found
+ /tables/0: required property 'extend' not found
+ : property 'name' is not defined in the schema and the schema does not allow additional properties""";
assertEquals(expectedMessage.replaceAll("\n", System.lineSeparator()), e.getMessage());
}
@@ -165,19 +175,15 @@ public void testValidDbSchema(String resource) throws Exception {
@Test
public void testInvalidDbSchema() throws Exception {
String jsonConfig = loadHjsonFromClassPath("/validator/invalid_schema/db_invalid.hjson");
- Exception e = assertThrows(IllegalStateException.class,
+ Exception e = assertThrows(InvalidSchemaException.class,
() -> testClass.verifySchema(Config.SQLDBConfig, jsonConfig, "db_invalid.hjson"));
- String expectedMessage = "Schema validation failed for: db_invalid.hjson\n"
- + "[ERROR]\n"
- + "Instance[/dbconfigs/0/driver] failed to validate against schema[/properties/dbconfigs/items/properties/driver]. Input value[11COM.ibm.db2.jdbc.net.DB2Driver] is not a valid Java class name.\n"
- + "[ERROR]\n"
- + "Instance[/dbconfigs/0/name] failed to validate against schema[/properties/dbconfigs/items/properties/name]. Name [11MyDB2Connection] is not allowed. Name must start with an alphabetic character and can include alaphabets, numbers and '_' only.\n"
- + "[ERROR]\n"
- + "Instance[/dbconfigs/0/propertyMap/hibernate.show_sql] failed to validate against schema[/properties/dbconfigs/items/properties/propertyMap/patternProperties/^([A-Za-z0-9_]+[.]?)+$]. instance type (null) does not match any allowed primitive type (allowed: [\"array\",\"boolean\",\"integer\",\"number\",\"object\",\"string\"])\n"
- + "[ERROR]\n"
- + "Instance[/dbconfigs/1/dialect] failed to validate against schema[/properties/dbconfigs/items/properties/dialect]. instance type (integer) does not match any allowed primitive type (allowed: [\"string\"])\n"
- + "[ERROR]\n"
- + "Instance[/dbconfigs/1/url] failed to validate against schema[/properties/dbconfigs/items/properties/url]. Input value [ojdbc:mysql://localhost/testdb?serverTimezone=UTC] is not a valid JDBC url, it must start with 'jdbc:'.";
+ String expectedMessage = """
+ Schema validation failed for: db_invalid.hjson
+ /dbconfigs/0/name: does not match the elideName pattern must start with an alphabetic character and can include alphabets, numbers and '_' only.
+ /dbconfigs/0/driver: does not match the javaClassName pattern is not a valid Java class name.
+ /dbconfigs/0/propertyMap/hibernate.show_sql: null found, [string, number, boolean, array, object] expected
+ /dbconfigs/1/url: does not match the elideJdbcUrl pattern must start with 'jdbc:'.
+ /dbconfigs/1/dialect: integer found, string expected""";
assertEquals(expectedMessage.replaceAll("\n", System.lineSeparator()), e.getMessage());
}
diff --git a/elide-model-config/src/test/java/com/yahoo/elide/modelconfig/validator/DynamicConfigValidatorTest.java b/elide-model-config/src/test/java/com/yahoo/elide/modelconfig/validator/DynamicConfigValidatorTest.java
index db0ed49802..875838c9e5 100644
--- a/elide-model-config/src/test/java/com/yahoo/elide/modelconfig/validator/DynamicConfigValidatorTest.java
+++ b/elide-model-config/src/test/java/com/yahoo/elide/modelconfig/validator/DynamicConfigValidatorTest.java
@@ -235,11 +235,11 @@ public void testBadSecurityRoleConfig() throws Exception {
assertEquals(2, exitStatus);
});
- String expectedError = "Schema validation failed for: models/security.hjson\n"
- + "[ERROR]\n"
- + "Instance[/roles/0] failed to validate against schema[/properties/roles/items]. Role [admin,] is not allowed. Role must start with an alphabetic character and can include alaphabets, numbers, spaces and '.' only.\n"
- + "[ERROR]\n"
- + "Instance[/roles/1] failed to validate against schema[/properties/roles/items]. Role [guest,] is not allowed. Role must start with an alphabetic character and can include alaphabets, numbers, spaces and '.' only.\n";
+ String expectedError = """
+ Schema validation failed for: models/security.hjson
+ /roles/0: does not match the elideRole pattern must start with an alphabetic character and can include alphabets, numbers, spaces and '.' only.
+ /roles/1: does not match the elideRole pattern must start with an alphabetic character and can include alphabets, numbers, spaces and '.' only.
+ """;
assertEquals(expectedError.replaceAll("\n", System.lineSeparator()), error);
}
@@ -262,9 +262,10 @@ public void testNamespaceBadDefaultName() throws Exception {
assertEquals(2, exitStatus);
});
- String expected = "Schema validation failed for: models/namespaces/test_namespace.hjson\n"
- + "[ERROR]\n"
- + "Instance[/namespaces/0/name] failed to validate against schema[/properties/namespaces/items/properties/name]. Name [Default] clashes with the 'default' namespace. Either change the case or pick a different namespace name.\n";
+ String expected = """
+ Schema validation failed for: models/namespaces/test_namespace.hjson
+ /namespaces/0/name: does not match the elideNamespaceName pattern must start with an alphabetic character and can include alphabets, numbers and '_' only and must not clash with the 'default' namespace.
+ """;
assertEquals(expected.replaceAll("\n", System.lineSeparator()), error);
}
@@ -297,32 +298,28 @@ public void testBadTableConfigJoinType() throws Exception {
DynamicConfigValidator.main(new String[] { "--configDir", "src/test/resources/validator/bad_table_join_type"}));
assertEquals(2, exitStatus);
});
- String expected = "Schema validation failed for: models/tables/table1.hjson\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/joins/0/kind] failed to validate against schema[/definitions/join/properties/kind]. Join kind [toAll] is not allowed. Supported value is one of [ToOne, ToMany].\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/joins/1/type] failed to validate against schema[/definitions/join/properties/type]. Join type [full outer] is not allowed. Supported value is one of [left, inner, full, cross].\n";
+ String expected = """
+ Schema validation failed for: models/tables/table1.hjson
+ /tables/0/joins/0/kind: does not match the elideJoinKind pattern must be one of [ToOne, ToMany].
+ /tables/0/joins/1/type: does not match the elideJoinType pattern must be one of [left, inner, full, cross].
+ """;
assertEquals(expected.replaceAll("\n", System.lineSeparator()), error);
}
@Test
public void testBadDimName() throws Exception {
- String expectedMessage = "Schema validation failed for: models/tables/table1.hjson\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/dimensions/0] failed to validate against schema[/properties/tables/items/properties/dimensions/items]. instance failed to match exactly one schema (matched 0 out of 2)\n"
- + " Instance[/tables/0/dimensions/0] failed to validate against schema[/definitions/dimension]. instance failed to match all required schemas (matched only 1 out of 2)\n"
- + " Instance[/tables/0/dimensions/0/name] failed to validate against schema[/definitions/dimensionRef/properties/name]. Field name [id] is not allowed. Field name cannot be one of [id, sql]\n"
- + " Instance[/tables/0/dimensions/0] failed to validate against schema[/definitions/timeDimension]. instance failed to match all required schemas (matched only 0 out of 2)\n"
- + " Instance[/tables/0/dimensions/0/name] failed to validate against schema[/definitions/dimensionRef/properties/name]. Field name [id] is not allowed. Field name cannot be one of [id, sql]\n"
- + " Instance[/tables/0/dimensions/0/type] failed to validate against schema[/definitions/timeDimension/allOf/1/properties/type]. Field type [Text] is not allowed. Field type must be [Time] for any time dimension.\n"
- + "[ERROR]\n"
- + "Instance[/tables/0/dimensions/1] failed to validate against schema[/properties/tables/items/properties/dimensions/items]. instance failed to match exactly one schema (matched 0 out of 2)\n"
- + " Instance[/tables/0/dimensions/1] failed to validate against schema[/definitions/dimension]. instance failed to match all required schemas (matched only 1 out of 2)\n"
- + " Instance[/tables/0/dimensions/1/name] failed to validate against schema[/definitions/dimensionRef/properties/name]. Field name [_region] is not allowed. Field name must start with lower case alphabet and can include alaphabets, numbers and '_' only.\n"
- + " Instance[/tables/0/dimensions/1] failed to validate against schema[/definitions/timeDimension]. instance failed to match all required schemas (matched only 0 out of 2)\n"
- + " Instance[/tables/0/dimensions/1/name] failed to validate against schema[/definitions/dimensionRef/properties/name]. Field name [_region] is not allowed. Field name must start with lower case alphabet and can include alaphabets, numbers and '_' only.\n"
- + " Instance[/tables/0/dimensions/1/type] failed to validate against schema[/definitions/timeDimension/allOf/1/properties/type]. Field type [Text] is not allowed. Field type must be [Time] for any time dimension.\n";
+ String expectedMessage = """
+ Schema validation failed for: models/tables/table1.hjson
+ /tables/0/dimensions/0: must be valid to one and only one schema, but 0 are valid
+ /tables/0/dimensions/0/name: does not match the elideFieldName pattern must start with lower case alphabet and can include alphabets, numbers and '_' only and cannot be one of [id, sql]
+ /tables/0/dimensions/0/name: does not match the elideFieldName pattern must start with lower case alphabet and can include alphabets, numbers and '_' only and cannot be one of [id, sql]
+ /tables/0/dimensions/0/type: does not match the elideTimeFieldType pattern must be [Time] for any time dimension.
+ /tables/0/dimensions/1: must be valid to one and only one schema, but 0 are valid
+ /tables/0/dimensions/1/name: does not match the elideFieldName pattern must start with lower case alphabet and can include alphabets, numbers and '_' only and cannot be one of [id, sql]
+ /tables/0/dimensions/1/name: does not match the elideFieldName pattern must start with lower case alphabet and can include alphabets, numbers and '_' only and cannot be one of [id, sql]
+ /tables/0/dimensions/1/type: does not match the elideTimeFieldType pattern must be [Time] for any time dimension.
+ """;
String error = tapSystemErr(() -> {
int exitStatus = catchSystemExit(() ->
diff --git a/elide-model-config/src/test/resources/validator/invalid_schema/table_schema_with_arguments.hjson b/elide-model-config/src/test/resources/validator/invalid_schema/table_schema_with_arguments.hjson
new file mode 100644
index 0000000000..f92c57507e
--- /dev/null
+++ b/elide-model-config/src/test/resources/validator/invalid_schema/table_schema_with_arguments.hjson
@@ -0,0 +1,29 @@
+{
+ // unsupported: additional property 'name'
+ name: Geography
+ tables:
+ [
+ {
+ name: Country
+ table: country
+ // unsupported: cardinality value
+ cardinality: Extra Large
+ filterTemplate: countryIsoCode={{code}};startTime=={{start}}
+ arguments:
+ [
+ {
+ // both tableSource and values are not supported. Choose One or None
+ name: aggregation
+ description: Aggregation
+ type : TEXT
+ values: ['SUM', 'MIN', 'MAX']
+ tableSource: {
+ table: abc
+ column: def
+ }
+ default: SUM
+ }
+ ]
+ }
+ ]
+}
diff --git a/pom.xml b/pom.xml
index 92e5e7b0fb..e57ad6f7c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -122,7 +122,7 @@
5.1.3
1.5.1
2.9.0
- 2.2.14
+ 1.4.2
5.10.2
1.5.6
1.18.32
@@ -457,7 +457,7 @@
${json-path.version}
- com.github.java-json-tools
+ com.networknt
json-schema-validator
${json-schema-validator.version}