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

org.apache.drill.exec.server.options.PersistedOptionValue Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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.apache.drill.exec.server.options;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.apache.drill.common.util.JacksonUtils;
import org.apache.drill.shaded.guava.com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * 

* This represents a persisted {@link OptionValue}. Decoupling the {@link OptionValue} from what * is persisted will prevent us from accidentally breaking backward compatibility in the future * when the {@link OptionValue} changes. Additionally when we do change the format of stored options we * will not have to change much code since this is already designed with backward compatibility in mind. * This class is also forward compatible with the Drill Option storage format in Drill 1.11 and earlier. *

* *

* Contract: * Only {@link PersistedOptionValue}s created from an {@link OptionValue} should be persisted. * And {@link OptionValue}s should only be created from {@link PersistedOptionValue}s that are * retrieved from a store. *

*/ // Custom Deserializer required for backward compatibility DRILL-5809 @JsonInclude(JsonInclude.Include.NON_NULL) @JsonDeserialize(using = PersistedOptionValue.Deserializer.class) public class PersistedOptionValue { /** * This is present for forward compatability with Drill 1.11 and earlier */ public static final String SYSTEM_TYPE = "SYSTEM"; /** * This constant cannot be changed for backward and forward compatibility reasons. */ public static final String JSON_TYPE = "type"; /** * This constant cannot be changed for backward and forward compatibility reasons. */ public static final String JSON_KIND = "kind"; /** * This constant cannot be changed for backward and forward compatibility reasons. */ public static final String JSON_NAME = "name"; /** * This constant cannot be changed for backward and forward compatibility reasons. */ public static final String JSON_NUM_VAL = "num_val"; /** * This constant cannot be changed for backward and forward compatibility reasons. */ public static final String JSON_STRING_VAL = "string_val"; /** * This constant cannot be changed for backward and forward compatibility reasons. */ public static final String JSON_BOOL_VAL = "bool_val"; /** * This constant cannot be changed for backward and forward compatibility reasons. */ public static final String JSON_FLOAT_VAL = "float_val"; /** * This constant cannot be changed for backward and forward compatibility reasons. */ public static final String JSON_INTEGER_VAL = "int_val"; private String value; private OptionValue.Kind kind; private String name; private Long num_val; private String string_val; private Boolean bool_val; private Double float_val; public PersistedOptionValue(String value) { this.value = Preconditions.checkNotNull(value); } public PersistedOptionValue(OptionValue.Kind kind, String name, Long num_val, String string_val, Boolean bool_val, Double float_val) { this.kind = kind; this.name = name; this.num_val = num_val; this.string_val = string_val; this.bool_val = bool_val; this.float_val = float_val; switch (kind) { case BOOLEAN: Preconditions.checkNotNull(bool_val); value = bool_val.toString(); break; case STRING: Preconditions.checkNotNull(string_val); value = string_val; break; case DOUBLE: Preconditions.checkNotNull(float_val); value = float_val.toString(); break; case LONG: Preconditions.checkNotNull(num_val); value = num_val.toString(); break; default: throw new UnsupportedOperationException(String.format("Unsupported type %s", kind)); } } /** * This is ignored for forward compatibility. */ @JsonIgnore public String getValue() { return value; } /** * This is present for forward compatibility. */ @JsonProperty(JSON_TYPE) public String getType() { return SYSTEM_TYPE; } /** * This is present for forward compatibility. */ @JsonProperty(JSON_KIND) public OptionValue.Kind getKind() { return kind; } /** * This is present for forward compatibility. */ @JsonProperty(JSON_NAME) public String getName() { return name; } /** * This is present for forward compatibility. */ @JsonProperty(JSON_NUM_VAL) public Long getNumVal() { return num_val; } /** * This is present for forward compatibility. */ @JsonProperty(JSON_STRING_VAL) public String getStringVal() { return string_val; } /** * This is present for forward compatibility. */ @JsonProperty(JSON_BOOL_VAL) public Boolean getBoolVal() { return bool_val; } /** * This is present for forward compatibility. */ @JsonProperty(JSON_FLOAT_VAL) public Double getFloatVal() { return float_val; } public OptionValue toOptionValue(final OptionDefinition optionDefinition, final OptionValue.OptionScope optionScope) { Preconditions.checkNotNull(value, "The value must be defined in order for this to be converted to an " + "option value"); final OptionValidator validator = optionDefinition.getValidator(); final OptionValue.Kind kind = validator.getKind(); final String name = validator.getOptionName(); final OptionValue.AccessibleScopes accessibleScopes = optionDefinition.getMetaData().getAccessibleScopes(); return OptionValue.create(kind, accessibleScopes, name, value, optionScope); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } PersistedOptionValue that = (PersistedOptionValue) o; if (value != null ? !value.equals(that.value) : that.value != null) { return false; } if (kind != that.kind) { return false; } if (name != null ? !name.equals(that.name) : that.name != null) { return false; } if (num_val != null ? !num_val.equals(that.num_val) : that.num_val != null) { return false; } if (string_val != null ? !string_val.equals(that.string_val) : that.string_val != null) { return false; } if (bool_val != null ? !bool_val.equals(that.bool_val) : that.bool_val != null) { return false; } return float_val != null ? float_val.equals(that.float_val) : that.float_val == null; } @Override public int hashCode() { int result = value != null ? value.hashCode() : 0; result = 31 * result + (kind != null ? kind.hashCode() : 0); result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (num_val != null ? num_val.hashCode() : 0); result = 31 * result + (string_val != null ? string_val.hashCode() : 0); result = 31 * result + (bool_val != null ? bool_val.hashCode() : 0); result = 31 * result + (float_val != null ? float_val.hashCode() : 0); return result; } @Override public String toString() { return "PersistedOptionValue{" + "value='" + value + '\'' + ", kind=" + kind + ", name='" + name + '\'' + ", num_val=" + num_val + ", string_val='" + string_val + '\'' + ", bool_val=" + bool_val + ", float_val=" + float_val + '}'; } /** * This deserializer only fetches the relevant information we care about from a store, which is the * value of an option. This deserializer is essentially future proof since it only requires a value * to be stored for an option. */ @SuppressWarnings("serial") public static class Deserializer extends StdDeserializer { private static final Logger logger = LoggerFactory.getLogger(Deserializer.class); private Deserializer() { super(PersistedOptionValue.class); } protected Deserializer(JavaType valueType) { super(valueType); } protected Deserializer(StdDeserializer src) { super(src); } @Override public PersistedOptionValue deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { ObjectCodec oc = p.getCodec(); JsonNode node = oc.readTree(p); String value = null; if (node.has(OptionValue.JSON_NUM_VAL)) { value = node.get(OptionValue.JSON_NUM_VAL).asText(); } if (node.has(OptionValue.JSON_STRING_VAL)) { value = node.get(OptionValue.JSON_STRING_VAL).asText(); } if (node.has(OptionValue.JSON_BOOL_VAL)) { value = node.get(OptionValue.JSON_BOOL_VAL).asText(); } if (node.has(OptionValue.JSON_FLOAT_VAL)) { value = node.get(OptionValue.JSON_FLOAT_VAL).asText(); } if (node.has(OptionValue.JSON_INTEGER_VAL)) { value = node.get(OptionValue.JSON_INTEGER_VAL).asText(); } if (value == null) { logger.error("Invalid json stored {}.", JacksonUtils.createObjectMapper().writeValueAsString(node)); } return new PersistedOptionValue(value); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy