Package org.apache.felix.sigil.common.config

Source Code of org.apache.felix.sigil.common.config.BldConfig

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 org.apache.felix.sigil.common.config;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import org.apache.felix.sigil.common.util.QuoteUtil;

public class BldConfig implements Cloneable
{
    // control properties
    public static final String C_BUNDLES = "-bundles";
    public static final String C_REPOSITORIES = "-repositories";
    public static final String C_REPOSITORY_PATH = "-repositorypath";

    // string properties
    public static final String S_ACTIVATOR = "-activator";
    public static final String S_DEFAULTS = "-defaults";
    public static final String S_SINGLETON = "-singleton";
    public static final String S_ID = "id";
    public static final String S_SYM_NAME = "name";
    public static final String S_VERSION = "version";
    public static final String[] STRING_KEYS = { S_ACTIVATOR, S_DEFAULTS, S_ID,
            S_SYM_NAME, S_VERSION, S_SINGLETON };

    // list properties
    public static final String L_CONTENTS = "-contents";
    public static final String L_SRC_CONTENTS = "-sourcedirs";
    public static final String L_RESOURCES = "-resources";
    public static final String[] LIST_KEYS = { L_CONTENTS, L_SRC_CONTENTS, L_RESOURCES };

    // map properties
    public static final String M_EXPORTS = "-exports";
    public static final String M_IMPORTS = "-imports";
    public static final String M_REQUIRES = "-requires";
    public static final String M_FRAGMENT = "-fragment";
    public static final String M_LIBS = "-libs";
    public static final String[] MAP_KEYS = { M_EXPORTS, M_IMPORTS, M_REQUIRES,
            M_FRAGMENT, M_LIBS };

    // property properties
    public static final String P_HEADER = "header";
    public static final String P_OPTION = "option";
    public static final String P_PACKAGE_VERSION = "package";
    public static final String P_BUNDLE_VERSION = "bundle";
    public static final String[] PROP_KEYS = { P_HEADER, P_OPTION, P_PACKAGE_VERSION,
            P_BUNDLE_VERSION };

    // private constants
    private static final String LIST_REGEX = ",\\s*";
    private static final String MAPATTR_REGEX = ";\\s*";
    private static final String MAPATTR_SEP = ";";
    private static final String SUBKEY_SEP = ";";
   
    // configuration is stored in typed maps
    private Map<String, String> string = new TreeMap<String, String>();
    private Map<String, List<String>> list = new TreeMap<String, List<String>>();
    private Map<String, Map<String, Map<String, String>>> map = new TreeMap<String, Map<String, Map<String, String>>>();
    private Map<String, BldConfig> config = new TreeMap<String, BldConfig>();
    private Map<String, Properties> property = new TreeMap<String, Properties>();

    // default config - not modified or saved
    private BldConfig dflt;

    private Properties unknown = new Properties();
    private String comment = "";
    private final URI location;

    public BldConfig()
    {
        this.location = null;
    }
   
    public BldConfig(URI loc)
    {
        this.location = loc;
    }

    public BldConfig(Properties p) throws IOException
    {
        this.location = null;
        merge(p);
    }

    public void setDefault(BldConfig dflt)
    {
        this.dflt = dflt;
    }

    public void setComment(String comment)
    {
        this.comment = comment;
    }

    public Properties getUnknown()
    {
        return unknown;
    }

    /**
     * @param name
     * @return
     */
    public URI getDefinition(String id, String key)
    {
        URI def = null;
        if (dflt != null)
            def = dflt.getDefinition(id, key);

        if ( def == null ) {
            if (property.containsKey(key)) {
                def = location;
            }
            else if (id != null && config.containsKey(id))
            {
                Properties p2 = config.get(id).getProps(null, key);
                if (p2 != null)
                    def = location;
            }
        }

        return def;
    }

    public String getString(String id, String key)
    {
        if (id != null && config.containsKey(id))
        {
            String value = config.get(id).getString(null, key);
            if (value != null)
                return value;
        }
        return string.containsKey(key) ? string.get(key)
            : (dflt != null ? dflt.getString(id, key) : null);
    }

