package org.intermine.webservice.server.webproperties;

/*
 * Copyright (C) 2002-2017 FlyMine
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  See the LICENSE file for more
 * information or http://www.gnu.org/copyleft/lesser.html.
 *
 */

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.Queue;

import org.apache.log4j.Logger;
import org.intermine.api.InterMineAPI;
import org.intermine.util.PropertiesUtil;
import org.intermine.web.context.InterMineContext;
import org.intermine.webservice.server.core.JSONService;


/**
 * Exports selected web.properties.
 *
 * @author Julie
 */
public class WebPropertiesService extends JSONService
{
    private static final Logger LOG = Logger.getLogger(WebPropertiesService.class);

    /** @param im The InterMine state object. **/
    public WebPropertiesService(InterMineAPI im) {
        super(im);
    }

    @Override
    protected void execute() throws Exception {
        Properties props = InterMineContext.getWebProperties();
        Map<String, Object> webPropertiesMap = new HashMap<String, Object>();

        // region search
        appendProperties(webPropertiesMap, "genomicRegionSearch");

        // example identifiers for list upload
        appendProperties(webPropertiesMap, "bag");

        // example identifiers for quickSearch
        appendProperties(webPropertiesMap, "quickSearch");

        // mine name, citation
        appendProperties(webPropertiesMap, "project");

        // list params, delimiters
        appendProperties(webPropertiesMap, "list");

        // defaults for iodocs, only setting default query right now
        appendProperties(webPropertiesMap, "services");

        addResultItem(webPropertiesMap, false);
    }

    @Override
    public String getResultsKey() {
        return "web-properties";
    }

    private void appendProperties(final Map<String, Object> webPropertiesMap,
            final String startingPath) {
        Properties props = PropertiesUtil.getPropertiesStartingWith(startingPath, webProperties);
        Map<String, Object> thisPropertyMap = new HashMap<String, Object>();
        for (Object key: props.keySet()) {
            String keyString = String.valueOf(key);
            String[] keyParts = keyString.split("\\.");
            Queue<String> path = new LinkedList<String>();
            for (int i = 1; i < keyParts.length; i++) {
                path.add(keyParts[i]);
            }
            setProperty(thisPropertyMap, path, props.getProperty(keyString));
        }
        webPropertiesMap.put(startingPath, thisPropertyMap);
    }

    private void setProperty(
            final Map<String, Object> propertyMap,
            final Queue<String> path,
            final String value) {
        String key = path.remove();
        if (path.isEmpty()) {
            propertyMap.put(key, value);
        } else {
            Map<String, Object> thisLevel;
            if (!propertyMap.containsKey(key)) {
                thisLevel = new HashMap<String, Object>();
                propertyMap.put(key, thisLevel);
            } else {
                thisLevel = (Map<String, Object>) propertyMap.get(key);
            }
            setProperty(thisLevel, path, value);
        }
    }

}

@@ -49,16 +49,42 @@
 rties;%0A%0A
+import java.util.Arrays;%0A%0A
 /*%0A * Co
@@ -508,40 +508,8 @@
 e;%0A%0A
-import org.apache.log4j.Logger;%0A
 impo
@@ -815,24 +815,26 @@
 rvice%0A%7B%0A    
+//
 private stat
@@ -900,16 +900,157 @@
 .class);
+%0A    // if there is a parent property with an additional child value, we need a key%0A    private static final String DEFAULT_PATH = %22default%22;
 %0A%0A    /*
@@ -1180,24 +1180,24 @@
   @Override%0A
+
     protecte
@@ -1236,72 +1236,8 @@
 n %7B%0A
-        Properties props = InterMineContext.getWebProperties();%0A
     
@@ -3060,36 +3060,610 @@
     
-propertyMap.put(key, value);
+// make sure that there are no children for this attribute%0A            // eg. bag.examples = %22eve%22%0A            //     bag.examples.protein = %22EVE_DROME%22%0A            Map%3CString, Object%3E thisLevel = (Map%3CString, Object%3E) propertyMap.get(key);%0A            if (thisLevel == null %7C%7C thisLevel.isEmpty()) %7B%0A                propertyMap.put(key, value);%0A            %7D else %7B%0A                // there are other children at this level, so just call this value %22default%22%0A                // see #1631%0A                setProperty(thisLevel, new LinkedList%3CString%3E(Arrays.asList(DEFAULT_PATH)), value);%0A            %7D
 %0A   

Handle default properties. Refs #1634