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

com.eva.properties.MapProperties Maven / Gradle / Ivy

Go to download

Advanced properties with object factories, references and inheritance.

There is a newer version: 0.3
Show newest version
/*
 * $Id: MapProperties.java 42 2007-02-27 21:27:41Z 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.IOException;
import java.io.StringReader;
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.
 * 
 * @author Max Antoni
 * @version $Revision: 42 $
 */
class MapProperties extends Properties implements Map {
    private static final String JOKER = "*";
    private static final String SUPER = "super";
    private static final String SYSTEM = "system";
    private Map map;

    MapProperties(Properties inParent) {
        this(inParent, new LinkedHashMap());
        
    }
    
    MapProperties(Properties inParent, Map inMap) {
        super(inParent);
        map = inMap;
    }
    
    /* 
     * @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);
    }

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

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

    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;
    }
    
    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) {
                return checkDelegate(inContext, inKey);
            }
            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);
    }
    
    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(this);
                }
                catch(NumberFormatException e) {
                    value = new MapProperties(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 Properties) {
            ((Properties) inValue).setParent(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(
                    new StringReader(systemProperty), false);
        }
        catch(PropertiesException e) {
            // Cannot be parsed
            value = systemProperty;
        }
        catch(IOException e) {
            throw new PropertiesException(e.getMessage());
        }
        if(value instanceof String) {
            return inContext.replaceString((String) value);
        }
        if(value instanceof Replaceable) {
            return inContext.replaceReplaceable((Replaceable) value);
        }
        return value;
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy