| /* |
| * 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 { |
| // TODO: atomic change start |
| final T copy = (T) root.copy(); |
| |
| final TARGET select = selector.select(copy); |
| select.changeWithoutValidation(newValue); |
| copy.validate(root); |
| selector.select(root).changeWithoutValidation(newValue); |
| // TODO: atomic change end |
| } |
| |
| /** |
| * |
| * @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} */ |
| public void update(PROP newValue, ConfigurationProperty<PROP, PROP> modifier) { |
| storage.save(key, newValue); |
| } |
| }); |
| storage.listen(key, property::setSilently); |
| } |
| } |