Skip to content

Commit d8c7270

Browse files
committed
Consistent Iterator/Stream support in PropertySources and PropertyValues
Issue: SPR-16894
1 parent bb3061d commit d8c7270

File tree

7 files changed

+194
-18
lines changed

7 files changed

+194
-18
lines changed

spring-beans/src/main/java/org/springframework/beans/MutablePropertyValues.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,21 @@
1818

1919
import java.io.Serializable;
2020
import java.util.ArrayList;
21+
import java.util.Collections;
2122
import java.util.HashSet;
23+
import java.util.Iterator;
2224
import java.util.List;
2325
import java.util.Map;
2426
import java.util.Set;
27+
import java.util.Spliterator;
28+
import java.util.Spliterators;
29+
import java.util.stream.Stream;
2530

2631
import org.springframework.lang.Nullable;
2732
import org.springframework.util.StringUtils;
2833

2934
/**
30-
* Default implementation of the {@link PropertyValues} interface.
35+
* The default implementation of the {@link PropertyValues} interface.
3136
* Allows simple manipulation of properties, and provides constructors
3237
* to support deep copy and construction from a Map.
3338
*
@@ -244,6 +249,21 @@ public void removePropertyValue(String propertyName) {
244249
}
245250

246251

252+
@Override
253+
public Iterator<PropertyValue> iterator() {
254+
return Collections.unmodifiableList(this.propertyValueList).iterator();
255+
}
256+
257+
@Override
258+
public Spliterator<PropertyValue> spliterator() {
259+
return Spliterators.spliterator(this.propertyValueList, 0);
260+
}
261+
262+
@Override
263+
public Stream<PropertyValue> stream() {
264+
return this.propertyValueList.stream();
265+
}
266+
247267
@Override
248268
public PropertyValue[] getPropertyValues() {
249269
return this.propertyValueList.toArray(new PropertyValue[0]);

spring-beans/src/main/java/org/springframework/beans/PropertyValues.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616

1717
package org.springframework.beans;
1818

19+
import java.util.Arrays;
20+
import java.util.Iterator;
21+
import java.util.Spliterator;
22+
import java.util.Spliterators;
23+
import java.util.stream.Stream;
24+
import java.util.stream.StreamSupport;
25+
1926
import org.springframework.lang.Nullable;
2027

2128
/**
@@ -27,7 +34,33 @@
2734
* @since 13 May 2001
2835
* @see PropertyValue
2936
*/
30-
public interface PropertyValues {
37+
public interface PropertyValues extends Iterable<PropertyValue> {
38+
39+
/**
40+
* Return an {@link Iterator} over the property values.
41+
* @since 5.1
42+
*/
43+
@Override
44+
default Iterator<PropertyValue> iterator() {
45+
return Arrays.asList(getPropertyValues()).iterator();
46+
}
47+
48+
/**
49+
* Return a {@link Spliterator} over the property values.
50+
* @since 5.1
51+
*/
52+
@Override
53+
default Spliterator<PropertyValue> spliterator() {
54+
return Spliterators.spliterator(getPropertyValues(), 0);
55+
}
56+
57+
/**
58+
* Return a sequential {@link Stream} containing the property values.
59+
* @since 5.1
60+
*/
61+
default Stream<PropertyValue> stream() {
62+
return StreamSupport.stream(spliterator(), false);
63+
}
3164

3265
/**
3366
* Return an array of the PropertyValue objects held in this object.

spring-beans/src/test/java/org/springframework/beans/AbstractPropertyValuesTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public abstract class AbstractPropertyValuesTests {
3030
/**
3131
* Must contain: forname=Tony surname=Blair age=50
3232
*/
33-
protected void doTestTony(PropertyValues pvs) throws Exception {
33+
protected void doTestTony(PropertyValues pvs) {
3434
assertTrue("Contains 3", pvs.getPropertyValues().length == 3);
3535
assertTrue("Contains forname", pvs.contains("forname"));
3636
assertTrue("Contains surname", pvs.contains("surname"));

spring-beans/src/test/java/org/springframework/beans/MutablePropertyValuesTests.java

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,20 +16,24 @@
1616

1717
package org.springframework.beans;
1818

19+
import java.util.Iterator;
20+
1921
import org.junit.Test;
2022

23+
import static org.hamcrest.CoreMatchers.*;
2124
import static org.junit.Assert.*;
2225

2326
/**
2427
* Tests for {@link MutablePropertyValues}.
2528
*
2629
* @author Rod Johnson
2730
* @author Chris Beams
31+
* @author Juergen Hoeller
2832
*/
2933
public class MutablePropertyValuesTests extends AbstractPropertyValuesTests {
3034

3135
@Test
32-
public void testValid() throws Exception {
36+
public void testValid() {
3337
MutablePropertyValues pvs = new MutablePropertyValues();
3438
pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
3539
pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
@@ -44,7 +48,7 @@ public void testValid() throws Exception {
4448
}
4549

4650
@Test
47-
public void testAddOrOverride() throws Exception {
51+
public void testAddOrOverride() {
4852
MutablePropertyValues pvs = new MutablePropertyValues();
4953
pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
5054
pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
@@ -59,7 +63,7 @@ public void testAddOrOverride() throws Exception {
5963
}
6064

6165
@Test
62-
public void testChangesOnEquals() throws Exception {
66+
public void testChangesOnEquals() {
6367
MutablePropertyValues pvs = new MutablePropertyValues();
6468
pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
6569
pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
@@ -70,7 +74,7 @@ public void testChangesOnEquals() throws Exception {
7074
}
7175

7276
@Test
73-
public void testChangeOfOneField() throws Exception {
77+
public void testChangeOfOneField() {
7478
MutablePropertyValues pvs = new MutablePropertyValues();
7579
pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
7680
pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
@@ -103,4 +107,50 @@ public void testChangeOfOneField() throws Exception {
103107
assertTrue("new value is bar", fn.getValue().equals("bar"));
104108
}
105109

110+
@Test
111+
public void iteratorContainsPropertyValue() {
112+
MutablePropertyValues pvs = new MutablePropertyValues();
113+
pvs.add("foo", "bar");
114+
115+
Iterator<PropertyValue> it = pvs.iterator();
116+
assertTrue(it.hasNext());
117+
PropertyValue pv = it.next();
118+
assertEquals("foo", pv.getName());
119+
assertEquals("bar", pv.getValue());
120+
121+
try {
122+
it.remove();
123+
fail("Should have thrown UnsupportedOperationException");
124+
}
125+
catch (UnsupportedOperationException ex) {
126+
// expected
127+
}
128+
assertFalse(it.hasNext());
129+
}
130+
131+
@Test
132+
public void iteratorIsEmptyForEmptyValues() {
133+
MutablePropertyValues pvs = new MutablePropertyValues();
134+
Iterator<PropertyValue> it = pvs.iterator();
135+
assertFalse(it.hasNext());
136+
}
137+
138+
@Test
139+
public void streamContainsPropertyValue() {
140+
MutablePropertyValues pvs = new MutablePropertyValues();
141+
pvs.add("foo", "bar");
142+
143+
assertThat(pvs.stream(), notNullValue());
144+
assertThat(pvs.stream().count(), is(1L));
145+
assertThat(pvs.stream().anyMatch(pv -> "foo".equals(pv.getName()) && "bar".equals(pv.getValue())), is(true));
146+
assertThat(pvs.stream().anyMatch(pv -> "bar".equals(pv.getName()) && "foo".equals(pv.getValue())), is(false));
147+
}
148+
149+
@Test
150+
public void streamIsEmptyForEmptyValues() {
151+
MutablePropertyValues pvs = new MutablePropertyValues();
152+
assertThat(pvs.stream(), notNullValue());
153+
assertThat(pvs.stream().count(), is(0L));
154+
}
155+
106156
}

spring-core/src/main/java/org/springframework/core/env/MutablePropertySources.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,15 +18,18 @@
1818

1919
import java.util.Iterator;
2020
import java.util.List;
21+
import java.util.Spliterator;
22+
import java.util.Spliterators;
2123
import java.util.concurrent.CopyOnWriteArrayList;
24+
import java.util.stream.Stream;
2225

2326
import org.apache.commons.logging.Log;
2427
import org.apache.commons.logging.LogFactory;
2528

2629
import org.springframework.lang.Nullable;
2730

2831
/**
29-
* Default implementation of the {@link PropertySources} interface.
32+
* The default implementation of the {@link PropertySources} interface.
3033
* Allows manipulation of contained property sources and provides a constructor
3134
* for copying an existing {@code PropertySources} instance.
3235
*
@@ -73,6 +76,21 @@ public MutablePropertySources(PropertySources propertySources) {
7376
}
7477

7578

79+
@Override
80+
public Iterator<PropertySource<?>> iterator() {
81+
return this.propertySourceList.iterator();
82+
}
83+
84+
@Override
85+
public Spliterator<PropertySource<?>> spliterator() {
86+
return Spliterators.spliterator(this.propertySourceList, 0);
87+
}
88+
89+
@Override
90+
public Stream<PropertySource<?>> stream() {
91+
return this.propertySourceList.stream();
92+
}
93+
7694
@Override
7795
public boolean contains(String name) {
7896
return this.propertySourceList.contains(PropertySource.named(name));
@@ -85,10 +103,6 @@ public PropertySource<?> get(String name) {
85103
return (index != -1 ? this.propertySourceList.get(index) : null);
86104
}
87105

88-
@Override
89-
public Iterator<PropertySource<?>> iterator() {
90-
return this.propertySourceList.iterator();
91-
}
92106

93107
/**
94108
* Add the given property source object with highest precedence.

spring-core/src/main/java/org/springframework/core/env/PropertySources.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,16 +16,29 @@
1616

1717
package org.springframework.core.env;
1818

19+
import java.util.stream.Stream;
20+
import java.util.stream.StreamSupport;
21+
1922
import org.springframework.lang.Nullable;
2023

2124
/**
2225
* Holder containing one or more {@link PropertySource} objects.
2326
*
2427
* @author Chris Beams
28+
* @author Juergen Hoeller
2529
* @since 3.1
30+
* @see PropertySource
2631
*/
2732
public interface PropertySources extends Iterable<PropertySource<?>> {
2833

34+
/**
35+
* Return a sequential {@link Stream} containing the property sources.
36+
* @since 5.1
37+
*/
38+
default Stream<PropertySource<?>> stream() {
39+
return StreamSupport.stream(spliterator(), false);
40+
}
41+
2942
/**
3043
* Return whether a property source with the given name is contained.
3144
* @param name the {@linkplain PropertySource#getName() name of the property source} to find

spring-core/src/test/java/org/springframework/core/env/MutablePropertySourcesTests.java

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.core.env;
1818

19+
import java.util.Iterator;
20+
1921
import org.junit.Test;
2022

2123
import org.springframework.mock.env.MockPropertySource;
@@ -46,9 +48,9 @@ public void test() {
4648
assertThat(sources.contains("g"), is(false));
4749

4850
assertThat(sources.get("b"), not(nullValue()));
49-
assertThat(sources.get("b").getProperty("p1"), equalTo((Object)"bValue"));
51+
assertThat(sources.get("b").getProperty("p1"), equalTo("bValue"));
5052
assertThat(sources.get("d"), not(nullValue()));
51-
assertThat(sources.get("d").getProperty("p1"), equalTo((Object)"dValue"));
53+
assertThat(sources.get("d").getProperty("p1"), equalTo("dValue"));
5254

5355
sources.addBefore("b", new MockPropertySource("a"));
5456
sources.addAfter("b", new MockPropertySource("c"));
@@ -153,4 +155,48 @@ public void getNonExistentPropertySourceReturnsNull() {
153155
assertThat(sources.get("bogus"), nullValue());
154156
}
155157

158+
@Test
159+
public void iteratorContainsPropertySource() {
160+
MutablePropertySources sources = new MutablePropertySources();
161+
sources.addLast(new MockPropertySource("test"));
162+
163+
Iterator<PropertySource<?>> it = sources.iterator();
164+
assertTrue(it.hasNext());
165+
assertEquals("test", it.next().getName());
166+
167+
try {
168+
it.remove();
169+
fail("Should have thrown UnsupportedOperationException");
170+
}
171+
catch (UnsupportedOperationException ex) {
172+
// expected
173+
}
174+
assertFalse(it.hasNext());
175+
}
176+
177+
@Test
178+
public void iteratorIsEmptyForEmptySources() {
179+
MutablePropertySources sources = new MutablePropertySources();
180+
Iterator<PropertySource<?>> it = sources.iterator();
181+
assertFalse(it.hasNext());
182+
}
183+
184+
@Test
185+
public void streamContainsPropertySource() {
186+
MutablePropertySources sources = new MutablePropertySources();
187+
sources.addLast(new MockPropertySource("test"));
188+
189+
assertThat(sources.stream(), notNullValue());
190+
assertThat(sources.stream().count(), is(1L));
191+
assertThat(sources.stream().anyMatch(source -> "test".equals(source.getName())), is(true));
192+
assertThat(sources.stream().anyMatch(source -> "bogus".equals(source.getName())), is(false));
193+
}
194+
195+
@Test
196+
public void streamIsEmptyForEmptySources() {
197+
MutablePropertySources sources = new MutablePropertySources();
198+
assertThat(sources.stream(), notNullValue());
199+
assertThat(sources.stream().count(), is(0L));
200+
}
201+
156202
}

0 commit comments

Comments
 (0)