blob: 46d7658365a4eb0df8b36f02ade4b576a14e00ba [file] [log] [blame]
/*
* 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 ${package};
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.InvalidPropertiesFormatException;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
class WrapperProperties extends Properties {
final Supplier<Map<String, String>> getter;
final Consumer<Properties> setter;
WrapperProperties(Supplier<Map<String, String>> getter, Consumer<Properties> setter) {
this.getter = getter;
this.setter = setter;
}
@Override
public String getProperty(String key) {
return getter.get().get(key);
}
@Override
public String getProperty(String key, String defaultValue) {
return getter.get().getOrDefault(key, defaultValue);
}
@Override
public Enumeration<?> propertyNames() {
return Collections.enumeration(getter.get().keySet());
}
@Override
public Set<String> stringPropertyNames() {
return getter.get().keySet();
}
@Override
public void list(PrintStream out) {
throw new UnsupportedOperationException();
}
@Override
public void list(PrintWriter out) {
throw new UnsupportedOperationException();
}
@Override
public int size() {
return getter.get().size();
}
@Override
public boolean isEmpty() {
return getter.get().isEmpty();
}
@Override
public Enumeration<Object> keys() {
return Collections.enumeration((Set) getter.get().keySet());
}
@Override
public Enumeration<Object> elements() {
return Collections.enumeration((Collection) getter.get().values());
}
@Override
public boolean contains(Object value) {
return getter.get().containsKey(value != null ? value.toString() : null);
}
@Override
public boolean containsValue(Object value) {
return getter.get().containsValue(value);
}
@Override
public boolean containsKey(Object key) {
return getter.get().containsKey(key);
}
@Override
public Object get(Object key) {
return getter.get().get(key);
}
@Override
public synchronized String toString() {
return getter.get().toString();
}
@Override
public Set<Object> keySet() {
return (Set) getter.get().keySet();
}
@Override
public Collection<Object> values() {
return (Collection) getter.get().values();
}
@Override
public Set<Map.Entry<Object, Object>> entrySet() {
return (Set) getter.get().entrySet();
}
@Override
public synchronized boolean equals(Object o) {
if (o instanceof WrapperProperties) {
o = ((WrapperProperties) o).getter.get();
}
return getter.get().equals(o);
}
@Override
public synchronized int hashCode() {
return getter.get().hashCode();
}
@Override
public Object getOrDefault(Object key, Object defaultValue) {
return getter.get().getOrDefault(key, defaultValue != null ? defaultValue.toString() : null);
}
@Override
public synchronized void forEach(BiConsumer<? super Object, ? super Object> action) {
getter.get().forEach(action);
}
interface WriteOp<T> {
T perform(Properties props);
}
interface WriteOpVoid {
void perform(Properties props);
}
private <T> T writeOperation(WriteOp<T> runner) {
Properties props = new Properties();
props.putAll(getter.get());
T ret = runner.perform(props);
if (!props.equals(getter.get())) {
setter.accept(props);
}
return ret;
}
private void writeOperationVoid(WriteOpVoid runner) {
Properties props = new Properties();
props.putAll(getter.get());
runner.perform(props);
if (!props.equals(getter.get())) {
setter.accept(props);
}
}
@Override
public synchronized Object setProperty(String key, String value) {
return writeOperation(p -> p.setProperty(key, value));
}
@Override
public synchronized Object put(Object key, Object value) {
return writeOperation(p -> p.put(key, value));
}
@Override
public synchronized Object remove(Object key) {
return writeOperation(p -> p.remove(key));
}
@Override
public synchronized void putAll(Map<?, ?> t) {
writeOperationVoid(p -> p.putAll(t));
}
@Override
public synchronized void clear() {
writeOperationVoid(Properties::clear);
}
@Override
public synchronized void replaceAll(BiFunction<? super Object, ? super Object, ?> function) {
writeOperationVoid(p -> p.replaceAll(function));
}
@Override
public synchronized Object putIfAbsent(Object key, Object value) {
return writeOperation(p -> p.putIfAbsent(key, value));
}
@Override
public synchronized boolean remove(Object key, Object value) {
return writeOperation(p -> p.remove(key, value));
}
@Override
public synchronized boolean replace(Object key, Object oldValue, Object newValue) {
return writeOperation(p -> p.replace(key, oldValue, newValue));
}
@Override
public synchronized Object replace(Object key, Object value) {
return writeOperation(p -> p.replace(key, value));
}
@Override
public synchronized Object computeIfAbsent(Object key, Function<? super Object, ?> mappingFunction) {
return writeOperation(p -> p.computeIfAbsent(key, mappingFunction));
}
@Override
public synchronized Object computeIfPresent(
Object key, BiFunction<? super Object, ? super Object, ?> remappingFunction) {
return writeOperation(p -> p.computeIfPresent(key, remappingFunction));
}
@Override
public synchronized Object compute(Object key, BiFunction<? super Object, ? super Object, ?> remappingFunction) {
return writeOperation(p -> p.compute(key, remappingFunction));
}
@Override
public synchronized Object merge(
Object key, Object value, BiFunction<? super Object, ? super Object, ?> remappingFunction) {
return writeOperation(p -> p.merge(key, value, remappingFunction));
}
@Override
public synchronized void load(Reader reader) throws IOException {
try {
writeOperationVoid(p -> {
try {
p.load(reader);
} catch (IOException e) {
throw new IOError(e);
}
});
} catch (IOError e) {
throw (IOException) e.getCause();
}
}
@Override
public synchronized void load(InputStream inStream) throws IOException {
try {
writeOperationVoid(p -> {
try {
p.load(inStream);
} catch (IOException e) {
throw new IOError(e);
}
});
} catch (IOError e) {
throw (IOException) e.getCause();
}
}
@Override
public void save(OutputStream out, String comments) {
Properties props = new Properties();
props.putAll(getter.get());
props.save(out, comments);
}
@Override
public void store(Writer writer, String comments) throws IOException {
Properties props = new Properties();
props.putAll(getter.get());
props.store(writer, comments);
}
@Override
public void store(OutputStream out, String comments) throws IOException {
Properties props = new Properties();
props.putAll(getter.get());
props.store(out, comments);
}
@Override
public synchronized void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException {
throw new UnsupportedOperationException();
}
@Override
public void storeToXML(OutputStream os, String comment) throws IOException {
Properties props = new Properties();
props.putAll(getter.get());
props.storeToXML(os, comment);
}
@Override
public void storeToXML(OutputStream os, String comment, String encoding) throws IOException {
Properties props = new Properties();
props.putAll(getter.get());
props.storeToXML(os, comment, encoding);
}
}