/*
 * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. 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.wso2.carbon.database.query.manager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.database.query.manager.config.Queries;
import org.wso2.carbon.database.query.manager.exception.QueryMappingNotAvailableException;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * The query mapping provider which mapping the queries of default map with component default config and
 * deployment.yaml config.
 */
public class QueryProvider {
    private static final Logger LOGGER = LoggerFactory.getLogger(QueryProvider.class);
    private static final String DEFAULT_TYPE = "default";

    /**
     * Merge the query mapping for component and deployment queries.
     *
     * @param databaseType      database type for query template lookup.
     * @param databaseVersion   database version for query template lookup.
     * @param componentQueries  queries array load from component queries config file.
     * @param deploymentQueries queries array load from carbon deployment config file.
     * @return results map of the component and deployment queries mapping.
     * @throws QueryMappingNotAvailableException
     */
    public static Map<String, String> mergeMapping(String databaseType, String databaseVersion,
                                                   List<Queries> componentQueries,
                                                   List<Queries> deploymentQueries)
            throws QueryMappingNotAvailableException {
        Set<String> defaultConfigSet = new HashSet<>();
        Map<String, String> deploymentConfigMap = new HashMap<>();
        Map<String, String> componentConfigMap = new HashMap<>();
        Map<String, String> result = new HashMap<>();
        if (deploymentQueries != null) {
            //populate the deployment query map for given database type and version.
            for (Queries queries : deploymentQueries) {
                if (queries.getType().equals(databaseType) && (queries.getVersion() == null ?
                        databaseVersion == null : queries.getVersion().equals(databaseVersion))) {
                    deploymentConfigMap = queries.getMappings();
                }
            }
        }
        if (componentQueries != null) {
            //populate the default and component query map for given type and version.
            for (Queries queries : componentQueries) {
                if (queries.getType().equals(DEFAULT_TYPE)) {
                    defaultConfigSet = queries.getMappings().keySet();
                } else if (queries.getType().equals(databaseType) && (queries.getVersion() == null ?
                        databaseVersion == null : queries.getVersion().equals(databaseVersion))) {
                    componentConfigMap = queries.getMappings();
                }
            }
            //if matching database type and version not found check whether default version available.
            if (componentConfigMap == null || componentConfigMap.isEmpty()) {
                for (Queries queries : componentQueries) {
                    if (queries.getType().equals(databaseType) && queries.getVersion() != null &&
                            queries.getVersion().equals(DEFAULT_TYPE)) {
                        componentConfigMap = queries.getMappings();
                    }
                }
            }
        } else {
            throw new QueryMappingNotAvailableException("Component configuration array list is null.");
        }
        if (!defaultConfigSet.isEmpty()) {
            for (String defaultEntry : defaultConfigSet) {
                String value;
                if (deploymentConfigMap != null && !deploymentConfigMap.isEmpty() &&
                        deploymentConfigMap.containsKey(defaultEntry)) {
                    value = deploymentConfigMap.get(defaultEntry);
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Override the query : '" + removeCRLFCharacters(defaultEntry) +
                                "' with deployment config value: '" + removeCRLFCharacters(value) +
                                "'  for database type: '" + removeCRLFCharacters(databaseType) + "' and version '" +
                                removeCRLFCharacters(String.valueOf(databaseVersion)) + "'.");
                    }
                } else {
                    if (componentConfigMap != null && !componentConfigMap.isEmpty()
                            && componentConfigMap.containsKey(defaultEntry)) {
                        value = componentConfigMap.get(defaultEntry);
                    } else {
                        throw new QueryMappingNotAvailableException("Mapping value for query: '" +
                                defaultEntry + "' not found in Deployment config Map and Component " +
                                "config Map for database type: '" + databaseType + "' and version '" +
                                databaseVersion + "'.");
                    }
                }
                result.put(defaultEntry, value);
            }
            return result;
        } else {
            throw new QueryMappingNotAvailableException("Default configuration map is null or empty.");
        }
    }

    private static String removeCRLFCharacters(String str) {
        if (str != null) {
            str = str.replace('\n', '_').replace('\r', '_');
        }
        return str;
    }
}

@@ -2542,22 +2542,35 @@
 ployment
+.yaml RDBMS
  quer
-y
+ies
  map for
@@ -2679,36 +2679,159 @@
     
-if (queries.getType().equals
+String queriesType = queries.getType();%0A                String queriesVersion = queries.getVersion();%0A                if ((queriesType.equalsIgnoreCase
 (dat
@@ -2845,100 +2845,174 @@
 pe) 
-&& (
+%7C%7C 
 queries
-.getVersion() == null ?%0A                        databaseVersion == null :
+Type.equalsIgnoreCase(DEFAULT_TYPE)) &&%0A                        (queriesVersion.equalsIgnoreCase(databaseVersion) %7C%7C%0A                               
  queries
 .get
@@ -3011,44 +3011,45 @@
 ries
-.get
 Version
-()
 .equals
-(databaseVersion
+IgnoreCase(DEFAULT_TYPE
 ))) 
@@ -3107,32 +3107,59 @@
 .getMappings();%0A
+                    break;%0A
                 
@@ -3273,21 +3273,29 @@
 mponent 
+RDBMS 
 quer
-y
+ies
  map for
@@ -3394,195 +3394,88 @@
     
-if (queries.getType().equals(DEFAULT_TYPE)) %7B%0A                    defaultConfigSet = queries.getMappings().keySet();%0A                %7D else if (queries.getType().equals(databaseType) && (
+String queriesType = queries.getType();%0A                String queriesVersion = 
 quer
@@ -3494,18 +3494,9 @@
 on()
- == null ?
+;
 %0A   
@@ -3512,86 +3512,53 @@
     
-        databaseVersion == null : queries.getVersion().equals(databaseVersion)
+if (queriesType.equalsIgnoreCase(DEFAULT_TYPE
 )) %7B
@@ -3578,34 +3578,32 @@
         
-componen
+defaul
 tConfig
-Map
+Set
  = queri
@@ -3610,32 +3610,41 @@
 es.getMappings()
+.keySet()
 ;%0A              
@@ -3650,365 +3650,141 @@
    %7D
-%0A            %7D%0A            //if matching database type and version not found check whether default version available.%0A            if (componentConfigMap == null %7C%7C componentConfigMap.isEmpty()) %7B%0A                for (Q
+ else if (queriesType.equalsIgnoreCase(databaseType)%0A                        && (q
 ueries
- queries : componentQueries) %7B%0A                    if (queries.getType().equals(databaseType) && queries.get
+Version.equalsIgnoreCase(database
 Version
-(
 ) 
-!= null &&%0A    
+%7C%7C%0A
     
@@ -3814,28 +3814,32 @@
 ries
-.get
 Version
-()
 .equals
+IgnoreCase
 (DEF
@@ -3841,39 +3841,36 @@
 e(DEFAULT_TYPE))
+)
  %7B%0A
-    
                 
@@ -3929,33 +3929,38 @@
                 
-%7D
+break;
 %0A               

Fix the DEFAULT version not loading issue in QueryProvider