summaryrefslogtreecommitdiffstats
path: root/config-model/src/main/java/com/yahoo/vespa/model/container/xml/embedder/EmbedderOption.java
blob: 206745887d17aec5d6e9203e368955838f8dc948 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package com.yahoo.vespa.model.container.xml.embedder;

import com.yahoo.config.model.deploy.DeployState;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;

import java.util.HashMap;
import java.util.Map;


/**
 * Holds options for embedder configuration. This includes code for handling special
 * options such as model specifiers.
 *
 * @author lesters
 */
public class EmbedderOption {

    public static final OptionTransformer defaultOptionTransformer = new OptionTransformer();

    private final String name;
    private final boolean required;
    private final String value;
    private final Map<String, String> attributes;
    private final OptionTransformer optionTransformer;
    private final boolean set;

    private EmbedderOption(Builder builder) {
        this.name = builder.name;
        this.required = builder.required;
        this.value = builder.value;
        this.attributes = builder.attributes;
        this.optionTransformer = builder.optionTransformer;
        this.set = builder.set;
    }

    public void toElement(DeployState deployState, Element parent) {
        optionTransformer.transform(deployState, parent, this);
    }

    public String name() {
        return name;
    }

    public String value() {
        return value;
    }

    public boolean required() {
        return required;
    }

    public OptionTransformer optionTransformer() {
        return optionTransformer;
    }

    public boolean isSet() {
        return set;
    }

    /**
     * Basic option transformer. No special handling of options.
     */
    public static class OptionTransformer {
        public void transform(DeployState deployState, Element parent, EmbedderOption option) {
            createElement(parent, option.name(), option.value());
        }

        public static Element createElement(Element parent, String name, String value) {
            Element element = parent.getOwnerDocument().createElement(name);
            element.setTextContent(value);
            parent.appendChild(element);
            return element;
        }
    }

    /**
     * Transforms model options of type &lt;x id="..." url="..." path="..." /&gt; to the
     * required fields in the config definition.
     */
    public static class ModelOptionTransformer extends OptionTransformer {

        private final String pathField;
        private final String urlField;

        public ModelOptionTransformer(String pathField, String urlField) {
            super();
            this.pathField = pathField;
            this.urlField = urlField;
        }

        @Override
        public void transform(DeployState deployState, Element parent, EmbedderOption option) {
            String id = option.attributes.get("id");
            String url = option.attributes.get("url");
            String path = option.attributes.get("path");

            // Always use path if it is set
            if (path != null && path.length() > 0) {
                createElement(parent, pathField, path);
                createElement(parent, urlField, "");
                return;
            }

            // Only use the id if we're on cloud
            if (deployState.isHosted() && id != null && id.length() > 0) {
                createElement(parent, urlField, EmbedderConfig.modelIdToUrl(id));
                createElement(parent, pathField, createDummyPath(deployState));
                return;
            }

            // Otherwise, use url
            if (url != null && url.length() > 0) {
                createElement(parent, urlField, url);
                createElement(parent, pathField, createDummyPath(deployState));
                return;
            }

            if ( ! deployState.isHosted() && id != null && id.length() > 0) {
                throw new IllegalArgumentException("Model option 'id' is not valid here");
            }
            throw new IllegalArgumentException("Model option requires either a 'path' or a 'url' attribute");
        }

        private String createDummyPath(DeployState deployState) {
            // For now, until we have optional config parameters, return services.xml as it is guaranteed to exist
            return "services.xml";
        }

    }

    public static class Builder {
        private String name = "";
        private boolean required = false;
        private String value = "";
        private Map<String, String> attributes = Map.of();
        private OptionTransformer optionTransformer = defaultOptionTransformer;
        private boolean set = false;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder required(boolean required) {
            this.required = required;
            return this;
        }

        public Builder value(String value) {
            this.value = value;
            this.set = true;
            return this;
        }

        public Builder attributes(Map<String, String> attributes) {
            this.attributes = attributes;
            return this;
        }

        public Builder attributes(Element element) {
            NamedNodeMap map = element.getAttributes();
            if (map.getLength() > 0) {
                this.attributes = new HashMap<>(map.getLength());
                for (int i = 0; i < map.getLength(); ++i) {
                    String attr = map.item(i).getNodeName();
                    attributes.put(attr, element.getAttribute(attr));
                }
            }
            return this;
        }

        public Builder optionTransformer(OptionTransformer optionTransformer) {
            this.optionTransformer = optionTransformer;
            return this;
        }

        public EmbedderOption build() {
            return new EmbedderOption(this);
        }

    }

}