| 
001 /*002  * Copyright 2008-2015 the original author or authors.
 003  *
 004  * Licensed under the Apache License, Version 2.0 (the "License");
 005  * you may not use this file except in compliance with the License.
 006  * You may obtain a copy of the License at
 007  *
 008  *     http://www.apache.org/licenses/LICENSE-2.0
 009  *
 010  * Unless required by applicable law or agreed to in writing, software
 011  * distributed under the License is distributed on an "AS IS" BASIS,
 012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 013  * See the License for the specific language governing permissions and
 014  * limitations under the License.
 015  */
 016 package org.codehaus.griffon.runtime.core;
 017
 018 import griffon.core.Configuration;
 019 import griffon.core.MutableConfiguration;
 020 import griffon.util.AbstractMapResourceBundle;
 021 import griffon.util.CompositeResourceBundle;
 022 import griffon.util.ConfigUtils;
 023
 024 import javax.annotation.Nonnull;
 025 import javax.annotation.Nullable;
 026 import java.util.LinkedHashMap;
 027 import java.util.LinkedHashSet;
 028 import java.util.Map;
 029 import java.util.MissingResourceException;
 030 import java.util.ResourceBundle;
 031 import java.util.Set;
 032
 033 import static griffon.util.ConfigUtils.getConfigValue;
 034 import static griffon.util.GriffonNameUtils.requireNonBlank;
 035 import static java.util.Arrays.asList;
 036 import static java.util.Collections.unmodifiableMap;
 037 import static java.util.Objects.requireNonNull;
 038
 039 /**
 040  * @author Andres Almiray
 041  * @since 2.2.0
 042  */
 043 public class DelegatingMutableConfiguration extends ConfigurationDecorator implements MutableConfiguration {
 044     private static final String ERROR_KEY_BLANK = "Argument 'key' must not be blank";
 045     private static final String ERROR_VALUE_NULL = "Argument 'value' must not be null";
 046
 047     private final Map<String, Object> mutableKeyValues = new LinkedHashMap<>();
 048     private final Set<String> removedKeys = new LinkedHashSet<>();
 049
 050     public DelegatingMutableConfiguration(@Nonnull Configuration delegate) {
 051         super(delegate);
 052     }
 053
 054     @Override
 055     public void set(@Nonnull String key, @Nonnull Object value) {
 056         requireNonBlank(key, ERROR_KEY_BLANK);
 057         requireNonNull(value, ERROR_VALUE_NULL);
 058         mutableKeyValues.put(key, value);
 059     }
 060
 061     @Nullable
 062     @Override
 063     public Object remove(@Nonnull String key) {
 064         requireNonBlank(key, ERROR_KEY_BLANK);
 065         if (mutableKeyValues.containsKey(key)) {
 066             return mutableKeyValues.remove(key);
 067         } else if (delegate.containsKey(key)) {
 068             removedKeys.add(key);
 069             return delegate.get(key);
 070         }
 071         return null;
 072     }
 073
 074     @Nonnull
 075     @Override
 076     public Map<String, Object> asFlatMap() {
 077         Map<String, Object> flatMap = new LinkedHashMap<>(delegate.asFlatMap());
 078         flatMap.putAll(mutableKeyValues);
 079         for (String removedKey : removedKeys) {
 080             flatMap.remove(removedKey);
 081         }
 082         return unmodifiableMap(flatMap);
 083     }
 084
 085     @Nonnull
 086     @Override
 087     public ResourceBundle asResourceBundle() {
 088         return new CompositeResourceBundle(asList(new PrivateMapResourceBundle(asFlatMap()), delegate.asResourceBundle()));
 089     }
 090
 091     @Nullable
 092     @Override
 093     public Object get(@Nonnull String key) {
 094         requireNonBlank(key, ERROR_KEY_BLANK);
 095         try {
 096             return getConfigValue(mutableKeyValues, key);
 097         } catch (MissingResourceException mre) {
 098             if (removedKeys.contains(key)) {
 099                 return null;
 100             }
 101             return super.get(key);
 102         }
 103     }
 104
 105     @Override
 106     public boolean containsKey(@Nonnull String key) {
 107         requireNonBlank(key, ERROR_KEY_BLANK);
 108         return ConfigUtils.containsKey(mutableKeyValues, key) || (!removedKeys.contains(key) && delegate.containsKey(key));
 109     }
 110
 111     private static class PrivateMapResourceBundle extends AbstractMapResourceBundle {
 112         private final Map<String, Object> map = new LinkedHashMap<>();
 113
 114         private PrivateMapResourceBundle(Map<String, Object> map) {
 115             this.map.putAll(map);
 116             initialize(entries);
 117             initializeKeys();
 118         }
 119
 120         @Override
 121         protected void initialize(@Nonnull Map<String, Object> entries) {
 122             if (map != null && entries != null) {
 123                 entries.putAll(map);
 124             }
 125         }
 126     }
 127 }
 |