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