Add org.apache.commons.collections4.properties.OrderedProperties and
OrderedPropertiesFactory
This commit is contained in:
parent
d3dbdc80d4
commit
452533ab6d
2
pom.xml
2
pom.xml
|
@ -647,7 +647,7 @@
|
|||
<suppressionsLocation>${basedir}/src/conf/checkstyle-suppressions.xml</suppressionsLocation>
|
||||
<enableRulesSummary>false</enableRulesSummary>
|
||||
<includeTestSourceDirectory>true</includeTestSourceDirectory>
|
||||
<resourceExcludes>NOTICE.txt,LICENSE.txt,**/pom.properties,**/test.properties,**/resolver-status.properties</resourceExcludes>
|
||||
<resourceExcludes>NOTICE.txt,LICENSE.txt,**/pom.properties,**/test*.properties,**/resolver-status.properties</resourceExcludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -270,6 +270,9 @@
|
|||
<action issue="COLLECTIONS-746" dev="ggregory" type="add" due-to="Gary Gregory">
|
||||
Add PropertiesFactory.
|
||||
</action>
|
||||
<action dev="ggregory" type="add" due-to="Gary Gregory">
|
||||
Add org.apache.commons.collections4.properties.OrderedProperties and OrderedPropertiesFactory.
|
||||
</action>
|
||||
<!-- UPDATE -->
|
||||
<action dev="ggregory" type="update" due-to="Gary Gregory, Dependabot">
|
||||
Bump org.easymock:easymock from 4.0.2 to 5.1.0 #352, #355, #375.
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.collections4.properties;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A drop-in replacement for {@link Properties} for ordered keys.
|
||||
* <p>
|
||||
* Overrides methods to keep keys in insertion order. Allows other methods in the superclass to work with ordered keys.
|
||||
* </p>
|
||||
*
|
||||
* @see OrderedPropertiesFactory#INSTANCE
|
||||
* @since 4.5
|
||||
*/
|
||||
public class OrderedProperties extends Properties {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Preserves the insertion order.
|
||||
*/
|
||||
private final LinkedHashSet<Object> orderedKeys = new LinkedHashSet<>();
|
||||
|
||||
@Override
|
||||
public synchronized void clear() {
|
||||
orderedKeys.clear();
|
||||
super.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object compute(Object key, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
|
||||
Object compute = super.compute(key, remappingFunction);
|
||||
if (compute != null) {
|
||||
orderedKeys.add(key);
|
||||
}
|
||||
return compute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object computeIfAbsent(Object key, Function<? super Object, ? extends Object> mappingFunction) {
|
||||
Object computeIfAbsent = super.computeIfAbsent(key, mappingFunction);
|
||||
if (computeIfAbsent != null) {
|
||||
orderedKeys.add(key);
|
||||
}
|
||||
return computeIfAbsent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Enumeration<Object> keys() {
|
||||
return Collections.enumeration(orderedKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Object> keySet() {
|
||||
return orderedKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object merge(final Object key, final Object value,
|
||||
final BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
|
||||
orderedKeys.add(key);
|
||||
return super.merge(key, value, remappingFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<?> propertyNames() {
|
||||
return Collections.enumeration(orderedKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object put(final Object key, final Object value) {
|
||||
Object put = super.put(key, value);
|
||||
if (put == null) {
|
||||
orderedKeys.add(key);
|
||||
}
|
||||
return put;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void putAll(final Map<? extends Object, ? extends Object> t) {
|
||||
orderedKeys.addAll(t.keySet());
|
||||
super.putAll(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object putIfAbsent(final Object key, final Object value) {
|
||||
Object putIfAbsent = super.putIfAbsent(key, value);
|
||||
if (putIfAbsent == null) {
|
||||
orderedKeys.add(key);
|
||||
}
|
||||
return putIfAbsent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object remove(final Object key) {
|
||||
Object remove = super.remove(key);
|
||||
if (remove != null) {
|
||||
orderedKeys.remove(key);
|
||||
}
|
||||
return remove;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean remove(final Object key, final Object value) {
|
||||
boolean remove = super.remove(key, value);
|
||||
if (remove) {
|
||||
orderedKeys.remove(key);
|
||||
}
|
||||
return remove;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.commons.collections4.properties;
|
||||
|
||||
/**
|
||||
* Creates and loads {@link OrderedProperties}.
|
||||
*
|
||||
* @see OrderedProperties
|
||||
* @since 4.5
|
||||
*/
|
||||
public class OrderedPropertiesFactory extends AbstractPropertiesFactory<OrderedProperties> {
|
||||
|
||||
/**
|
||||
* The singleton instance.
|
||||
*/
|
||||
public static final OrderedPropertiesFactory INSTANCE = new OrderedPropertiesFactory();
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
*/
|
||||
private OrderedPropertiesFactory() {
|
||||
// There is only one instance.
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses override to provide customized properties instances.
|
||||
*
|
||||
* @return a new Properties instance.
|
||||
*/
|
||||
@Override
|
||||
protected OrderedProperties createProperties() {
|
||||
return new OrderedProperties();
|
||||
}
|
||||
|
||||
}
|
|
@ -64,14 +64,14 @@ public abstract class AbstractPropertiesFactoryTest<T extends Properties> {
|
|||
assertEquals("value11", properties.getProperty("key11"));
|
||||
}
|
||||
|
||||
private boolean isXmlTest(final String fileExtension) {
|
||||
return ".xml".equals(fileExtension);
|
||||
}
|
||||
|
||||
private String getPathString(final String fileExtension) {
|
||||
return BulkTest.TEST_PROPERTIES_PATH + "test" + fileExtension;
|
||||
}
|
||||
|
||||
private boolean isXmlTest(final String fileExtension) {
|
||||
return ".xml".equals(fileExtension);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstance() {
|
||||
assertNotNull(PropertiesFactory.INSTANCE);
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.collections4.properties;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link OrderedPropertiesFactory}.
|
||||
*/
|
||||
public class OrderedPropertiesFactoryTest extends AbstractPropertiesFactoryTest<OrderedProperties> {
|
||||
|
||||
public OrderedPropertiesFactoryTest() {
|
||||
super(OrderedPropertiesFactory.INSTANCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testInstance() {
|
||||
assertNotNull(OrderedPropertiesFactory.INSTANCE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.collections4.properties;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link OrderedProperties}.
|
||||
*/
|
||||
public class OrderedPropertiesTest {
|
||||
|
||||
private void assertAscendingOrder(final OrderedProperties orderedProperties) {
|
||||
final int first = 1;
|
||||
final int last = 11;
|
||||
final Enumeration<Object> enumObjects = orderedProperties.keys();
|
||||
for (int i = first; i <= last; i++) {
|
||||
assertEquals("key" + i, enumObjects.nextElement());
|
||||
}
|
||||
final Iterator<Object> iterSet = orderedProperties.keySet().iterator();
|
||||
for (int i = first; i <= last; i++) {
|
||||
assertEquals("key" + i, iterSet.next());
|
||||
}
|
||||
final Enumeration<?> propertyNames = orderedProperties.propertyNames();
|
||||
for (int i = first; i <= last; i++) {
|
||||
assertEquals("key" + i, propertyNames.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
private OrderedProperties assertDescendingOrder(final OrderedProperties orderedProperties) {
|
||||
final int first = 11;
|
||||
final int last = 1;
|
||||
final Enumeration<Object> enumObjects = orderedProperties.keys();
|
||||
for (int i = first; i <= last; i--) {
|
||||
assertEquals("key" + i, enumObjects.nextElement());
|
||||
}
|
||||
final Iterator<Object> iterSet = orderedProperties.keySet().iterator();
|
||||
for (int i = first; i <= last; i--) {
|
||||
assertEquals("key" + i, iterSet.next());
|
||||
}
|
||||
final Enumeration<?> propertyNames = orderedProperties.propertyNames();
|
||||
for (int i = first; i <= last; i--) {
|
||||
assertEquals("key" + i, propertyNames.nextElement());
|
||||
}
|
||||
return orderedProperties;
|
||||
}
|
||||
|
||||
private OrderedProperties loadOrderedKeysReverse() throws FileNotFoundException, IOException {
|
||||
final OrderedProperties orderedProperties = new OrderedProperties();
|
||||
try (FileReader reader = new FileReader("src/test/resources/org/apache/commons/collections4/properties/test-reverse.properties")) {
|
||||
orderedProperties.load(reader);
|
||||
}
|
||||
return assertDescendingOrder(orderedProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompute() {
|
||||
final OrderedProperties orderedProperties = new OrderedProperties();
|
||||
int first = 1;
|
||||
int last = 11;
|
||||
for (int i = first; i <= last; i++) {
|
||||
final AtomicInteger aInt = new AtomicInteger(i);
|
||||
orderedProperties.compute("key" + i, (k, v) -> "value" + aInt.get());
|
||||
}
|
||||
assertAscendingOrder(orderedProperties);
|
||||
orderedProperties.clear();
|
||||
first = 11;
|
||||
last = 1;
|
||||
for (int i = first; i >= last; i--) {
|
||||
final AtomicInteger aInt = new AtomicInteger(i);
|
||||
orderedProperties.compute("key" + i, (k, v) -> "value" + aInt.get());
|
||||
}
|
||||
assertDescendingOrder(orderedProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComputeIfAbsent() {
|
||||
final OrderedProperties orderedProperties = new OrderedProperties();
|
||||
int first = 1;
|
||||
int last = 11;
|
||||
for (int i = first; i <= last; i++) {
|
||||
final AtomicInteger aInt = new AtomicInteger(i);
|
||||
orderedProperties.computeIfAbsent("key" + i, k -> "value" + aInt.get());
|
||||
}
|
||||
assertAscendingOrder(orderedProperties);
|
||||
orderedProperties.clear();
|
||||
first = 11;
|
||||
last = 1;
|
||||
for (int i = first; i >= last; i--) {
|
||||
final AtomicInteger aInt = new AtomicInteger(i);
|
||||
orderedProperties.computeIfAbsent("key" + i, k -> "value" + aInt.get());
|
||||
}
|
||||
assertDescendingOrder(orderedProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntrySet() {
|
||||
final OrderedProperties orderedProperties = new OrderedProperties();
|
||||
for (char ch = 'Z'; ch >= 'A'; ch--) {
|
||||
orderedProperties.put(String.valueOf(ch), "Value" + ch);
|
||||
}
|
||||
final Iterator<Map.Entry<Object, Object>> entries = orderedProperties.entrySet().iterator();
|
||||
for (char ch = 'Z'; ch <= 'A'; ch++) {
|
||||
final Map.Entry<Object, Object> entry = entries.next();
|
||||
assertEquals(String.valueOf(ch), entry.getKey());
|
||||
assertEquals("Value" + ch, entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeys() {
|
||||
final OrderedProperties orderedProperties = new OrderedProperties();
|
||||
for (char ch = 'Z'; ch >= 'A'; ch--) {
|
||||
orderedProperties.put(String.valueOf(ch), "Value" + ch);
|
||||
}
|
||||
final Enumeration<Object> keys = orderedProperties.keys();
|
||||
for (char ch = 'Z'; ch <= 'A'; ch++) {
|
||||
assertEquals(String.valueOf(ch), keys.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadOrderedKeys() throws FileNotFoundException, IOException {
|
||||
final OrderedProperties orderedProperties = new OrderedProperties();
|
||||
try (FileReader reader = new FileReader("src/test/resources/org/apache/commons/collections4/properties/test.properties")) {
|
||||
orderedProperties.load(reader);
|
||||
}
|
||||
assertAscendingOrder(orderedProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadOrderedKeysReverse() throws FileNotFoundException, IOException {
|
||||
loadOrderedKeysReverse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMerge() {
|
||||
final OrderedProperties orderedProperties = new OrderedProperties();
|
||||
int first = 1;
|
||||
int last = 11;
|
||||
for (int i = first; i <= last; i++) {
|
||||
orderedProperties.merge("key" + i, "value" + i, (k, v) -> v);
|
||||
}
|
||||
assertAscendingOrder(orderedProperties);
|
||||
orderedProperties.clear();
|
||||
first = 11;
|
||||
last = 1;
|
||||
for (int i = first; i >= last; i--) {
|
||||
orderedProperties.merge("key" + i, "value" + i, (k, v) -> v);
|
||||
}
|
||||
assertDescendingOrder(orderedProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPut() {
|
||||
final OrderedProperties orderedProperties = new OrderedProperties();
|
||||
int first = 1;
|
||||
int last = 11;
|
||||
for (int i = first; i <= last; i++) {
|
||||
orderedProperties.put("key" + i, "value" + i);
|
||||
}
|
||||
assertAscendingOrder(orderedProperties);
|
||||
orderedProperties.clear();
|
||||
first = 11;
|
||||
last = 1;
|
||||
for (int i = first; i >= last; i--) {
|
||||
orderedProperties.put("key" + i, "value" + i);
|
||||
}
|
||||
assertDescendingOrder(orderedProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAll() {
|
||||
final OrderedProperties sourceProperties = new OrderedProperties();
|
||||
int first = 1;
|
||||
int last = 11;
|
||||
for (int i = first; i <= last; i++) {
|
||||
sourceProperties.put("key" + i, "value" + i);
|
||||
}
|
||||
final OrderedProperties orderedProperties = new OrderedProperties();
|
||||
orderedProperties.putAll(sourceProperties);
|
||||
assertAscendingOrder(orderedProperties);
|
||||
orderedProperties.clear();
|
||||
first = 11;
|
||||
last = 1;
|
||||
for (int i = first; i >= last; i--) {
|
||||
orderedProperties.put("key" + i, "value" + i);
|
||||
}
|
||||
assertDescendingOrder(orderedProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutIfAbsent() {
|
||||
final OrderedProperties orderedProperties = new OrderedProperties();
|
||||
int first = 1;
|
||||
int last = 11;
|
||||
for (int i = first; i <= last; i++) {
|
||||
orderedProperties.putIfAbsent("key" + i, "value" + i);
|
||||
}
|
||||
assertAscendingOrder(orderedProperties);
|
||||
orderedProperties.clear();
|
||||
first = 11;
|
||||
last = 1;
|
||||
for (int i = first; i >= last; i--) {
|
||||
orderedProperties.putIfAbsent("key" + i, "value" + i);
|
||||
}
|
||||
assertDescendingOrder(orderedProperties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveKey() throws FileNotFoundException, IOException {
|
||||
final OrderedProperties props = loadOrderedKeysReverse();
|
||||
final String k = "key1";
|
||||
props.remove(k);
|
||||
assertFalse(props.contains(k));
|
||||
assertFalse(props.containsKey(k));
|
||||
assertFalse(Collections.list(props.keys()).contains(k));
|
||||
assertFalse(Collections.list(props.propertyNames()).contains(k));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveKeyValue() throws FileNotFoundException, IOException {
|
||||
final OrderedProperties props = loadOrderedKeysReverse();
|
||||
final String k = "key1";
|
||||
props.remove(k, "value1");
|
||||
assertFalse(props.contains(k));
|
||||
assertFalse(props.containsKey(k));
|
||||
assertFalse(Collections.list(props.keys()).contains(k));
|
||||
assertFalse(Collections.list(props.propertyNames()).contains(k));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
key11 = value11
|
||||
key10 = value10
|
||||
key9 = value9
|
||||
key8 = value8
|
||||
key7 = value7
|
||||
key6 = value6
|
||||
key5 = value5
|
||||
key4 = value4
|
||||
key3 = value3
|
||||
key2 = value2
|
||||
key1 = value1
|
Loading…
Reference in New Issue