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

webit.script.util.props.PropsData Maven / Gradle / Ivy

There is a newer version: 1.5.2
Show newest version
// Copyright (c) 2003-2013, Jodd Team (jodd.org). All Rights Reserved.
package webit.script.util.props;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import webit.script.util.StringUtil;

/**
 * Props data storage for base and profile properties. Properties can be
 * lookuped and modified only through this class.
 */
class PropsData implements Cloneable {

    private static final int MAX_INNER_MACROS = 100;
    private static final String APPEND_SEPARATOR = ",";
    private final HashMap baseProperties;
    private final HashMap> profileProperties;
    /**
     * If set, duplicate props will be appended to the end, separated by comma.
     */
    private final static boolean appendDuplicateProps = false;
//	/**
//	 * When set, missing macros will be replaces with an empty string.
//	 */
//	private boolean ignoreMissingMacros;
    private final static boolean skipEmptyProps = true;

    PropsData() {
        this.baseProperties = new HashMap();
        this.profileProperties = new HashMap>();
    }

//	protected PropsData(final HashMap properties, final HashMap> profiles) {
//		this.baseProperties = properties;
//		this.profileProperties = profiles;
//	}
//
//	@Override
//	public PropsData clone() {
//		final HashMap newBase = new HashMap();
//		final HashMap> newProfiles = new HashMap>();
//
//		newBase.putAll(baseProperties);
//		for (final Map.Entry> entry : profileProperties.entrySet()) {
//			final Map map = new HashMap(entry.getValue().size());
//			map.putAll(entry.getValue());
//			newProfiles.put(entry.getKey(), map);
//		}
//
//		final PropsData pd = new PropsData(newBase, newProfiles);
//		pd.appendDuplicateProps = appendDuplicateProps;
//		pd.ignoreMissingMacros = ignoreMissingMacros;
//		pd.skipEmptyProps = skipEmptyProps;
//		return pd;
//	}
    // ---------------------------------------------------------------- misc
    /**
     * Puts key-value pair into the map, with respect of appending duplicate
     * properties
     */
    private void put(final Map map, final String key, final String value, final boolean append) {
        String realValue = value;
        if (append || appendDuplicateProps) {
            PropsValue pv = map.get(key);
            if (pv != null) {
                realValue = StringUtil.concat(pv.value, APPEND_SEPARATOR, realValue);
            }
        }
        map.put(key, new PropsValue(realValue));
    }

    // ---------------------------------------------------------------- properties
//    /**
//     * Counts base properties.
//     */
//    public int countBaseProperties() {
//        return baseProperties.size();
//    }
    /**
     * Adds base property.
     */
    void putBaseProperty(final String key, final String value, final boolean append) {
        put(baseProperties, key, value, append);
    }

    /**
     * Returns base property or
     * null if it doesn't exist.
     */
    PropsValue getBaseProperty(final String key) {
        return baseProperties.get(key);
    }

    // ---------------------------------------------------------------- profiles
//	/**
//	 * Counts profile properties. Note: this method is not
//	 * that easy on execution.
//	 */
//	public int countProfileProperties() {
//		final HashSet profileKeys = new HashSet();
//
//		for (final Map map : profileProperties.values()) {
//			for (final String key : map.keySet()) {
//				if (!baseProperties.containsKey(key)) {
//					profileKeys.add(key);
//				}
//			}
//		}
//		return profileKeys.size();
//	}
    /**
     * Adds profile property.
     */
    void putProfileProperty(final String key, final String value, final String profile, final boolean append) {
        Map map = profileProperties.get(profile);
        if (map == null) {
            map = new HashMap();
            profileProperties.put(profile, map);
        }
        put(map, key, value, append);
    }

//	/**
//	 * Returns profile property.
//	 */
//	public PropsValue getProfileProperty(final String profile, final String key) {
//		final Map profileMap = profileProperties.get(profile);
//		if (profileMap == null) {
//			return null;
//		}
//		return profileMap.get(key);
//	}
    // ---------------------------------------------------------------- lookup
    /**
     * Lookup props value through profiles and base properties.
     */
    private String lookupValue(final String key, final String... profiles) {
        if (profiles != null) {
            nextprofile:
            for (String profile : profiles) {
                while (true) {
                    final Map profileMap = this.profileProperties.get(profile);
                    if (profileMap == null) {
                        continue nextprofile;
                    }
                    final PropsValue value = profileMap.get(key);
                    if (value != null) {
                        return value.getValue();
                    }
                    final int ndx = profile.lastIndexOf('.');
                    if (ndx == -1) {
                        break;
                    }
                    profile = profile.substring(0, ndx);
                }
            }
        }
        final PropsValue value = getBaseProperty(key);
        return value == null ? null : value.getValue();
    }

    // ---------------------------------------------------------------- resolve
    /**
     * Resolves all macros in this props set. Called once on initialization.
     */
    void resolveMacros() {
        // create string template pareser that will be used internally
        //StringTemplateParser stringTemplateParser = new StringTemplateParser();
        //stringTemplateParser.setResolveEscapes(false);

//		if (!ignoreMissingMacros) {
//			stringTemplateParser.setReplaceMissingKey(false);
//		} else {
//			stringTemplateParser.setReplaceMissingKey(true);
//			stringTemplateParser.setMissingKeyReplacement("");
//		}

        // start parsing
        int loopCount = 0;
        while (loopCount++ < MAX_INNER_MACROS) {
            boolean replaced = resolveMacros(this.baseProperties, null);

            for (final Map.Entry> entry : profileProperties.entrySet()) {
                String profile = entry.getKey();

                replaced = resolveMacros(entry.getValue(), profile) || replaced;
            }

            if (!replaced) {
                break;
            }
        }
    }

    private boolean resolveMacros(final Map map, final String profile) {
        boolean replaced = false;

        final StringTemplateParser.MacroResolver macroResolver = new StringTemplateParser.MacroResolver() {
            public String resolve(String macroName) {
                return lookupValue(macroName, profile);
            }
        };

        Iterator> iterator = map.entrySet().iterator();

        while (iterator.hasNext()) {
            Map.Entry entry = iterator.next();
            final PropsValue pv = entry.getValue();
            final String newValue = StringTemplateParser.parse(pv.value, macroResolver);

            if (!newValue.equals(pv.value)) {
                if (skipEmptyProps) {
                    if (newValue.length() == 0) {
                        iterator.remove();
                        replaced = true;
                        continue;
                    }
                }

                pv.resolved = newValue;
                replaced = true;
            } else {
                pv.resolved = null;
            }
        }
        return replaced;
    }

    // ---------------------------------------------------------------- extract
    /**
     * Extract props to target map.
     */
    void extract(final Map target, final String[] profiles) {
        if (profiles != null) {
            for (String profile : profiles) {
                while (true) {
                    final Map map = this.profileProperties.get(profile);
                    if (map != null) {
                        extractMap(target, map);
                    }

                    final int ndx = profile.indexOf('.');
                    if (ndx == -1) {
                        break;
                    }
                    profile = profile.substring(0, ndx);
                }
            }
        }
        extractMap(target, this.baseProperties);
    }

    @SuppressWarnings("unchecked")
    private void extractMap(final Map target, final Map map) {
        for (Map.Entry entry : map.entrySet()) {
            final String key = entry.getKey();

            if (!target.containsKey(key)) {
                target.put(key, entry.getValue().getValue());
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy