4141import com .google .inject .Key ;
4242import com .google .inject .name .Names ;
4343import com .typesafe .config .Config ;
44- import com .typesafe .config .ConfigFactory ;
4544
4645import javaslang .API ;
4746import javaslang .control .Option ;
6968 */
7069public interface Env extends LifeCycle {
7170
71+ /**
72+ * Property source for {@link Resolver}
73+ *
74+ * @author edgar
75+ * @since 1.1.0
76+ */
77+ interface PropertySource {
78+
79+ /**
80+ * Get a property value or throw {@link NoSuchElementException}.
81+ *
82+ * @param key Property key/name.
83+ * @return Value or throw {@link NoSuchElementException}.
84+ * @throws NoSuchElementException If property is missing.
85+ */
86+ String get (String key ) throws NoSuchElementException ;
87+ }
88+
89+ /**
90+ * {@link PropertySource} for {@link Config}.
91+ *
92+ * @author edgar
93+ * @since 1.1.0
94+ */
95+ class ConfigSource implements PropertySource {
96+
97+ private Config source ;
98+
99+ public ConfigSource (final Config source ) {
100+ this .source = source ;
101+ }
102+
103+ @ Override
104+ public String get (final String key ) throws NoSuchElementException {
105+ if (source .hasPath (key )) {
106+ return source .getString (key );
107+ }
108+ throw new NoSuchElementException (key );
109+ }
110+
111+ }
112+
113+ /**
114+ * {@link PropertySource} for {@link Map}.
115+ *
116+ * @author edgar
117+ * @since 1.1.0
118+ */
119+ class MapSource implements PropertySource {
120+
121+ private Map <String , Object > source ;
122+
123+ public MapSource (final Map <String , Object > source ) {
124+ this .source = source ;
125+ }
126+
127+ @ Override
128+ public String get (final String key ) throws NoSuchElementException {
129+ Object value = source .get (key );
130+ if (value != null ) {
131+ return value .toString ();
132+ }
133+ throw new NoSuchElementException (key );
134+ }
135+
136+ }
137+
72138 /**
73139 * Template literal implementation, replaces <code>${expression}</code> from a String using a
74140 * {@link Config} object.
@@ -80,7 +146,7 @@ class Resolver {
80146
81147 private String endDelim = "}" ;
82148
83- private Config source ;
149+ private PropertySource source ;
84150
85151 private boolean ignoreMissing ;
86152
@@ -91,8 +157,7 @@ class Resolver {
91157 * @return This resolver.
92158 */
93159 public Resolver source (final Map <String , Object > source ) {
94- this .source = ConfigFactory .parseMap (source );
95- return this ;
160+ return source (new MapSource (source ));
96161 }
97162
98163 /**
@@ -101,11 +166,21 @@ public Resolver source(final Map<String, Object> source) {
101166 * @param source Source.
102167 * @return This resolver.
103168 */
104- public Resolver source (final Config source ) {
169+ public Resolver source (final PropertySource source ) {
105170 this .source = source ;
106171 return this ;
107172 }
108173
174+ /**
175+ * Set property source.
176+ *
177+ * @param source Source.
178+ * @return This resolver.
179+ */
180+ public Resolver source (final Config source ) {
181+ return source (new ConfigSource (source ));
182+ }
183+
109184 /**
110185 * Set start and end delimiters.
111186 *
@@ -166,14 +241,14 @@ public String resolve(final String text) {
166241 buffer .append (text .substring (offset , start ));
167242 String key = text .substring (start + startDelim .length (), end );
168243 Object value ;
169- if ( source . hasPath ( key )) {
170- value = source .getAnyRef (key );
171- } else {
244+ try {
245+ value = source .get (key );
246+ } catch ( NoSuchElementException x ) {
172247 if (ignoreMissing ) {
173248 value = text .substring (start , end + endDelim .length ());
174249 } else {
175250 throw err .apply (start , (line , column ) -> new NoSuchElementException (
176- "No configuration setting found for key '" + key + "' at " + line + ":" + column ));
251+ "Missing " + startDelim + key + endDelim + " at " + line + ":" + column ));
177252 }
178253 }
179254 buffer .append (value );
0 commit comments