com.vectorprint.configuration.VectorPrintProperties Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of VectorPrintConfig Show documentation
Show all versions of VectorPrintConfig Show documentation
A library for configuration of applications and parameterization of objects. Settings can be provided in a configfile (file, url, stream), as arguments and programmatically, object parameters can be set using annotations or code. Both provide data type support, serialization, cloning, a help mechanism.
package com.vectorprint.configuration;
/*
* #%L
* VectorPrintConfig3.0
* %%
* Copyright (C) 2011 - 2013 VectorPrint
* %%
* Licensed 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.
* #L%
*/
import com.vectorprint.VectorPrintRuntimeException;
import com.vectorprint.configuration.observing.KeyValueObservable;
import com.vectorprint.configuration.observing.PrepareKeyValue;
import com.vectorprint.ArrayHelper;
import com.vectorprint.configuration.observing.TrimKeyValue;
import com.vectorprint.configuration.parameters.MultipleValueParser;
import com.vectorprint.configuration.parameters.ParameterHelper;
import com.vectorprint.configuration.parser.MultiValueParser;
import com.vectorprint.configuration.parser.ParseException;
import com.vectorprint.configuration.parser.PropertiesParser;
import java.awt.Color;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PreDestroy;
/**
* Enhances Java Map with typing, debugging info, property source, overriding properties from the command line
* arguments. There are three sources for property values: a default value in source code, a value from a property file
* (or url) or a value on the command line.
*
* @author Eduard Drenth at VectorPrint.nl
*/
public class VectorPrintProperties extends HashMap
implements EnhancedMap, KeyValueObservable {
private static final long serialVersionUID = 1;
/**
* default name of the file containing help for settings
*/
public static final String HELPFILE = "help.properties";
public static final String MISSINGHELP = "no help configured, provide help file " + HELPFILE + " using format =;";
private static final Logger log = Logger.getLogger(VectorPrintProperties.class.getName());
@Override
public void listProperties(PrintStream ps) {
ps.println("settings from: " + getPropertyUrl() + ":\n");
for (Map.Entry entry : super.entrySet()) {
ps.println(entry.getKey() + "=" + entry.getValue());
}
ps.println("");
}
private URL propertyUrl;
private String urlString;
private boolean allowArguments = true;
private final Map help = new HashMap(50);
private final Set propsFromArgs = new HashSet(10);
private final Map> commentBeforeKeys = new HashMap>(50);
private final List trailingComment = new ArrayList(0);
/**
* calls {@link #VectorPrintProperties(String, String[], java.util.List)} with properties, null, null.
*
* @param properties
* @throws IOException
* @throws com.vectorprint.configuration.parser.ParseException
*/
public VectorPrintProperties(URL properties) throws IOException, ParseException {
this(properties, null, null);
}
/**
* calls {@link VectorPrintProperties#VectorPrintProperties(java.io.InputStream, java.lang.String, java.lang.String[], java.util.List)
* }
* with properties.toString for id.
*/
public VectorPrintProperties(URL properties, String[] args, List> observers) throws IOException, ParseException {
this(properties.openStream(), properties.toString(), observers);
}
/**
* bottleneck constructor
*
* @param in the stream the properties will be loaded from
* @param id the suggested id for these properties, an attempt is made to turn it into a url
* @param observers objects responsible for preparing key value pairs being added, may be null
* @throws IOException
* @throws com.vectorprint.configuration.parser.ParseException
*/
public VectorPrintProperties(InputStream in, String id, List> observers) throws IOException, ParseException {
super(25);
if (observers != null) {
for (PrepareKeyValue pv : observers) {
addObserver(pv);
}
}
try {
propertyUrl = new URL(id);
} catch (MalformedURLException me) {
log.warning(id + " cannot be turned into a URL");
}
urlString = id;
loadFromStream(in);
}
/**
* {@link ArgumentParser#parseArgs(java.lang.String[]) parses the arguments} and calls {@link #putAll(java.util.Map)
* }
*
* @param args
*/
@Override
public void addFromArguments(String[] args) {
if (allowArguments) {
Map props = ArgumentParser.parseArgs(args);
if (props != null) {
propsFromArgs.addAll(props.keySet());
putAll(props);
}
} else {
throw new VectorPrintRuntimeException("adding properties from arguments is not allowed");
}
}
/**
* loads properties (overwrites) from the stream determined at construction. If you put a \ at the end of a line in a
* settings file the next line will be concatenated. If there is no \ at the end and the next line contains no "="
* the next line will be concatenated with line.separator as glue.
*
* @throws IOException
*/
protected void loadFromStream(InputStream in) throws IOException, ParseException {
BufferedReader bi = new BufferedReader(new InputStreamReader(in));
try {
new PropertiesParser(bi).parse(this);
} finally {
bi.close();
}
}
/**
* loads properties (overwrites) from the url determined at construction. If you put a \ at the end of a line in a
* settings file the next line will be concatenated. If there is no \ at the end and the next line contains no "="
* the next line will be concatenated with line.separator as glue.
*
* @see #loadFromStream(java.io.InputStream)
* @throws IOException
*/
protected void loadFromUrl() throws IOException, ParseException {
loadFromStream(propertyUrl.openStream());
}
/**
* save the properties to the url the properties were initialized from, including those set by
* {@link #addFromArguments(String[])} .
*
* @throws IOException
*/
public void saveToUrl() throws IOException {
saveToUrl(propertyUrl);
}
public static final String EOL = System.getProperty("line.separator","\n");
/**
* save the properties to a url, including those set by {@link #addFromArguments(String[])}.
*
* @throws IOException
*/
public void saveToUrl(URL url) throws IOException {
BufferedOutputStream bo = null;
try {
OutputStream o;
if ("file".equals(url.getProtocol())) {
o = new FileOutputStream(url.getFile());
} else {
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(false);
o = conn.getOutputStream();
}
bo = new BufferedOutputStream(o);
for (Map.Entry entry : super.entrySet()) {
for (String s : getCommentBeforeKey(entry.getKey())) {
bo.write(s.getBytes());
}
bo.write((entry.getKey() + "=" + entry.getValue() + EOL).getBytes());
}
if (!trailingComment.isEmpty()) {
for (String s : trailingComment) {
bo.write(s.getBytes());
}
}
} finally {
if (bo != null) {
bo.close();
}
}
}
/**
* calls {@link #VectorPrintProperties(String, String[], java.util.List)} with an URL constructed from the filename
* and the arguments
*
* @param propertyFile
* @param args
* @throws IOException
*/
public VectorPrintProperties(String propertyFile, String[] args) throws IOException, ParseException {
this(new File(propertyFile).toURI().toURL(), args, null);
}
public VectorPrintProperties(String propertyFile, String[] args, List> observers) throws IOException, ParseException {
this(new File(propertyFile).toURI().toURL(), args, observers);
}
/**
* calls {@link #VectorPrintProperties(String, String[])} with an URL constructed from the filename and null
*
* @param propertyFile
* @throws IOException
*/
public VectorPrintProperties(String propertyFile) throws IOException, ParseException {
this(propertyFile, null);
}
/**
* clears all properties, reloads from the url that initialized these properties and applies the arguments provided.
* Can be usefull when you want to reuse {@link SettingsProvider}s and/or {@link Configurable}s.
*
* @throws IOException
*/
public void reset(String[] args) throws IOException, ParseException {
clear();
loadFromUrl();
addFromArguments(args);
}
protected void debug(String key, Object val) {
debug(key, val, true);
}
protected void debug(String key, Object val, boolean defaultVal) {
if (log.isLoggable(Level.FINE)) {
StringBuilder s = new StringBuilder(String.valueOf(val));
if (val != null && val.getClass().isArray()) {
s = new StringBuilder("");
Class compType = val.getClass().getComponentType();
if (!compType.isPrimitive()) {
for (Object o : (Object[]) val) {
s.append(String.valueOf(o)).append("; ");
}
} else {
if (compType.equals(boolean.class)) {
for (boolean o : (boolean[]) val) {
s.append(String.valueOf(o)).append("; ");
}
} else if (compType.equals(char.class)) {
for (char o : (char[]) val) {
s.append(String.valueOf(o)).append("; ");
}
} else if (compType.equals(byte.class)) {
for (byte o : (byte[]) val) {
s.append(String.valueOf(o)).append("; ");
}
} else if (compType.equals(short.class)) {
for (short o : (short[]) val) {
s.append(String.valueOf(o)).append("; ");
}
} else if (compType.equals(int.class)) {
for (int o : (int[]) val) {
s.append(String.valueOf(o)).append("; ");
}
} else if (compType.equals(long.class)) {
for (long o : (long[]) val) {
s.append(String.valueOf(o)).append("; ");
}
} else if (compType.equals(float.class)) {
for (float o : (float[]) val) {
s.append(String.valueOf(o)).append("; ");
}
} else if (compType.equals(double.class)) {
for (double o : (double[]) val) {
s.append(String.valueOf(o)).append("; ");
}
}
}
}
log.fine(String.format("looking for property %s in %s, using value %s", key, propertyUrl, s.append((defaultVal) ? " (default)" : "").toString()));
}
}
@Override
public final String get(Object key) {
unused.remove(key);
return super.get(key);
}
@Override
public String getProperty(String key) {
if (log.isLoggable(Level.FINE)) {
debug(key, (containsKey(key)) ? super.get(key) : null, false);
}
if (containsKey(key)) {
return get(key);
} else {
return null;
}
}
@Override
public String getProperty(String key, String defaultValue) {
if (!containsKey(key)) {
shouldUseDefault(key, defaultValue);
return defaultValue;
}
return getProperty(key);
}
@Override
public URL getURLProperty(String key, URL defaultValue) throws MalformedURLException {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
return new URL(getProperty(key));
}
@Override
public float getFloatProperty(String key, Float defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
return Float.parseFloat(getProperty(key));
}
@Override
public boolean getBooleanProperty(String key, Boolean defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
return Boolean.parseBoolean(getProperty(key));
}
/**
* determine if the default value should be used, check if it is set.
*
* @param key the value of key
* @param defaultVal the value of defaultVal
* @return true when the default value should be used
* @throws VectorPrintRuntimeException when defaultVal should be used and is null
*/
protected boolean shouldUseDefault(String key, Object defaultVal) throws VectorPrintRuntimeException {
if (!containsKey(key)) {
if (defaultVal == null) {
throw new VectorPrintRuntimeException(key + " not found in " + propertyUrl + " and default is null");
} else {
debug(key, defaultVal);
notPresent.add(key);
return true;
}
} else {
return false;
}
}
@Override
public double getDoubleProperty(String key, Double defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
return Double.parseDouble(getProperty(key));
}
@Override
public int getIntegerProperty(String key, Integer defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
return Integer.parseInt(getProperty(key));
}
@Override
public short getShortProperty(String key, Short defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
return Short.parseShort(getProperty(key));
}
@Override
public char getCharProperty(String key, Character defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
return getProperty(key).charAt(0);
}
@Override
public byte getByteProperty(String key, Byte defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
return Byte.decode(getProperty(key));
}
@Override
public long getLongProperty(String key, Long defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
return Long.parseLong(getProperty(key));
}
@Override
public Color getColorProperty(String key, Color defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
return ParameterHelper.getColorFromString(getProperty(key));
}
@Override
public String[] getStringProperties(String key, String[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.toArray(mvp.parseStringValues(getProperty(key), doTrim));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
private transient MultipleValueParser mvp = MultipleValueParser.getInstance();
@Override
public URL[] getURLProperties(String key, URL[] defaultValue) throws MalformedURLException {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.toArray(mvp.parseURLValues(getProperty(key),doTrim));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
@Override
public float[] getFloatProperties(String key, float[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.unWrap(ArrayHelper.toArray(mvp.parseFloatValues(getProperty(key),doTrim)));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
@Override
public char[] getCharProperties(String key, char[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.unWrap(ArrayHelper.toArray(mvp.parseCharValues(getProperty(key),doTrim)));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
@Override
public short[] getShortProperties(String key, short[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.unWrap(ArrayHelper.toArray(mvp.parseShortValues(getProperty(key),doTrim)));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
@Override
public byte[] getByteProperties(String key, byte[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.unWrap(ArrayHelper.toArray(mvp.parseByteValues(getProperty(key),doTrim)));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
@Override
public double[] getDoubleProperties(String key, double[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.unWrap(ArrayHelper.toArray(mvp.parseDoubleValues(getProperty(key),doTrim)));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
@Override
public int[] getIntegerProperties(String key, int[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.unWrap(ArrayHelper.toArray(mvp.parseIntValues(getProperty(key),doTrim)));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
@Override
public boolean[] getBooleanProperties(String key, boolean[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.unWrap(ArrayHelper.toArray(mvp.parseBooleanValues(getProperty(key),doTrim)));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
private boolean doTrim = false;
@Override
public Color[] getColorProperties(String key, Color[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.toArray(mvp.parseColorValues(getProperty(key),doTrim));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
public URL getPropertyUrl() {
return propertyUrl;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof VectorPrintProperties)) {
return false;
}
final VectorPrintProperties other = (VectorPrintProperties) obj;
return !((this.propertyUrl == null) ? (other.propertyUrl != null) : !this.propertyUrl.equals(other.propertyUrl));
}
@Override
public int hashCode() {
int hash = 3;
hash = 37 * hash + (this.propertyUrl != null ? this.propertyUrl.hashCode() : 0);
return hash;
}
public String getUrlString() {
return urlString;
}
@Override
public PropertyHelp getHelp(String key) {
if (help.containsKey(key)) {
return help.get(key);
} else {
return new PropertyHelpImpl("no help configured for " + key);
}
}
/**
* initializes help for properties
*
* @param help
* @see #getHelp(java.lang.String)
* @see #getHelp()
*/
@Override
public void setHelp(Map help) {
this.help.clear();
this.help.putAll(help);
}
@Override
public Map getHelp() {
return help;
}
@Override
public String printHelp() {
StringBuilder sb = new StringBuilder(1024);
for (Map.Entry h : help.entrySet()) {
sb.append(h.getKey()).append(": ").append(h.getValue().getType())
.append("; ")
.append(h.getValue().getExplanation())
.append(System.getProperty("line.separator"));
}
return sb.toString();
}
/**
* When true this property was set from {@link #addFromArguments(String[])} .
*
* @param key
* @return
*/
public boolean isFromArguments(String key) {
return containsKey(key) && propsFromArgs.contains(key);
}
@Override
public long[] getLongProperties(String key, long[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.unWrap(ArrayHelper.toArray(mvp.parseLongValues(getProperty(key),doTrim)));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
@Override
public void addObserver(PrepareKeyValue observer) {
observers.add(observer);
if (observer instanceof TrimKeyValue) {
doTrim = true;
}
}
@Override
public > PKV removeObserver(PKV observer) {
return (observers.remove(observer)) ? observer : null;
}
@Override
public Map prepareKeyValue(String key, String value) {
Map rv = null;
for (PrepareKeyValue pkv : observers) {
if (pkv.shouldPrepare(key, value)) {
rv = pkv.prepare(key, value);
}
}
return rv;
}
private final List> observers = new LinkedList>();
@Override
public final String put(String key, String value) {
Map prepared = prepareKeyValue(key, value);
unused.add(key);
if (prepared == null) {
return super.put(key, value);
} else {
Map.Entry e = prepared.entrySet().iterator().next();
return super.put(e.getKey(), e.getValue());
}
}
@Override
public final void clear() {
unused.clear();
notPresent.clear();
propsFromArgs.clear();
trailingComment.clear();
commentBeforeKeys.clear();
super.clear();
}
@Override
public final String remove(Object key) {
unused.remove(key);
propsFromArgs.remove(key);
return super.remove(key);
}
private MultiValueParser sp = null;
private MultiValueParser getParser(StringReader sr) {
if (sp == null) {
sp = new MultiValueParser(sr);
} else {
sp.ReInit(sr);
}
return sp;
}
/**
* make a clone of the properties in the argument
*
* @param vp
*/
protected VectorPrintProperties(VectorPrintProperties vp) {
super(vp);
init(vp);
}
private void init(VectorPrintProperties vp) {
help.putAll(vp.help);
observers.addAll(vp.observers);
propertyUrl = vp.propertyUrl;
propsFromArgs.addAll(vp.propsFromArgs);
urlString = vp.urlString;
}
@Override
public VectorPrintProperties clone() {
VectorPrintProperties vp = (VectorPrintProperties) super.clone();
init(vp);
return vp;
}
/**
*
* @return the part of the {@link #getUrlString() url} after the last {@link File#separator}
*/
@Override
public String getId() {
return urlString.substring(urlString.lastIndexOf(File.separatorChar) + 1);
}
/**
* not supported, write your own subclass to support this feature
*
* @param
* @param key
* @param defaultValue
* @param clazz
* @return
*/
@Override
public T getGenericProperty(String key, T defaultValue, Class clazz) {
Object o = null;
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
if (Boolean.class.equals(clazz)) {
o = Boolean.valueOf(getProperty(key));
} else if (Color.class.equals(clazz)) {
o = Color.decode(getProperty(key));
} else if (Byte.class.equals(clazz)) {
o = Byte.decode(getProperty(key));
} else if (Character.class.equals(clazz)) {
o = Character.valueOf(getProperty(key).charAt(0));
} else if (Short.class.equals(clazz)) {
o = Short.valueOf(getProperty(key));
} else if (Double.class.equals(clazz)) {
o = Double.valueOf(getProperty(key));
} else if (Float.class.equals(clazz)) {
o = Float.valueOf(getProperty(key));
} else if (Integer.class.equals(clazz)) {
o = Integer.valueOf(getProperty(key));
} else if (Long.class.equals(clazz)) {
o = Long.valueOf(getProperty(key));
} else if (String.class.equals(clazz)) {
o = getProperty(key);
} else if (URL.class.equals(clazz)) {
try {
o = new URL(getProperty(key));
} catch (MalformedURLException ex) {
throw new VectorPrintRuntimeException(ex);
}
} else if (String[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseStringValues(getProperty(key), doTrim));
} else if (URL[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseURLValues(getProperty(key),doTrim));
} else if (Float[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseFloatValues(getProperty(key),doTrim));
} else if (Double[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseDoubleValues(getProperty(key),doTrim));
} else if (Short[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseShortValues(getProperty(key),doTrim));
} else if (Character[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseCharValues(getProperty(key),doTrim));
} else if (Byte[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseByteValues(getProperty(key),doTrim));
} else if (Integer[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseFloatValues(getProperty(key),doTrim));
} else if (Long[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseLongValues(getProperty(key),doTrim));
} else if (Boolean[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseBooleanValues(getProperty(key),doTrim));
} else if (Color[].class.equals(clazz)) {
o = ArrayHelper.toArray(mvp.parseColorValues(getProperty(key),doTrim));
} else {
throw new VectorPrintRuntimeException(clazz.getName() + " not supported");
}
} catch (NumberFormatException numberFormatException) {
throw numberFormatException;
} catch (VectorPrintRuntimeException vectorPrintRuntimeException) {
throw vectorPrintRuntimeException;
} catch (ParseException parseException) {
throw new VectorPrintRuntimeException(parseException);
}
return (T) o;
}
public boolean isAllowArguments() {
return allowArguments;
}
public VectorPrintProperties setAllowArguments(boolean allowArguments) {
this.allowArguments = allowArguments;
return this;
}
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
mvp = MultipleValueParser.getInstance();
}
@Override
public Date getDateProperty(String key, Date defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return new SimpleDateFormat().parse(getProperty(key));
} catch (java.text.ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
@Override
public Date[] getDateProperties(String key, Date[] defaultValue) {
if (shouldUseDefault(key, defaultValue)) {
return defaultValue;
}
try {
return ArrayHelper.toArray(mvp.parseDateValues(getProperty(key),doTrim));
} catch (ParseException ex) {
throw new VectorPrintRuntimeException(ex);
}
}
private final Collection unused = new HashSet(25);
@Override
public Collection getUnusedKeys() {
for (Iterator it = unused.iterator(); it.hasNext();) {
String string = it.next();
if (!containsKey(string)) {
it.remove();
}
}
// cleanup here
return Collections.unmodifiableCollection(unused);
}
private final Collection notPresent = new HashSet(25);
@Override
public Collection getKeysNotPresent() {
return Collections.unmodifiableCollection(notPresent);
}
@PreDestroy
@Override
protected void finalize() throws Throwable {
log.info(String.format("Settings (%s) not used sofar: %s", getId(), getUnusedKeys()));
log.info(String.format("Settings (%s) not present, default used: %s", getId(), getKeysNotPresent()));
}
@Override
public List getCommentBeforeKey(String key) {
if (!commentBeforeKeys.containsKey(key)) {
commentBeforeKeys.put(key, new ArrayList(1));
}
return commentBeforeKeys.get(key);
}
@Override
public List getTrailingComment() {
return trailingComment;
}
@Override
public EnhancedMap addCommentBeforeKey(String key, String comment) {
if (!commentBeforeKeys.containsKey(key)) {
commentBeforeKeys.put(key, new ArrayList(1));
}
commentBeforeKeys.get(key).add(comment);
return this;
}
@Override
public EnhancedMap addTrailingComment(String comment) {
trailingComment.add(comment);
return this;
}
}