| 
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 griffon.util;
 017
 018 import javax.annotation.Nonnull;
 019 import javax.annotation.Nullable;
 020 import java.util.Enumeration;
 021 import java.util.Iterator;
 022 import java.util.LinkedHashMap;
 023 import java.util.Map;
 024 import java.util.ResourceBundle;
 025
 026 import static griffon.util.ConfigUtils.getConfigValue;
 027 import static griffon.util.GriffonNameUtils.requireNonBlank;
 028 import static java.util.Objects.requireNonNull;
 029
 030 /**
 031  * @author Andres Almiray
 032  * @since 2.0.0
 033  */
 034 public class ExpandableResourceBundle extends ResourceBundle {
 035     private final Map<String, Object> entries = new LinkedHashMap<>();
 036
 037     @Nonnull
 038     public static ResourceBundle wrapResourceBundle(@Nonnull ResourceBundle resourceBundle) {
 039         requireNonNull(resourceBundle, "Argument 'resourceBundle' must not be null");
 040         if (!(resourceBundle instanceof ExpandableResourceBundle)) {
 041             return new ExpandableResourceBundle(resourceBundle);
 042         }
 043         return resourceBundle;
 044     }
 045
 046     public ExpandableResourceBundle(@Nonnull ResourceBundle delegate) {
 047         requireNonNull(delegate, "Argument 'delegate' must not be null");
 048         for (String key : delegate.keySet()) {
 049             Object value = getConfigValue(delegate, key);
 050             processKey(key, entries, value);
 051             entries.put(key, value);
 052         }
 053     }
 054
 055     @SuppressWarnings("unchecked")
 056     private void processKey(@Nonnull String key, @Nonnull Map<String, Object> map, @Nullable Object value) {
 057         String[] keys = split(key);
 058         if (keys[1] == null) {
 059             map.put(keys[0], value);
 060         } else {
 061             Map<String, Object> m = (Map<String, Object>) map.get(keys[0]);
 062             if (m == null) {
 063                 m = new LinkedHashMap<>();
 064                 map.put(keys[0], m);
 065             }
 066             processKey(keys[1], m, value);
 067         }
 068     }
 069
 070     @Nonnull
 071     private String[] split(@Nonnull String input) {
 072         int split = input.indexOf(".");
 073         String head = split < 0 ? input : input.substring(0, split);
 074         String tail = split > 0 ? input.substring(split + 1) : null;
 075         return new String[]{head, tail};
 076     }
 077
 078     @Nullable
 079     @Override
 080     protected final Object handleGetObject(@Nonnull String key) {
 081         return entries.get(requireNonBlank(key, "Argument 'key' must not be blank"));
 082     }
 083
 084     @Nonnull
 085     @Override
 086     public final Enumeration<String> getKeys() {
 087         return new IteratorAsEnumeration<>(entries.keySet().iterator());
 088     }
 089
 090     private static class IteratorAsEnumeration<E> implements Enumeration<E> {
 091         private final Iterator<E> iterator;
 092
 093         public IteratorAsEnumeration(Iterator<E> iterator) {
 094             this.iterator = iterator;
 095         }
 096
 097         public boolean hasMoreElements() {
 098             return iterator.hasNext();
 099         }
 100
 101         public E nextElement() {
 102             return iterator.next();
 103         }
 104     }
 105 }
 |