ResourceBundleReader.java
001 /*
002  * SPDX-License-Identifier: Apache-2.0
003  *
004  * Copyright 2008-2017 the original author or authors.
005  *
006  * Licensed under the Apache License, Version 2.0 (the "License");
007  * you may not use this file except in compliance with the License.
008  * You may obtain a copy of the License at
009  *
010  *     http://www.apache.org/licenses/LICENSE-2.0
011  *
012  * Unless required by applicable law or agreed to in writing, software
013  * distributed under the License is distributed on an "AS IS" BASIS,
014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015  * See the License for the specific language governing permissions and
016  * limitations under the License.
017  */
018 package griffon.util;
019 
020 import griffon.core.env.Environment;
021 import griffon.core.env.Metadata;
022 
023 import javax.annotation.Nonnull;
024 import javax.annotation.Nullable;
025 import javax.inject.Inject;
026 import java.util.Collections;
027 import java.util.LinkedHashMap;
028 import java.util.Map;
029 import java.util.ResourceBundle;
030 
031 import static griffon.util.GriffonNameUtils.isBlank;
032 import static griffon.util.GriffonNameUtils.isNotBlank;
033 import static java.util.Objects.requireNonNull;
034 
035 /**
036  @author Andres Almiray
037  @since 2.10.0
038  */
039 public class ResourceBundleReader {
040     private static final String ENVIRONMENTS_METHOD = "environments";
041 
042     private final Map<String, String> conditionValues = new LinkedHashMap<>();
043 
044     public static class Provider implements javax.inject.Provider<ResourceBundleReader> {
045         @Inject private Metadata metadata;
046         @Inject private Environment environment;
047 
048         @Override
049         public ResourceBundleReader get() {
050             ResourceBundleReader propertiesReader = new ResourceBundleReader();
051             propertiesReader.registerConditionalBlock("environments", environment.getName());
052             propertiesReader.registerConditionalBlock("projects", metadata.getApplicationName());
053             propertiesReader.registerConditionalBlock("platforms", GriffonApplicationUtils.getPlatform());
054             return propertiesReader;
055         }
056     }
057 
058     public void registerConditionalBlock(@Nullable String blockName, @Nullable String blockValue) {
059         if (isNotBlank(blockName)) {
060             if (isBlank(blockValue)) {
061                 conditionValues.remove(blockName);
062             else {
063                 conditionValues.put(blockName, blockValue);
064             }
065         }
066     }
067 
068     @Nonnull
069     public Map<String, String> getConditionalBlockValues() {
070         return Collections.unmodifiableMap(conditionValues);
071     }
072 
073     @Nonnull
074     public String getEnvironment() {
075         return conditionValues.get(ENVIRONMENTS_METHOD);
076     }
077 
078     public void setEnvironment(String environment) {
079         conditionValues.put(ENVIRONMENTS_METHOD, environment);
080     }
081 
082     @Nonnull
083     public ResourceBundle read(final @Nonnull ResourceBundle bundle) {
084         requireNonNull(bundle, "Argument 'bundle' must not be null");
085         return new AbstractMapResourceBundle() {
086             @Override
087             protected void initialize(@Nonnull Map<String, Object> entries) {
088                 entries.putAll(processBundle(bundle));
089             }
090         };
091     }
092 
093     @Nonnull
094     protected Map<String, Object> processBundle(@Nonnull ResourceBundle input) {
095         Map<String, Object> output = new LinkedHashMap<>();
096 
097         for (String key : input.keySet()) {
098             ConditionalBlockMatch match = resolveConditionalBlockMatch(key);
099             if (match != null) {
100                 if (match.key != null) {
101                     output.put(match.key, input.getObject(key));
102                 }
103             else {
104                 output.put(key, input.getObject(key));
105             }
106         }
107 
108         return output;
109     }
110 
111     @Nullable
112     private ConditionalBlockMatch resolveConditionalBlockMatch(@Nonnull String key) {
113         for (Map.Entry<String, String> e : conditionValues.entrySet()) {
114             String blockName = e.getKey();
115             if (!key.startsWith(blockName + ".")) {
116                 continue;
117             }
118 
119             String prefix = blockName + "." + e.getValue() ".";
120             if (key.startsWith(prefix)) {
121                 String subkey = key.substring(prefix.length());
122                 ConditionalBlockMatch match = resolveConditionalBlockMatch(subkey);
123                 if (match == null) {
124                     match = new ConditionalBlockMatch(subkey);
125                 }
126                 return match;
127             else {
128                 return new ConditionalBlockMatch(null);
129             }
130         }
131 
132         return null;
133     }
134 
135     private static class ConditionalBlockMatch {
136         public final String key;
137 
138         private ConditionalBlockMatch(String key) {
139             this.key = key;
140         }
141     }
142 }