All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jsyntaxpane.util.Configuration Maven / Gradle / Ivy

There is a newer version: 5.3.2
Show newest version
/*
 * 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