blob: 763255432643b6a06a2e265e5f9e62e7e8beca62 [file] [log] [blame]
/*
* 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.ignite.internal.processors.configuration.distributed;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.util.future.GridFutureAdapter;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.lang.IgniteClosure;
import org.jetbrains.annotations.NotNull;
/**
* Distributed enum implementation for storing into meta storage.
* The implementation will serialize by its integer ordinal.
*
* @param <T> Type of enum.
*/
public class DistributedEnumProperty<T extends Enum> implements DistributedChangeableProperty<T> {
/** This property stored enumerator as order. */
private final SimpleDistributedProperty<Integer> internal;
/** Function reflects an integer, which getting from meta storage, to an enumeration value. */
private final IgniteClosure<Integer, T> fromOrdinalFunc;
/** Function converts an enumeration value to an integer for stored in meta storage. */
private final IgniteClosure<T, Integer> toOrdinalFunc;
/** Enum name-values map to parse string representation. */
private final Map<String, T> values;
/**
* Property constructor.
*
* @param name Name of property.
* @param fromOrdinalFunc Function reflects an integer to an enumiration value.
* @param toOrdinalFunc Function converts an enumeration value to an integer.
*/
public DistributedEnumProperty(
String name,
IgniteClosure<Integer, T> fromOrdinalFunc,
IgniteClosure<T, Integer> toOrdinalFunc,
Class<T> enumCls
) {
this.internal = new SimpleDistributedProperty<>(name, null);
this.fromOrdinalFunc = fromOrdinalFunc;
this.toOrdinalFunc = toOrdinalFunc;
this.values = Arrays.stream(enumCls.getEnumConstants())
.collect(Collectors.toMap(e -> e.name().toLowerCase(), e -> e));
}
/** {@inheritDoc} */
@Override public void onAttached() {
internal.onAttached();
}
/** {@inheritDoc} */
@Override public void onReadyForUpdate(@NotNull PropertyUpdateClosure updater) {
internal.onReadyForUpdate(updater);
}
/** {@inheritDoc} */
@Override public void localUpdate(Serializable newVal) {
if (newVal == null)
internal.localUpdate(null);
else if (newVal instanceof Enum)
internal.localUpdate(ordinalOrNull((T)newVal));
else if (newVal instanceof Integer)
internal.localUpdate(newVal);
}
/** {@inheritDoc} */
@Override public boolean propagate(T newVal) throws IgniteCheckedException {
return internal.propagate(ordinalOrNull(newVal));
}
/** {@inheritDoc} */
@Override public GridFutureAdapter<?> propagateAsync(T newVal) throws IgniteCheckedException {
return internal.propagateAsync(ordinalOrNull(newVal));
}
/** {@inheritDoc} */
@Override public GridFutureAdapter<?> propagateAsync(T expectedVal, T newVal) throws IgniteCheckedException {
return internal.propagateAsync(ordinalOrNull(expectedVal), ordinalOrNull(newVal));
}
/** {@inheritDoc} */
@Override public T get() {
return fromOrdinalOrNull(internal.get());
}
/** {@inheritDoc} */
@Override public T getOrDefault(T dfltVal) {
T val = get();
return val == null ? dfltVal : val;
}
/** {@inheritDoc} */
@Override public String getName() {
return internal.getName();
}
/** {@inheritDoc} */
@Override public void addListener(DistributePropertyListener<? super T> listener) {
internal.addListener(new DistributePropertyListener<Integer>() {
@Override public void onUpdate(String name, Integer oldVal, Integer newVal) {
listener.onUpdate(name, fromOrdinalOrNull(oldVal), fromOrdinalOrNull(newVal));
}
});
}
/**
* Determines ordinal by enum value, or returns null if enum value is {@code null}.
*
* @param val Enum value.
* @return Ordinal or {@code null}.
*/
private Integer ordinalOrNull(T val) {
return val == null ? null : toOrdinalFunc.apply(val);
}
/**
* Returns enum value or {@code null} if ordinal is {@code null} or less zero.
*
* @param ord Ordinal or {@code null}.
* @return Enum value or {@code null}.
*/
private T fromOrdinalOrNull(Integer ord) {
return ord != null && ord >= 0 ? fromOrdinalFunc.apply(ord) : null;
}
/** {@inheritDoc} */
@Override public T parse(String str) {
T t = values.get(str.toLowerCase());
if (t == null) {
throw new IllegalArgumentException("Unknown value for enum property " +
"[value=" + str + ", name=" + internal.getName());
}
return t;
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(DistributedEnumProperty.class, this);
}
}