jsyntaxpane.util.Configuration Maven / Gradle / Ivy
/*
* Copyright 2008 Ayman Al-Sairafi [email protected]
*
* 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.
*/
package jsyntaxpane.util;
import java.awt.Color;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Wrapper around the Properties class with supprt for Heirarchical confogurations
* and more functionality.
*
* Except for the getXXXX methods, all other Map Interface methods operate on the
* current (non-parent) collection and do NOT touch the parent.
*
* @author Ayman Al-Sairafi
*/
public class Configuration implements Map {
/**
* Our parent
*/
Configuration parent;
/**
* Our Class for the configuration
*/
Class clazz;
/**
* The properties we have, excluding the parents defaults
*/
Map props;
/**
* Creates a new COnfiguration that uses parent as its parent
* Configuration.
*
* @param theClass
* @param parent
*/
public Configuration(Class theClass, Configuration parent) {
this(theClass);
this.parent = parent;
}
/**
* Creates an empty Configuration
* @param theClass
*/
public Configuration(Class theClass) {
super();
this.clazz = theClass;
}
/**
* Get a string from this object or one of its parents. If nothing
* is found, null is returned.
* If the Regex ${key} is found, then it is replaced by the value of that
* key within this (or parent's) map.
* Special COnstructs in ${}:
* class_path
will be replaced by the name of the
* Configuration (usually ClassName) with "." replaced by "/", and then
* converted to all lowercase
* class_simpleName
is replaced by class.SimpleName
* @param key
* @return
*/
public String getString(String key) {
String value = null;
if (props != null) {
value = props.get(key);
}
for (Configuration p = parent; value == null && p != null; p = p.parent) {
value = p.get(key);
}
// if we have a parent, then perform ${} replacements
if (value != null) {
Matcher m = PARENT_KEY.matcher(value);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String p_key = m.group(1);
String p_value = getString(p_key);
if (p_key.equals("class_path")) {
p_value = clazz.getName().replace(".", "/").toLowerCase();
} else if (p_key.equals("class_simpleName")) {
p_value = clazz.getSimpleName();
} else {
p_value = getString(p_key);
if (p_value == null) {
Logger.getLogger(this.getClass().getName()).warning(
"no value for ${" + p_key +
"} is defined");
}
}
m.appendReplacement(sb, p_value);
}
m.appendTail(sb);
value = sb.toString();
}
return value;
}
/**
* Returns a non-null value either by traversing the current
* and parent(s) map, or returning the defaultValue
* @param key
* @param defaultValue
* @throws NullPointerException if defaultValue is null
* @return
*/
public String getString(String key, String defaultValue) {
if (defaultValue == null) {
throw new NullPointerException("defaultValue cannot be null");
}
String value = getString(key);
return (value == null) ? defaultValue : value;
}
/**
* Gets an integer from the properties. If number cannot be found
* or if it cannot be decoded, the default is returned
* The integer is decoded using {@link Integer.decode(String)}
* @param key
* @param Default
* @return
*/
public int getInteger(String key, int Default) {
String v = getString(key);
if (v == null) {
return Default;
}
try {
int i = Integer.decode(v);
return i;
} catch (NumberFormatException e) {
LOG.log(Level.WARNING, null, e);
return Default;
}
}
/**
* Returns a String[] of the comma separated items in the value.
*
* Does NOT return null. If the key is not found,
* then an empty string array is returned. So the return of this method
* can always be used directly in a foreach loop
* @param key
* @return non-null String[]
*/
public String[] getPropertyList(String key) {
String v = getString(key);
if (v == null) {
return EMPTY_LIST;
} else {
return COMMA_SEPARATOR.split(v);
}
}
/**
* Returns a boolean from the configuration
* @param key
* @param Default
* @return
*/
public boolean getBoolean(String key, boolean Default) {
String b = getString(key);
if (b == null) {
return Default;
}
return Boolean.parseBoolean(b.trim());
}
/**
* return the Color that has the given key or the Default
* @param key
* @param Default
* @return
*/
public Color getColor(String key, Color Default) {
String c = getString(key);
if (c == null) {
return Default;
} else {
try {
return Color.decode(c);
} catch (NumberFormatException e) {
return Default;
}
}
}
@SuppressWarnings("unchecked")
@Override
public void putAll(Map config) {
if (props == null) {
props = new HashMap();
}
props.putAll(config);
}
/**
* Returns ALL property names from this Configuration's parents and
* this Configuration. As usual, parents are added first so they
* are overriden by children.
*
* @return Set of all String keys in this and parents
*/
public Set stringPropertyNames() {
Set propNames = new HashSet();
if (parent != null) {
propNames.addAll(parent.stringPropertyNames());
}
if (props != null) {
for (Object k : props.keySet()) {
propNames.add(k.toString());
}
}
return propNames;
}
@Override
public String put(String key, String value) {
if (props == null) {
props = new HashMap();
}
Object old = props.put(key, value);
return (old == null) ? null : old.toString();
}
@Override
public int size() {
return (props == null) ? 0 : props.size();
}
@Override
public boolean isEmpty() {
return (props == null) ? true : props.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return (props == null) ? false : props.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return (props == null) ? false : props.containsValue(value);
}
@Override
public String get(Object key) {
return (props == null) ? null : props.get(key);
}
@Override
public String remove(Object key) {
if (props == null) {
return null;
}
Object old = props.remove(key);
return (old == null) ? null : old.toString();
}
@Override
public void clear() {
if (props != null) {
props.clear();
}
}
@Override
@SuppressWarnings("unchecked")
public Set keySet() {
if (props == null) {
return Collections.EMPTY_SET;
} else {
return props.keySet();
}
}
@Override
@SuppressWarnings("unchecked")
public Collection values() {
if (props == null) {
return Collections.EMPTY_SET;
} else {
return props.values();
}
}
@Override
@SuppressWarnings("unchecked")
public Set> entrySet() {
if (props == null) {
return Collections.EMPTY_SET;
} else {
return props.entrySet();
}
}
@Override
public String toString() {
return "Configuration " + clazz + " for " + parent;
}
/**
* Utility class to hold data for {@link getKeys} method.
*/
public static class StringKeyMatcher {
private StringKeyMatcher(String key, Matcher matcher, String group1, String value) {
this.key = key;
this.matcher = matcher;
this.group1 = group1;
this.value = value;
}
/**
* The full key matched
*/
public final String key;
/**
* matcher instance for the key
*/
public final Matcher matcher;
/**
* Matched group 1. Could be null if no Group 1 is found
*/
public final String group1;
/**
* Value for key matched
*/
public final String value;
}
/**
* Obtain a set of all keys (and parent's keys) that match the given pattern.
* If no keys match, then an empty set is returned.
* Use this instead of the {@link stringPropertyNames}
* @param pattern
* @return
*/
public Set getKeys(Pattern pattern) {
Set matched = new HashSet();
Set all = stringPropertyNames();
for (String k : all) {
Matcher m = pattern.matcher(k);
if (m.matches()) {
StringKeyMatcher skm = new StringKeyMatcher(k, m,
(m.groupCount() >= 1) ? m.group(1) : null,
getString(k));
matched.add(skm);
}
}
return matched;
}
public static final String[] EMPTY_LIST = new String[0];
public static final Pattern COMMA_SEPARATOR = Pattern.compile("\\s*,\\s*");
private static Pattern PARENT_KEY = Pattern.compile("\\$\\{(\\w+)\\}");
private static final Logger LOG = Logger.getLogger(Configuration.class.getName());
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy