ResourceBundleReader.java
001 /*
002  * Copyright 2008-2017 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 griffon.util;
017 
018 import griffon.core.env.Environment;
019 import griffon.core.env.Metadata;
020 
021 import javax.annotation.Nonnull;
022 import javax.annotation.Nullable;
023 import javax.inject.Inject;
024 import java.util.Collections;
025 import java.util.LinkedHashMap;
026 import java.util.Map;
027 import java.util.ResourceBundle;
028 
029 import static griffon.util.GriffonNameUtils.isBlank;
030 import static java.util.Objects.requireNonNull;
031 
032 /**
033  @author Andres Almiray
034  @since 2.10.0
035  */
036 public class ResourceBundleReader {
037     private static final String ENVIRONMENTS_METHOD = "environments";
038 
039     private final Map<String, String> conditionValues = new LinkedHashMap<>();
040 
041     public static class Provider implements javax.inject.Provider<ResourceBundleReader> {
042         @Inject private Metadata metadata;
043         @Inject private Environment environment;
044 
045         @Override
046         public ResourceBundleReader get() {
047             ResourceBundleReader propertiesReader = new ResourceBundleReader();
048             propertiesReader.registerConditionalBlock("environments", environment.getName());
049             propertiesReader.registerConditionalBlock("projects", metadata.getApplicationName());
050             propertiesReader.registerConditionalBlock("platforms", GriffonApplicationUtils.getPlatform());
051             return propertiesReader;
052         }
053     }
054 
055     public void registerConditionalBlock(@Nullable String blockName, @Nullable String blockValue) {
056         if (!isBlank(blockName)) {
057             if (isBlank(blockValue)) {
058                 conditionValues.remove(blockName);
059             else {
060                 conditionValues.put(blockName, blockValue);
061             }
062         }
063     }
064 
065     @Nonnull
066     public Map<String, String> getConditionalBlockValues() {
067         return Collections.unmodifiableMap(conditionValues);
068     }
069 
070     @Nonnull
071     public String getEnvironment() {
072         return conditionValues.get(ENVIRONMENTS_METHOD);
073     }
074 
075     public void setEnvironment(String environment) {
076         conditionValues.put(ENVIRONMENTS_METHOD, environment);
077     }
078 
079     @Nonnull
080     public ResourceBundle read(final @Nonnull ResourceBundle bundle) {
081         requireNonNull(bundle, "Argument 'bundle' must not be null");
082         return new AbstractMapResourceBundle() {
083             @Override
084             protected void initialize(@Nonnull Map<String, Object> entries) {
085                 entries.putAll(processBundle(bundle));
086             }
087         };
088     }
089 
090     @Nonnull
091     protected Map<String, Object> processBundle(@Nonnull ResourceBundle input) {
092         Map<String, Object> output = new LinkedHashMap<>();
093 
094         for (String key : input.keySet()) {
095             ConditionalBlockMatch match = resolveConditionalBlockMatch(key);
096             if (match != null) {
097                 if (match.key != null) {
098                     output.put(match.key, input.getObject(key));
099                 }
100             else {
101                 output.put(key, input.getObject(key));
102             }
103         }
104 
105         return output;
106     }
107 
108     @Nullable
109     private ConditionalBlockMatch resolveConditionalBlockMatch(@Nonnull String key) {
110         for (Map.Entry<String, String> e : conditionValues.entrySet()) {
111             String blockName = e.getKey();
112             if (!key.startsWith(blockName + ".")) {
113                 continue;
114             }
115 
116             String prefix = blockName + "." + e.getValue() ".";
117             if (key.startsWith(prefix)) {
118                 String subkey = key.substring(prefix.length());
119                 ConditionalBlockMatch match = resolveConditionalBlockMatch(subkey);
120                 if (match == null) {
121                     match = new ConditionalBlockMatch(subkey);
122                 }
123                 return match;
124             else {
125                 return new ConditionalBlockMatch(null);
126             }
127         }
128 
129         return null;
130     }
131 
132     private static class ConditionalBlockMatch {
133         public final String key;
134 
135         private ConditionalBlockMatch(String key) {
136             this.key = key;
137         }
138     }
139 }