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

src.main.java.com.eva.properties.MapProperties Maven / Gradle / Ivy

/*
 * $Id: MapProperties.java 109 2007-03-24 14:55:03Z max $
 * 
 * Copyright (c) 2006-2007 Maximilian Antoni. All rights reserved.
 * 
 * This software is licensed as described in the file LICENSE.txt, which you
 * should have received as part of this distribution. The terms are also
 * available at http://www.maxantoni.de/projects/eva-properties/license.txt.
 */
package com.eva.properties;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * is a map based properties implementation. This map implementation uses a
 * LinkedHashMap internally.
 * 
 * @author Max Antoni
 * @version $Revision: 109 $
 */
public class MapProperties extends Properties implements Map {
    public static final String JOKER = "*";
    public static final String SUPER = "super";
    public static final String SYSTEM = "system";
    private Map map = new LinkedHashMap();

    /**
     * creates a copy of the given properties map.
     * 
     * @param inMap the properties map.
     * @return the copy of the properties map.
     * @throws IllegalArgumentException if the map was not a properties map.
     */
    public static Map copy(Map inMap) {
        if(inMap == null) {
            throw new NullPointerException();
        }
        if(inMap instanceof MapProperties) {
            Properties properties = (Properties) inMap;
            return (MapProperties) properties.copy(properties.getParent());
        }
        throw new IllegalArgumentException("Not a properties map.");
    }
    
    /**
     * Creates an empty map properties object with no parent.
     */
    public MapProperties() {
        // Empty default constructor.
    }
    
    public MapProperties(ClassLoader inClassLoader, String inPath)
            throws PropertiesException, FileNotFoundException {
        if(inClassLoader == null) {
            throw new NullPointerException("ClassLoader is null.");
        }
        if(inPath == null) {
            throw new NullPointerException("Path is null.");
        }
        PropertiesParser.readMap(this, new DataSource(inClassLoader, inPath));
    }
    
    /**
     * creates a map properties object and initializes it with the the
     * configuration provided by the data source.
     * 
     * @param inDataSource the data source providing the configuration.
     * @throws PropertiesException
     */
    public MapProperties(DataSource inDataSource) throws PropertiesException {
        if(inDataSource == null) {
            throw new NullPointerException("DataSource is null.");
        }
        PropertiesParser.readMap(this, inDataSource);
    }
    
    /**
     * creates a map properties object and initializes it with the the
     * configuration provided by the input stream.
     * 
     * @param inStream the input stream providing the configuration.
     * @throws PropertiesException
     */
    public MapProperties(InputStream inStream) throws PropertiesException {
        if(inStream == null) {
            throw new NullPointerException("Stream is null.");
        }
        PropertiesParser.readMap(this, new InputStreamReader(inStream));
    }
    
    public MapProperties(Map inMap) {
        if(inMap == null) {
            throw new NullPointerException("Map is null.");
        }
        if(inMap instanceof Properties) {
            setParent((Properties) inMap);
        }
        else {
            map.putAll(inMap);
        }
    }
    
    /**
     * creates a map properties object with the given parent properties.
     * 
     * @param inParent the parent properties.
     */
    public MapProperties(Properties inParent) {
        super(inParent);
    }
    
    /**
     * creates a map properties object and initializes it with the the
     * configuration provided by the reader.
     * 
     * @param inReader the reader providing the configuration.
     * @throws PropertiesException
     */
    public MapProperties(Reader inReader) throws PropertiesException {
        if(inReader == null) {
            throw new NullPointerException("Reader is null.");
        }
        PropertiesParser.readMap(this, inReader);
    }
    
    public MapProperties(String inPath) throws PropertiesException,
            FileNotFoundException {
        if(inPath == null) {
            throw new NullPointerException("Path is null.");
        }
        PropertiesParser.readMap(this, new DataSource(inPath));
    }
    
    public MapProperties(String[] inParameters) {
        for(int i = 0; i < inParameters.length; i++) {
            int p = inParameters[i].indexOf('=');
            if(p == -1) {
                put(inParameters[i], Null.INSTANCE);
            }
            else {
                String argument = inParameters[i].substring(p + 1);
                Object value;
                try {
                    value = PropertiesParser.readObject(argument);
                }
                catch(PropertiesException e) {
                     throw new PropertiesException("Cannot parse argument: "
                            + argument, e);
                }
                put(inParameters[i].substring(0, p), value);
            }
        }
    }
    
    /* 
     * @see java.util.Map#clear()
     */
    public void clear() {
        map.clear();
    }
    
    /* 
     * @see java.util.Map#containsKey(java.lang.Object)
     */
    public boolean containsKey(Object inKey) {
        return map.containsKey(inKey);
    }
    
