All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.script.ScriptLanguagesInfo Maven / Gradle / Ivy

There is a newer version: 8.13.2
Show newest version
/*
 * Licensed to Elasticsearch under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.elasticsearch.script;

import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;

/**
 * The allowable types, languages and their corresponding contexts.  When serialized there is a top level types_allowed list,
 * meant to reflect the setting script.allowed_types with the allowed types (eg inline, stored).
 *
 * The top-level language_contexts list of objects have the language (eg. painless,
 * mustache) and a list of contexts available for the language.  It is the responsibility of the caller to ensure
 * these contexts are filtered by the script.allowed_contexts setting.
 *
 * The json serialization of the object has the form:
 * 
 *     {
 *   "types_allowed": [
 *     "inline",
 *     "stored"
 *   ],
 *   "language_contexts": [
 *     {
 *       "language": "expression",
 *       "contexts": [
 *         "aggregation_selector",
 *         "aggs"
 *         ...
 *       ]
 *     },
 *     {
 *       "language": "painless",
 *       "contexts": [
 *         "aggregation_selector",
 *         "aggs",
 *         "aggs_combine",
 *         ...
 *       ]
 *     }
 * ...
 *   ]
 * }
 * 
 */
public class ScriptLanguagesInfo implements ToXContentObject, Writeable {
    private static final ParseField TYPES_ALLOWED = new ParseField("types_allowed");
    private static final ParseField LANGUAGE_CONTEXTS = new ParseField("language_contexts");
    private static final ParseField LANGUAGE = new ParseField("language");
    private static final ParseField CONTEXTS = new ParseField("contexts");

    public final Set typesAllowed;
    public final Map> languageContexts;

    public ScriptLanguagesInfo(Set typesAllowed, Map> languageContexts) {
        this.typesAllowed = typesAllowed != null ? Collections.unmodifiableSet(typesAllowed): Collections.emptySet();
        this.languageContexts = languageContexts != null ? Collections.unmodifiableMap(languageContexts): Collections.emptyMap();
    }

    public ScriptLanguagesInfo(StreamInput in) throws IOException {
        typesAllowed = in.readSet(StreamInput::readString);
        languageContexts = in.readMap(StreamInput::readString, sin -> sin.readSet(StreamInput::readString));
    }

    @SuppressWarnings("unchecked")
    public static final ConstructingObjectParser PARSER =
        new ConstructingObjectParser<>("script_languages_info", true,
            (a) -> new ScriptLanguagesInfo(
                new HashSet<>((List)a[0]),
                ((List>>)a[1]).stream().collect(Collectors.toMap(Tuple::v1, Tuple::v2))
            )
        );

    @SuppressWarnings("unchecked")
    private static final ConstructingObjectParser>,Void> LANGUAGE_CONTEXT_PARSER =
        new ConstructingObjectParser<>("language_contexts", true,
            (m, name) -> new Tuple<>((String)m[0], Collections.unmodifiableSet(new HashSet<>((List)m[1])))
        );

    static {
        PARSER.declareStringArray(constructorArg(), TYPES_ALLOWED);
        PARSER.declareObjectArray(constructorArg(), LANGUAGE_CONTEXT_PARSER, LANGUAGE_CONTEXTS);
        LANGUAGE_CONTEXT_PARSER.declareString(constructorArg(), LANGUAGE);
        LANGUAGE_CONTEXT_PARSER.declareStringArray(constructorArg(), CONTEXTS);
    }

    public static ScriptLanguagesInfo fromXContent(XContentParser parser) throws IOException {
        return PARSER.parse(parser, null);
    }

    @Override
    public void writeTo(StreamOutput out) throws IOException {
        out.writeStringCollection(typesAllowed);
        out.writeMap(languageContexts, StreamOutput::writeString, StreamOutput::writeStringCollection);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        ScriptLanguagesInfo that = (ScriptLanguagesInfo) o;
        return Objects.equals(typesAllowed, that.typesAllowed) &&
            Objects.equals(languageContexts, that.languageContexts);
    }

    @Override
    public int hashCode() {
        return Objects.hash(typesAllowed, languageContexts);
    }

    @Override
    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
        builder.startObject().startArray(TYPES_ALLOWED.getPreferredName());
        for (String type: typesAllowed.stream().sorted().collect(Collectors.toList())) {
            builder.value(type);
        }

        builder.endArray().startArray(LANGUAGE_CONTEXTS.getPreferredName());
        List>> languagesByName = languageContexts.entrySet().stream().sorted(
            Map.Entry.comparingByKey()
        ).collect(Collectors.toList());

        for (Map.Entry> languageContext: languagesByName) {
            builder.startObject().field(LANGUAGE.getPreferredName(), languageContext.getKey()).startArray(CONTEXTS.getPreferredName());
            for (String context: languageContext.getValue().stream().sorted().collect(Collectors.toList())) {
                builder.value(context);
            }
            builder.endArray().endObject();
        }

        return builder.endArray().endObject();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy