From adcb1d4d55e71d78c662f798b033d3abea0d4b9e Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Wed, 31 Aug 2022 22:50:14 +0200 Subject: Add 'model' config type --- .../src/main/java/com/yahoo/config/FileNode.java | 4 - .../main/java/com/yahoo/config/FileReference.java | 3 + .../main/java/com/yahoo/config/LeafNodeMaps.java | 8 +- .../main/java/com/yahoo/config/LeafNodeVector.java | 7 +- .../src/main/java/com/yahoo/config/ModelNode.java | 64 ++++++++++++ .../main/java/com/yahoo/config/ModelReference.java | 109 +++++++++++++++++++++ .../src/main/java/com/yahoo/config/PathNode.java | 1 - .../main/java/com/yahoo/config/UrlReference.java | 1 + 8 files changed, 190 insertions(+), 7 deletions(-) create mode 100644 config-lib/src/main/java/com/yahoo/config/ModelNode.java create mode 100644 config-lib/src/main/java/com/yahoo/config/ModelReference.java (limited to 'config-lib/src/main') diff --git a/config-lib/src/main/java/com/yahoo/config/FileNode.java b/config-lib/src/main/java/com/yahoo/config/FileNode.java index e6a4af6f439..a7c1ebb1488 100644 --- a/config-lib/src/main/java/com/yahoo/config/FileNode.java +++ b/config-lib/src/main/java/com/yahoo/config/FileNode.java @@ -1,8 +1,6 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config; -import java.nio.file.Path; - /** * Represents a 'file' in a {@link ConfigInstance}, usually a filename. * @@ -16,8 +14,6 @@ public class FileNode extends LeafNode { public FileNode(String stringVal) { super(true); this.value = new FileReference(ReferenceNode.stripQuotes(stringVal)); - if (Path.of(value.value()).normalize().startsWith("..")) - throw new IllegalArgumentException("path may not start with '..', but got: " + value.value()); } public FileReference value() { diff --git a/config-lib/src/main/java/com/yahoo/config/FileReference.java b/config-lib/src/main/java/com/yahoo/config/FileReference.java index 686721e91ae..8b8434c8cc4 100755 --- a/config-lib/src/main/java/com/yahoo/config/FileReference.java +++ b/config-lib/src/main/java/com/yahoo/config/FileReference.java @@ -2,6 +2,7 @@ package com.yahoo.config; import java.io.File; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; @@ -19,6 +20,8 @@ public final class FileReference { private final String value; public FileReference(String value) { + if (Path.of(value).normalize().startsWith("..")) + throw new IllegalArgumentException("Path may not start with '..' but got '" + value + "'"); this.value = Objects.requireNonNull(value); } diff --git a/config-lib/src/main/java/com/yahoo/config/LeafNodeMaps.java b/config-lib/src/main/java/com/yahoo/config/LeafNodeMaps.java index 9435c09803f..82663fa8bfd 100644 --- a/config-lib/src/main/java/com/yahoo/config/LeafNodeMaps.java +++ b/config-lib/src/main/java/com/yahoo/config/LeafNodeMaps.java @@ -8,7 +8,6 @@ import java.util.stream.Collectors; /** * @author gjoranv - * @since 5.1.17 */ public class LeafNodeMaps { @@ -68,4 +67,11 @@ public class LeafNodeMaps { )); } + public static Map asModelNodeMap(Map modelReferenceMap) { + return Collections.unmodifiableMap( + modelReferenceMap.entrySet().stream().collect( + Collectors.toMap(Map.Entry::getKey, e -> new ModelNode(e.getValue())) + )); + } + } diff --git a/config-lib/src/main/java/com/yahoo/config/LeafNodeVector.java b/config-lib/src/main/java/com/yahoo/config/LeafNodeVector.java index 599385899e1..bdabc045e18 100644 --- a/config-lib/src/main/java/com/yahoo/config/LeafNodeVector.java +++ b/config-lib/src/main/java/com/yahoo/config/LeafNodeVector.java @@ -13,7 +13,6 @@ import java.util.List; * A vector of leaf nodes. * * @author gjoranv - * @since 5.1.4 */ public class LeafNodeVector> extends NodeVector { @@ -79,5 +78,11 @@ public class LeafNodeVector> extends NodeVecto return new LeafNodeVector<>(files, new UrlNode()); } + public static LeafNodeVector createModelNodeVector(Collection values) { + List models = new ArrayList<>(); + for (ModelReference modelReference : values) + models.add(modelReference); + return new LeafNodeVector<>(models, new ModelNode()); + } } diff --git a/config-lib/src/main/java/com/yahoo/config/ModelNode.java b/config-lib/src/main/java/com/yahoo/config/ModelNode.java new file mode 100644 index 00000000000..775c4a12e82 --- /dev/null +++ b/config-lib/src/main/java/com/yahoo/config/ModelNode.java @@ -0,0 +1,64 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.config; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Represents a 'model' in a {@link ConfigInstance}. + * + * @author bratseth + */ +public class ModelNode extends LeafNode { + + public ModelNode() { + this.value = null; + } + + public ModelNode(ModelReference modelReference) { + super(true); + this.value = modelReference; + } + + public ModelReference value() { + return value; + } + + @Override + public String getValue() { + return value.toString(); + } + + @Override + public String toString() { + return (value == null) ? "(null)" : '"' + getValue() + '"'; + } + + @Override + protected boolean doSetValue(String stringVal) { + throw new UnsupportedOperationException(); + } + + public ModelReference getModelReference() { + return value; + } + + public static List toModelReferences(List modelNodes) { + List modelReferences = new ArrayList<>(); + for (ModelNode modelNode : modelNodes) + modelReferences.add(modelNode.getModelReference()); + return modelReferences; + } + + public static Map toModelReferenceMap(Map nodeMap) { + Map referenceMap = new LinkedHashMap<>(); + for (var entry : nodeMap.entrySet()) { + referenceMap.put(entry.getKey(), entry.getValue().getModelReference()); + } + return referenceMap; + } + +} diff --git a/config-lib/src/main/java/com/yahoo/config/ModelReference.java b/config-lib/src/main/java/com/yahoo/config/ModelReference.java new file mode 100644 index 00000000000..c0b610e4df3 --- /dev/null +++ b/config-lib/src/main/java/com/yahoo/config/ModelReference.java @@ -0,0 +1,109 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.config; + +import java.io.File; +import java.util.Objects; +import java.util.Optional; + +/** + * An immutable reference to a model. + * This is a file path when read by a client but is set in a config instance either as a + * path, url or id resolved to an url during deployment. + * + * @author bratseth + */ +public class ModelReference { + + // At least one of these are set + private final Optional modelId; + private final Optional url; + private final Optional path; + + public ModelReference(Optional modelId, + Optional url, + Optional path) { + if (modelId.isEmpty() && url.isEmpty() && path.isEmpty()) + throw new IllegalArgumentException("A model reference must have either a model id, url or path"); + this.modelId = modelId; + this.url = url; + this.path = path; + } + + public Optional modelId() { return modelId; } + public Optional url() { return url; } + public Optional path() { return path; } + + public ModelReference withModelId(Optional modelId) { + return new ModelReference(modelId, url, path); + } + + public ModelReference withUrl(Optional url) { + return new ModelReference(modelId, url, path); + } + + public ModelReference withPath(Optional path) { + return new ModelReference(modelId, url, path); + } + + /** Returns the path to the file containing this model. */ + public String value() { + if (url.isPresent() && new File(url.get().value()).exists()) + return new File(url.get().value()).getAbsolutePath(); + if (path.isPresent()) + return path.get().value(); + throw new IllegalStateException("No url or path is available"); + } + + @Override + public boolean equals(Object o) { + if ( ! (o instanceof ModelReference other)) return false; + if ( ! this.modelId.equals(other.modelId)) return false; + if ( ! this.url.equals(other.url)) return false; + if ( ! this.path.equals(other.path)) return false; + return true; + } + + @Override + public int hashCode() { + return Objects.hash(modelId, url, path); + } + + /** Returns this on the format accepted by valueOf */ + @Override + public String toString() { + return modelId.orElse("") + " " + + url.map(v -> v.value()).orElse("") + " " + + path.map(v -> v.value()).orElse(""); + } + + /** Creates a model reference having a model id only. */ + public static ModelReference fromModelId(String modelId) { + return new ModelReference(Optional.of(modelId), Optional.empty(), Optional.empty()); + } + + /** Creates a model reference having a url only. */ + public static ModelReference fromUrl(String url) { + return new ModelReference(Optional.empty(), Optional.of(new UrlReference(url)), Optional.empty()); + } + + /** Creates a model reference having a path only. */ + public static ModelReference fromPath(String path) { + return new ModelReference(Optional.empty(), Optional.empty(), Optional.of(new FileReference(path))); + } + + /** + * Creates a model reference from a three-part string on the form + * modelId url path + * Each of the elements are either a value not containing space, or empty represented by "". + */ + public static ModelReference valueOf(String s) { + String[] parts = s.split(" "); + if (parts.length != 3) + throw new IllegalArgumentException("Expected a config with exactly three space-separated parts, but got '" + s + "'"); + return new ModelReference(parts[0].equals("") ? Optional.empty() : Optional.of(parts[0]), + parts[1].equals("") ? Optional.empty() : Optional.of(new UrlReference(parts[1])), + parts[2].equals("") ? Optional.empty() : Optional.of(new FileReference(parts[2]))); + + } + +} diff --git a/config-lib/src/main/java/com/yahoo/config/PathNode.java b/config-lib/src/main/java/com/yahoo/config/PathNode.java index ea4c657af8c..b757e569ffe 100644 --- a/config-lib/src/main/java/com/yahoo/config/PathNode.java +++ b/config-lib/src/main/java/com/yahoo/config/PathNode.java @@ -1,7 +1,6 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config; -import java.io.File; import java.nio.file.Path; import java.util.ArrayList; import java.util.LinkedHashMap; diff --git a/config-lib/src/main/java/com/yahoo/config/UrlReference.java b/config-lib/src/main/java/com/yahoo/config/UrlReference.java index 1adab8aaa53..d7a74165896 100755 --- a/config-lib/src/main/java/com/yahoo/config/UrlReference.java +++ b/config-lib/src/main/java/com/yahoo/config/UrlReference.java @@ -11,6 +11,7 @@ import java.util.Objects; */ public final class UrlReference { + /** Either the url or, if downloaded, the absolute path to the downloaded file. */ private final String value; public UrlReference(String value) { -- cgit v1.2.3