/* * Licensed to Crate.io Inc. ("Crate.io") under one or more contributor * license agreements. See the NOTICE file distributed with this work for * additional information regarding copyright ownership. Crate.io 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. * * To enable or use any of the enterprise features, Crate.io must have given * you permission to enable and use the Enterprise Edition of CrateDB and you * must have a valid Enterprise or Subscription Agreement with Crate.io. If * you enable or use features that are part of the Enterprise Edition, you * represent and warrant that you have a valid Enterprise or Subscription * Agreement with Crate.io. Your use of features of the Enterprise Edition * is governed by the terms and conditions of your Enterprise or Subscription * Agreement with Crate.io. */ package io.crate.operation.udf; import com.google.common.annotations.VisibleForTesting; import io.crate.types.DataType; import org.elasticsearch.cluster.AbstractDiffable; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; import java.util.*; public class UserDefinedFunctionsMetaData extends AbstractDiffable<MetaData.Custom> implements MetaData.Custom { public static final String TYPE = "user_defined_functions"; static final UserDefinedFunctionsMetaData PROTO = new UserDefinedFunctionsMetaData(); static { // register non plugin custom metadata MetaData.registerPrototype(TYPE, PROTO); } private final List<UserDefinedFunctionMetaData> functionsMetaData; private UserDefinedFunctionsMetaData() { this.functionsMetaData = new ArrayList<>(); } private UserDefinedFunctionsMetaData(List<UserDefinedFunctionMetaData> functions) { this.functionsMetaData = functions; } public static UserDefinedFunctionsMetaData newInstance(UserDefinedFunctionsMetaData instance) { return new UserDefinedFunctionsMetaData(new ArrayList<>(instance.functionsMetaData)); } @VisibleForTesting public static UserDefinedFunctionsMetaData of(UserDefinedFunctionMetaData... functions) { return new UserDefinedFunctionsMetaData(Arrays.asList(functions)); } public void add(UserDefinedFunctionMetaData function) { functionsMetaData.add(function); } public void replace(UserDefinedFunctionMetaData function) { for (int i = 0; i < functionsMetaData.size(); i++) { if (functionsMetaData.get(i).sameSignature(function.schema(), function.name(), function.argumentTypes())) { functionsMetaData.set(i, function); } } } public boolean contains(String schema, String name, List<DataType> types) { for (UserDefinedFunctionMetaData function : functionsMetaData) { if (function.sameSignature(schema, name, types)) { return true; } } return false; } public void remove(String schema, String name, List<DataType> types) { for (ListIterator<UserDefinedFunctionMetaData> iter = functionsMetaData.listIterator(); iter.hasNext(); ) { if (iter.next().sameSignature(schema, name, types)) { iter.remove(); } } } public List<UserDefinedFunctionMetaData> functionsMetaData() { return functionsMetaData; } @Override public void writeTo(StreamOutput out) throws IOException { out.writeVInt(functionsMetaData.size()); for (UserDefinedFunctionMetaData function : functionsMetaData) { function.writeTo(out); } } @Override public MetaData.Custom readFrom(StreamInput in) throws IOException { int size = in.readVInt(); List<UserDefinedFunctionMetaData> functions = new ArrayList<>(size); for (int i = 0; i < size; i++) { functions.add(UserDefinedFunctionMetaData.fromStream(in)); } return new UserDefinedFunctionsMetaData(functions); } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startArray("functions"); for (UserDefinedFunctionMetaData function : functionsMetaData) { function.toXContent(builder, params); } builder.endArray(); return builder; } @Override public String type() { return TYPE; } @Override public MetaData.Custom fromXContent(XContentParser parser) throws IOException { List<UserDefinedFunctionMetaData> functions = new ArrayList<>(); if (parser.nextToken() == XContentParser.Token.FIELD_NAME && Objects.equals(parser.currentName(), "functions")) { if ((parser.nextToken()) == XContentParser.Token.START_ARRAY) { XContentParser.Token token; while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY && token != null) { functions.add(UserDefinedFunctionMetaData.fromXContent(parser)); } } } return new UserDefinedFunctionsMetaData(functions); } @Override public EnumSet<MetaData.XContentContext> context() { return EnumSet.of(MetaData.XContentContext.GATEWAY, MetaData.XContentContext.SNAPSHOT); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UserDefinedFunctionsMetaData that = (UserDefinedFunctionsMetaData) o; return functionsMetaData.equals(that.functionsMetaData); } }