    public List<String> getList(String id, String key)
    {
        if (id != null && config.containsKey(id))
        {
            List<String> value = config.get(id).getList(null, key);
            if (value != null)
                return value;
        }
        return list.containsKey(key) ? list.get(key) : (dflt != null ? dflt.getList(id,
            key) : Collections.<String> emptyList());
    }

    public Map<String, Map<String, String>> getMap(String id, String key)
    {
        if (id != null && config.containsKey(id))
        {
            Map<String, Map<String, String>> value = config.get(id).getMap(null, key);
            if (value != null)
                return value;
        }
        return map.containsKey(key) ? map.get(key) : (dflt != null ? dflt.getMap(id, key)
            : Collections.<String, Map<String, String>> emptyMap());
    }

    public void setString(String id, String key, String value)
    {
        if (!value.equals(getString(id, key)))
        {
            if (id != null)
            {
                if (!config.containsKey(id))
                    config.put(id, new BldConfig());
                config.get(id).setString(null, key, value);
            }
            else
            {
                String dval = (dflt != null ? dflt.getString(null, key) : null);
                if (value.equals("") && (dval == null || dval.equals("")))
                {
                    string.remove(key);
                }
                else
                {
                    string.put(key, value);
                }
            }
        }
    }

    public void setList(String id, String key, List<String> value)
    {
        if (!value.equals(getList(id, key)))
        {
            if (id != null)
            {
                if (!config.containsKey(id))
                    config.put(id, new BldConfig());
                config.get(id).setList(null, key, value);
            }
            else if (value.isEmpty()
                && (dflt == null || dflt.getList(null, key).isEmpty()))
            {
                list.remove(key);
            }
            else
            {
                list.put(key, value);
            }
        }
    }

    public void setMap(String id, String key, Map<String, Map<String, String>> value)
    {
        if (!value.equals(getMap(id, key)))
        {
            if (id != null)
            {
                if (!config.containsKey(id))
                    config.put(id, new BldConfig());
                config.get(id).setMap(null, key, value);
            }
            else if (value.isEmpty()
                && (dflt == null || dflt.getMap(null, key).isEmpty()))
            {
                map.remove(key);
            }
            else
            {
                map.put(key, value);
            }
        }
    }

    public Properties getProps(String id, String key)
    {
        // merge main and sub properties
        Properties props = new Properties();

        if (dflt != null)
            props.putAll(dflt.getProps(id, key));

        if (property.containsKey(key))
            props.putAll(property.get(key));

        if (id != null && config.containsKey(id))
        {
            Properties p2 = config.get(id).getProps(null, key);
            if (p2 != null)
                props.putAll(p2);
        }

        return props;
    }

    // only sets one property at a time
    public void setProp(String id, String key, String k2, String v2)
    {
        if (v2 == null)
            return;
        Properties props = getProps(id, key);
        if (!v2.equals(props.getProperty(key)))
        {
            if (id != null)
            {
                if (!config.containsKey(id))
                    config.put(id, new BldConfig());
                config.get(id).setProp(null, key, k2, v2);
            }
            else
            {
                if (property.containsKey(key))
                {
                    property.get(key).put(k2, v2);
                }
                else
                {
                    Properties value = new Properties();
                    value.put(k2, v2);
                    property.put(key, value);
                }
            }
        }
    }

    /**
     * write config in Property file format.
     * This allows us to make it prettier than Properties.store().
     */
    public void write(final PrintWriter out)
    {
        out.println(comment);

        // Note: don't add date stamp, or file will differ each time it's saved.
        out.println("# sigil project file, saved by plugin.\n");

        dump("", new Properties()
        {
            private static final long serialVersionUID = 1L; //appease eclipse

            @Override
            public Object put(Object key, Object value)
            {
                if (value instanceof String)
                {
                    out.println(key + ": " + value);
                    out.println("");
                }
                else if (value instanceof List<?>)
                {
                    out.println(key + ": \\");
                    for (Object k : (List<?>) value)
                    {
                        out.println("\t" + k + ", \\");
                    }
                    out.println("");
                }
                else if (value instanceof Map<?,?>)
                {
                    out.println(key + ": \\");
                    StringBuilder b = new StringBuilder();
                    for (Map.Entry<?, ?> e : ((Map<?, ?>) value).entrySet())
                    {
                        b.append("\t");
                        b.append(e.getKey());
                        Map<?, ?> v = (Map<?, ?>) e.getValue();
                        if (!v.isEmpty())
                        {
                            for (Map.Entry<?, ?> e2 : v.entrySet())
                            {
                                b.append(MAPATTR_SEP);
                                b.append(e2.getKey());
                                b.append("=");
                                String v2 = e2.getValue().toString();
                                if (v2.contains(","))
                                {
                                    b.append("\"");
                                    b.append(v2);
                                    b.append("\"");
                                }
                                else
                                {
                                    b.append(v2);
                                }
                            }
                        }
                        b.append(", \\\n");
                    }
                    out.println(b.toString());
                }
                return null;
            }
        });
        out.println("# end");
    }

