001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package dev.metaschema.core.configuration; 007 008import java.util.HashMap; 009import java.util.Map; 010 011import dev.metaschema.core.util.CollectionUtil; 012import edu.umd.cs.findbugs.annotations.NonNull; 013 014/** 015 * Provides a basic configuration management implementation that allows mutable 016 * access to configuration state. 017 * 018 * @param <T> 019 * the type of managed features 020 */ 021public class DefaultConfiguration<T extends IConfigurationFeature<?>> 022 implements IMutableConfiguration<T> { 023 @NonNull 024 private Map<T, Object> featureValues; 025 026 /** 027 * Create a new configuration. 028 * 029 */ 030 public DefaultConfiguration() { 031 this.featureValues = new HashMap<>(); 032 } 033 034 /** 035 * Create a new configuration based on the provided feature value map. 036 * 037 * @param featureValues 038 * the set of enabled features 039 */ 040 public DefaultConfiguration(@NonNull Map<T, Object> featureValues) { 041 this.featureValues = new HashMap<>(featureValues); 042 } 043 044 /** 045 * Create a new configuration based on the provided configuration. 046 * 047 * @param original 048 * the original configuration 049 */ 050 public DefaultConfiguration(@NonNull DefaultConfiguration<T> original) { 051 this(original.getFeatureValues()); 052 } 053 054 @Override 055 public Map<T, Object> getFeatureValues() { 056 return CollectionUtil.unmodifiableMap(featureValues); 057 } 058 059 private void ensureBooleanValue(@NonNull T feature) { 060 Class<?> valueClass = feature.getValueClass(); 061 if (!Boolean.class.isAssignableFrom(valueClass)) { 062 throw new UnsupportedOperationException( 063 String.format("Feature value class '%s' is boolean valued.", valueClass.getName())); 064 } 065 } 066 067 @Override 068 public boolean isFeatureEnabled(@NonNull T feature) { 069 ensureBooleanValue(feature); 070 return get(feature); 071 } 072 073 @Override 074 public IMutableConfiguration<T> enableFeature(@NonNull T feature) { 075 ensureBooleanValue(feature); 076 featureValues.put(feature, true); 077 return this; 078 } 079 080 @Override 081 public IMutableConfiguration<T> disableFeature(@NonNull T feature) { 082 ensureBooleanValue(feature); 083 featureValues.put(feature, false); 084 return this; 085 } 086 087 @Override 088 public IMutableConfiguration<T> applyConfiguration(@NonNull IConfiguration<T> original) { 089 this.featureValues.putAll(original.getFeatureValues()); 090 return this; 091 } 092 093 @Override 094 public IMutableConfiguration<T> set(T feature, Object value) { 095 Class<?> featureValueClass = feature.getValueClass(); 096 Class<?> valueClass = value.getClass(); 097 if (!featureValueClass.isAssignableFrom(valueClass)) { 098 throw new UnsupportedOperationException( 099 String.format("Provided value of class '%s' is not assignment compatible with feature value class '%s'.", 100 valueClass.getName(), 101 featureValueClass.getName())); 102 } 103 featureValues.put(feature, value); 104 return this; 105 } 106}