    /* 
     * @see java.util.Map#containsValue(java.lang.Object)
     */
    public boolean containsValue(Object inValue) {
        return map.containsValue(inValue);
    }

    /* 
     * @see java.util.Map#entrySet()
     */
    public Set entrySet() {
        return map.entrySet();
    }
    
    /* 
     * @see java.util.Map#get(java.lang.Object)
     */
    public Object get(Object inKey) {
        try {
            return new Context(this).lookup((String) inKey);
        }
        catch(PropertiesException e) {
            throw new PropertiesException("Cannot resolve \"" + inKey
                    + "\", " + e.getMessage(), e);
        }
    }

    /* 
     * @see java.util.Map#isEmpty()
     */
    public boolean isEmpty() {
        return map.isEmpty();
    }

    /* 
     * @see java.util.Map#keySet()
     */
    public Set keySet() {
        return map.keySet();
    }

    /* 
     * @see java.util.Map#put(java.lang.Object, java.lang.Object)
     */
    public Object put(Object inKey, Object inValue) {
        return putProperty(new Context(this), (String) inKey, inValue);
    }

    /* 
     * @see java.util.Map#putAll(java.util.Map)
     */
    public void putAll(Map inMap) {
        for(Iterator i = inMap.keySet().iterator(); i.hasNext();) {
            Object key = i.next();
            put(key, inMap.get(key));
        }
    }

    /* 
     * @see java.util.Map#remove(java.lang.Object)
     */
    public Object remove(Object inKey) {
        String key = (String) inKey;
        int p = key.lastIndexOf('.');
        if(p > 0) {
            String leftKey = key.substring(0, p);
            String removeKey = key.substring(p + 1);
            Object value = get(leftKey);
            if(value instanceof Map) {
                return ((Map) value).remove(removeKey);
            }
            throw new PropertiesException("Cannot remove " + key + ", "
                    + leftKey + " is not a map.");
        }
        return map.remove(key);
    }

    public void setSuper(Properties inProperties) {
        map.put(SUPER, inProperties);
    }

    /* 
     * @see java.util.Map#size()
     */
    public int size() {
        return map.size();
    }

    /* 
     * @see java.util.Map#values()
     */
    public Collection values() {
        return map.values();
    }
    
    /**
     * returns the internal map.
     * 
     * @return the internal map.
     */
    public Map getMap() {
        return map;
    }

    public boolean containsKeyInternal(String inKey) {
        return map.containsKey(inKey);
    }
    
    /*
     * @see com.eva.properties.Properties#copy(com.eva.properties.Properties)
     */
    Properties copy(Properties inParent) {
        MapProperties newProperties = new MapProperties(inParent);
        for(Iterator i = map.keySet().iterator(); i.hasNext();) {
            String key = (String) i.next();
            Object value = map.get(key);
            if(value instanceof Properties) {
                newProperties.map.put(key, ((Properties) value)
                        .copy(newProperties));
            }
            else if(value instanceof Replaceable) {
                newProperties.map.put(key, ((Replaceable) value)
                        .copy(newProperties));
            }
            else {
                newProperties.map.put(key, value);
            }
        }
        return newProperties;
    }
    
    public Object getInternal(String inKey) {
        return map.get(inKey);
    }
    
    /*
     * @see com.eva.properties.AbstractProperties#getProperty(
     *      com.eva.properties.Context, java.lang.String)
     */
    Object getProperty(Context inContext, String inKey)
            throws PropertiesException {
        int p = inKey.indexOf('.');
        if(p > 0) {
            String localKey = inKey.substring(0, p);
            String rightKey = inKey.substring(p + 1);
            if(localKey.equals(JOKER)) {
                return createJokerMap(inContext, rightKey);
            }
            if(localKey.equals(SYSTEM)) {
                return getSystemProperty(inContext, rightKey);
            }
            Object value = map.get(localKey);
            if(value == null) {
                value = checkDelegate(inContext, localKey);
            }
            if(value instanceof Replaceable) {
                value = inContext.replaceReplaceable((Replaceable) value);
            }
            if(value instanceof Properties) {
                Properties inner = (Properties) value;
                value = inner.getProperty(new Context(inContext, inner),
                        rightKey);
                if(value != null) {
                    return value;
                }
            }
            return checkDelegate(inContext, inKey);
        }
        Object value = map.get(inKey);
        if(value == null) {
            value = map.get(JOKER);
            if(value == null) {
                value = checkDelegate(inContext, inKey);
                if(value == null) {
                    return null;
                }
            }
        }
        return inContext.replace(value);
    }

    public void putInternal(String inKey, Object inValue) {
        map.put(inKey, inValue);
    }
    