    /**
     * dump config in pseudo Properties format.
     * Note: some values are not Strings (they're List<String>).
     */
    private void dump(String prefix, Properties p)
    {
        for (String key : string.keySet())
        {
            p.put(prefix + key, string.get(key));
        }

        for (String key : list.keySet())
        {
            List<String> list2 = list.get(key);
            p.put(prefix + key, list2);
        }

        for (String key : map.keySet())
        {
            Map<String, Map<String, String>> map2 = map.get(key);
            p.put(prefix + key, map2);
        }

        for (String key : property.keySet())
        {
            Properties props = property.get(key);
            for (Object k2 : props.keySet())
            {
                p.put(prefix + key + SUBKEY_SEP + k2, props.get(k2));
            }
        }

        for (String key : config.keySet())
        {
            BldConfig config2 = config.get(key);
            config2.dump(key + SUBKEY_SEP + prefix, p);
        }

        for (Object key : unknown.keySet())
        {
            String value = unknown.getProperty((String) key);
            if (value.length() > 0)
                p.put(prefix + key, value);
        }
    }

    /**
     * merges properties into current configuration.
     * @param p
     * @throws IOException
     */
    public void merge(Properties p) throws IOException
    {
        if (p.isEmpty())
            return;

        final List<String> strings = Arrays.asList(STRING_KEYS);
        final List<String> lists = Arrays.asList(LIST_KEYS);
        final List<String> maps = Arrays.asList(MAP_KEYS);

        List<String> bundleKeys = new ArrayList<String>();
        List<String> repoKeys = new ArrayList<String>();

        String bundles = p.getProperty(C_BUNDLES);
        if (bundles != null)
        {
            bundleKeys.addAll(Arrays.asList(bundles.split(LIST_REGEX)));
            list.put(C_BUNDLES, bundleKeys);
        }

        String repos = p.getProperty(C_REPOSITORIES);
        if (repos != null && !list.containsKey(C_REPOSITORIES))
        {
            for (String s : repos.split(LIST_REGEX))
            {
                repoKeys.add(s.trim());
            }
            list.put(C_REPOSITORIES, repoKeys);
        }

        List<String> subKeys = new ArrayList<String>();
        subKeys.addAll(Arrays.asList(PROP_KEYS));
        subKeys.addAll(bundleKeys);
        subKeys.addAll(repoKeys);

        Map<String, Properties> sub = new TreeMap<String, Properties>();

        for (Object k : p.keySet())
        {
            String key = (String) k;
            if (key.equals(C_BUNDLES) || key.equals(C_REPOSITORIES))
                continue;

            String[] keys = key.split(SUBKEY_SEP, 2);
            String value = p.getProperty(key);

            if (keys.length > 1)
            {
                Properties p2 = sub.get(keys[0]);
                if (p2 == null)
                {
                    p2 = new Properties();
                    sub.put(keys[0], p2);
                    if (!subKeys.contains(keys[0]))
                    {
                        // unknown.setProperty(keys[0] + SUBKEY_SEP, "");
                    }
                }
                p2.setProperty(keys[1], value);
            }
            else if (strings.contains(key))
            {
                if (!string.containsKey(key))
                    string.put(key, value);
            }
            else if (lists.contains(key))
            {
                if (!list.containsKey(key))
                {
                    ArrayList<String> list2 = new ArrayList<String>();
                    for (String s : value.split(LIST_REGEX))
                    {
                        if (s.trim().length() > 0)
                        {
                            list2.add(s.trim());
                        }
                    }
                    if (!list2.isEmpty())
                    {
                        list.put(key, list2);
                    }
                }
            }
            else if (maps.contains(key))
            {
                if (!map.containsKey(key))
                {
                    Map<String, Map<String, String>> map2 = new TreeMap<String, Map<String, String>>();

                    for (String subValue : QuoteUtil.split(value))
                    {
                        if (subValue.trim().length() > 0)
                        {
                            String[] split = subValue.split(MAPATTR_REGEX);
                            Map<String, String> map3 = new TreeMap<String, String>();
                            for (int i = 1; i < split.length; ++i)
                            {
                                String[] keyVal = split[i].split(":?=", 2);
                                if (keyVal.length != 2)
                                {
                                    throw new IOException("attribute missing '=':"
                                        + subValue);
                                }
                                map3.put(keyVal[0], keyVal[1]);
                            }
                            map2.put(split[0], map3);
                        }
                    }

                    map.put(key, map2);
                }
            }
            else
            {
                unknown.setProperty(key, value);
            }
        }

        for (String subKey : sub.keySet())
        {
            Properties props = sub.get(subKey);
            if (!props.isEmpty())
            {
                if (bundleKeys.contains(subKey))
                {
                    BldConfig config2 = new BldConfig(props);
                    Properties unkProps = config2.getUnknown();

                    if (config2.map.containsKey(M_IMPORTS))
                        unkProps.setProperty(M_IMPORTS, "");

                    if (config2.map.containsKey(M_REQUIRES))
                        unkProps.setProperty(M_REQUIRES, "");

                    for (Object unk : unkProps.keySet())
                    {
                        unknown.setProperty(subKey + SUBKEY_SEP + unk, "");
                    }
                    config.put(subKey, config2);
                }
                else
                {
                    Properties p2 = property.get(subKey);
                    if (p2 == null)
                    {
                        property.put(subKey, props);
                    }
                    else
                    {
                        for (Object k : props.keySet())
                        {
                            if (!p2.containsKey(k))
                            {
                                p2.put(k, props.get(k));
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public String toString()
    {
        return "STRING: " + string + " LIST:" + list + " MAP: " + map + " PROPERTY: "
            + property + " CONFIG:" + config + "\nDFLT{ " + dflt + "}";
    }
   
    public BldConfig clone() {
        try
        {
            BldConfig bc = (BldConfig) super.clone();
            bc.string = new TreeMap<String, String>(bc.string);
            bc.list = cloneMap(bc.list);
            bc.map = cloneMap(bc.map);
            bc.config = new TreeMap<String, BldConfig>(bc.config);
            bc.property = new TreeMap<String, Properties>(bc.property);

            // default config - not modified or saved
            // bc.dflt = bc.dflt.clone();

            bc.unknown = cloneProps(bc.unknown);
           
            return bc;
        }
        catch (CloneNotSupportedException e)
        {
            throw new IllegalStateException(e);
        }
    }
   
    @SuppressWarnings("unchecked")
    private static <K, V> Map<K, V> cloneMap(Map<K,V> map) {
        Map clone = new TreeMap();
        for (Map.Entry<?,?> e : map.entrySet()) {
            if ( e.getValue() == null ) {
                clone.put(e.getKey(), null);
            }
            else if ( e.getValue() instanceof List<?> ) {
                clone.put(e.getKey(), new ArrayList((List<?>) e.getValue()));
            }
            else if (e.getValue() instanceof Map<?,?>) {
                clone.put(e.getKey(), cloneMap((Map<?,?>)e.getValue()));
            }
            else if (e.getValue() instanceof String) {
                clone.put(e.getKey(), e.getValue());
            }
            else if (e.getValue() instanceof BldConfig) {
                BldConfig c = (BldConfig) e.getValue();
                clone.put(e.getKey(), c.clone());
            }
            else if (e.getValue() instanceof Properties) {
                Properties p = (Properties) e.getValue();
                clone.put(e.getKey(), cloneProps(p));
            }
            else {
                throw new IllegalStateException("Unexpected value: " + e.getValue());
            }
        }
        return clone;
    }
   
    private static Properties cloneProps(Properties p) {
        Properties props = new Properties();
        for (Map.Entry<?,?> pe : props.entrySet()) {
            props.put(pe.getKey(), pe.getValue());
        }
        return props;
    }
}
TOP

Related Classes of org.apache.felix.sigil.common.config.BldConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.