blob: 6150b60dbb9234218cffb685228478be2cc66557 [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.configuration;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.apache.ignite.configuration.internal.DynamicConfiguration;
import org.apache.ignite.configuration.internal.DynamicProperty;
import org.apache.ignite.configuration.internal.Modifier;
import org.apache.ignite.configuration.internal.selector.Selector;
import org.apache.ignite.configuration.storage.ConfigurationStorage;
import org.apache.ignite.configuration.validation.ConfigurationValidationException;
import org.apache.ignite.configuration.validation.FieldValidator;
import org.apache.ignite.configuration.internal.validation.MemberKey;
/**
* Convenient wrapper for configuration root. Provides access to configuration tree, stores validators, performs actions
* on configuration such as initialized, change and view.
* @param <T> Type of configuration root.
*/
public class Configurator<T extends DynamicConfiguration<?, ?, ?>> {
/** Storage for the configuration tree. */
private final ConfigurationStorage storage;
/** Root of the configuration tree. */
private final T root;
/** Configuration property validators. */
private final Map<MemberKey, List<FieldValidator<? extends Serializable, T>>> fieldValidators = new HashMap<>();
/**
*
* @param storage
* @param rootBuilder
* @param <VIEW>
* @param <INIT>
* @param <CHANGE>
* @param <CONF>
* @return
*/
public static <VIEW, INIT, CHANGE, CONF extends DynamicConfiguration<VIEW, INIT, CHANGE>> Configurator<CONF> create(
ConfigurationStorage storage,
Function<Configurator<CONF>, CONF> rootBuilder
) {
return new Configurator<>(storage, rootBuilder, null);
}
/**
*
* @param storage
* @param rootBuilder
* @param init
* @param <VIEW>
* @param <INIT>
* @param <CHANGE>
* @param <CONF>
* @return
*/
public static <VIEW, INIT, CHANGE, CONF extends DynamicConfiguration<VIEW, INIT, CHANGE>> Configurator<CONF> create(
ConfigurationStorage storage,
Function<Configurator<CONF>, CONF> rootBuilder,
INIT init
) {
return new Configurator<>(storage, rootBuilder, init);
}
/**
* Constructor.
* @param storage Configuration storage.
* @param rootBuilder Function, that creates configuration root.
*/
private <VIEW, INIT, CHANGE, CONF extends DynamicConfiguration<VIEW, INIT, CHANGE>> Configurator(
ConfigurationStorage storage,
Function<Configurator<CONF>, CONF> rootBuilder,
INIT init
) {
this.storage = storage;
final CONF built = rootBuilder.apply((Configurator<CONF>) this);
if (init != null)
built.init(init);
root = (T) built;
}
/**
*
* @param selector
* @param <TARGET>
* @param <VIEW>
* @param <INIT>
* @param <CHANGE>
* @return
*/
public <TARGET extends Modifier<VIEW, INIT, CHANGE>, VIEW, INIT, CHANGE> VIEW getPublic(
Selector<T, TARGET, VIEW, INIT, CHANGE> selector
) {
return selector.select(root).value();
}
/**
*
* @param selector
* @param newValue
* @param <TARGET>
* @param <VIEW>
* @param <INIT>
* @param <CHANGE>
* @throws ConfigurationValidationException
*/
public <TARGET extends Modifier<VIEW, INIT, CHANGE>, VIEW, INIT, CHANGE> void set(
Selector<T, TARGET, VIEW, INIT, CHANGE> selector,
CHANGE newValue
) throws ConfigurationValidationException {
final T copy = (T) root.copy();
final TARGET select = selector.select(copy);
select.changeWithoutValidation(newValue);
copy.validate(root);
selector.select(root).changeWithoutValidation(newValue);
}
/**
*
* @param selector
* @param <TARGET>
* @param <VIEW>
* @param <INIT>
* @param <CHANGE>
* @return
*/
public <TARGET extends Modifier<VIEW, INIT, CHANGE>, VIEW, INIT, CHANGE> ConfigurationProperty<VIEW, CHANGE> getInternal(
Selector<T, TARGET, VIEW, INIT, CHANGE> selector
) {
return selector.select(root);
}
/**
*
* @param aClass
* @param key
* @param validators
* @param <PROP>
*/
public <PROP extends Serializable> void addValidations(
Class<? extends ConfigurationTree<?, ?>> aClass,
String key,
List<FieldValidator<? super PROP, ? extends ConfigurationTree<?, ?>>> validators
) {
fieldValidators.put(new MemberKey(aClass, key), (List) validators);
}
/**
* Get all validators for given member key (class + field).
* @param key Member key.
* @return Validators.
*/
public List<FieldValidator<? extends Serializable, T>> validators(MemberKey key) {
return fieldValidators.getOrDefault(key, Collections.emptyList());
}
/**
* Get configuration root.
* @return Configuration root.
*/
public T getRoot() {
return root;
}
/**
* Execute on property attached to configurator.
* @param property Property.
* @param <PROP> Type of the property.
*/
public <PROP extends Serializable> void onAttached(DynamicProperty<PROP> property) {
final String key = property.key();
property.addListener(new PropertyListener<PROP, PROP>() {
/** {@inheritDoc} */
@Override public void update(PROP newValue, ConfigurationProperty<PROP, PROP> modifier) {
storage.save(key, newValue);
}
});
storage.listen(key, property::setSilently);
}
}