    /*
     * @see com.eva.properties.Properties#putProperty(
     *      com.eva.properties.Context, java.lang.String, java.lang.Object)
     */
    Object putProperty(Context inContext, String inKey, Object inValue) {
        int p = inKey.indexOf('.');
        if(p > 0) {
            String left = inKey.substring(0, p);
            if(left.equals(SUPER)) {
                throw new PropertiesException("Illegal key \"" + SUPER + "\".");
            }
            String right = inKey.substring(p + 1);
            Object value = map.get(left);
            if(value == null) {
                p = right.indexOf('.');
                String index = p > 0 ? right.substring(p + 1) : right;
                try {
                    Integer.parseInt(index);
                    value = new ListProperties((Properties) this);
                }
                catch(NumberFormatException e) {
                    value = new MapProperties((Properties) this);
                }
                map.put(left, value);
            }
            else if(value instanceof Replaceable) {
                value = inContext.replaceReplaceable((Replaceable) value);
            }
            if(value instanceof Properties) {
                Properties inner = (Properties) value;
                return inner.putProperty(new Context(inContext, inner),
                        right, inValue);
            }
            throw new PropertiesException("Cannot put " + inKey + ", " + left
                    + " is not a list or a map.");
        }
        if(inKey.equals(SUPER)) {
            if(!(inValue instanceof String) && !(inValue instanceof Reference)
                    && !(inValue instanceof Proxy)
                    && !(inValue instanceof Properties)) {
                throw new PropertiesException("Value for " + SUPER
                        + " must be either null, a path, a reference, "
                        + "a proxy or a map.");
            }
        }
        else if(inValue instanceof MapProperties) {
            MapProperties m = (MapProperties) inValue;
            for(Iterator i = m.keySet().iterator(); i.hasNext();) {
                String key = (String) i.next();
                putProperty(inContext, inKey + "." + key, m.get(key));
            }
            return null;
        }
        else if(inValue instanceof Properties) {
            inValue = ((Properties) inValue).copy(this);
        }
        return map.put(inKey, inValue);
    }

    /* 
     * @see com.eva.properties.Properties#write(com.eva.properties.Writer)
     */
    void write(Writer inoutWriter) {
        inoutWriter.append("{\n");
        inoutWriter.increaseIndentation();
        for(Iterator i = map.keySet().iterator(); i.hasNext();) {
            inoutWriter.appendIndentation();
            String key = (String) i.next();
            inoutWriter.append(key);
            inoutWriter.append(": ");
            inoutWriter.write(map.get(key));
        }
        inoutWriter.decreaseIndentation();
        inoutWriter.appendIndentation();
        inoutWriter.append("}\n");
    }
    
    private Object checkDelegate(Context inContext, String inKey)
            throws PropertiesException {
        Object superValue = map.get(SUPER);
        if(superValue == null) {
            return null;
        }
        Properties delegate = getDelegate(inContext, superValue);
        return delegate.getProperty(inContext, inKey);
    }

    private Object createJokerMap(Context inContext, String inRightKey)
            throws PropertiesException {
        MapProperties properties = new MapProperties(getParent());
        for(Iterator i = map.keySet().iterator(); i.hasNext();) {
            String key = (String) i.next();
            Object value = map.get(key);
            if(value instanceof Properties) {
                value = ((Properties) value).getProperty(inContext,
                        inRightKey);
                if(value != null) {
                    properties.putInternal(key, value);
                }
            }
        }
        return properties;
    }

    private Properties getDelegate(Context inContext, Object inSuperValue)
            throws PropertiesException {
        if(inSuperValue instanceof Reference) {
            String reference = ((Reference) inSuperValue).getReference();
            Properties delegate = (Properties) inContext.getParent().lookup(
                    reference);
            if(delegate == null) {
                throw new PropertiesException("Invalid super reference, \""
                        + reference + "\" is null.");
            }
            return delegate;
        }
        if(inSuperValue instanceof Proxy) {
            return (Properties) ((Proxy) inSuperValue).replace(inContext);
        }
        if(inSuperValue instanceof Properties) {
            return (Properties) inSuperValue;
        }
        if(SYSTEM.equals(inSuperValue)) {
            return SystemProperties.INSTANCE;
        }
        throw new PropertiesException("Invalid super: " + inSuperValue);
    }

    private Object getSystemProperty(Context inContext, String inProperty) {
        String systemProperty = System.getProperty(inProperty);
        if(systemProperty == null) {
            return null;
        }
        Object value;
        try {
            value = PropertiesParser.readObject(systemProperty);
        }
        catch(PropertiesException e) {
            // Cannot be parsed
            value = systemProperty;
        }
        if(value instanceof String) {
            return inContext.replaceString((String) value);
        }
        if(value instanceof Replaceable) {
            return inContext.replaceReplaceable((Replaceable) value);
        }
        return value;
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy