/**
* Copyright 2008-2016 Qualogy Solutions B.V.
*
* Licensed 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 com.qualogy.qafe.business.integration.rdb;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.qualogy.qafe.bind.commons.type.Out;
import com.qualogy.qafe.bind.core.application.ApplicationContext;
import com.qualogy.qafe.bind.integration.service.Method;
import com.qualogy.qafe.bind.integration.service.Service;
import com.qualogy.qafe.bind.resource.DatasourceBindResource;
import com.qualogy.qafe.bind.resource.query.Call;
import com.qualogy.qafe.bind.resource.query.Query;
import com.qualogy.qafe.business.integration.Processor;
import com.qualogy.qafe.business.integration.adapter.AdaptedToService;
import com.qualogy.qafe.business.integration.filter.Filters;
import com.qualogy.qafe.business.resource.ResourcePool;
import com.qualogy.qafe.business.resource.rdb.RDBDatasource;
import com.qualogy.qafe.core.datastore.DataIdentifier;
import com.qualogy.qafe.core.datastore.DataMap;
import com.qualogy.qafe.core.errorhandling.ExternalException;
public class RDBServiceProcessor extends Processor {
/**
* Method to create a set of keys for output, filtered
* from the outputparamlist. These keys can be used
* for sql enhancements f.i. if useOut is set.
*
* @param params
* @return
*/
private Set outputParametersToSet(List params) {
Set<String> set = new HashSet<String>();
if (params != null) {
for (Iterator iter = params.iterator(); iter.hasNext();) {
Out out = (Out) iter.next();
if (out.getRef() != null) {
set.add(out.getRef().getRootRef());
}
}
}
return set;
}
/**
* Processor execute method which determines the datasource to use for
* the execute of this method. Based upon the methodname the query is
* looked up in the datasource wrapper
*/
@Override
protected Object execute(ApplicationContext context, Service service, Method method, Map<String, AdaptedToService> paramsIn, Filters filters, DataIdentifier dataId) throws ExternalException {
String queryName = method.getName();
if (queryName == null) {
throw new IllegalArgumentException("queryName cannot be null");
}
if ((service.getResourceRef() == null) || (service.getResourceRef().getRef() == null) || !(service.getResourceRef().getRef() instanceof DatasourceBindResource)) {
throw new IllegalArgumentException("resource for datasourceservice must be set");
}
String dsRef = service.getResourceRef().getRef().getId(); //expecting just one
if (dsRef == null) {
throw new IllegalArgumentException("datasourceRef cannot be null");
}
RDBDatasource ds = (RDBDatasource) ResourcePool.getInstance().get(context.getId(), dsRef);
if (ds == null) {
throw new NullPointerException("database resource is null");
}
Query query = ds.get(queryName);
if (query == null) {
throw new IllegalArgumentException("query not found for key [" + queryName + "]");
}
new QafeDataSource(ds, dataId);
// Getting rid of the maps types in the input parameters,
// the input parameters can contain multiple records for processing
Object result = null;
List<Map<String, AdaptedToService>> newParamsIn = checkParamsIn(query, paramsIn);
if (newParamsIn.size() == 0) {
newParamsIn.add(new HashMap<String, AdaptedToService>());
}
for (Map<String, AdaptedToService> dataHashMap : newParamsIn) {
removeInternalKeys(dataHashMap);
result = DAODelegate.delegate(ds, query, method, dataHashMap, outputParametersToSet(method.getOutput()), filters, dataId);
}
return result;
}
private void removeInternalKeys(Map<String, AdaptedToService> paramsIn) {
if (paramsIn != null) {
if (paramsIn.containsKey(DataMap.ROW_NUMBER)){
paramsIn.remove(DataMap.ROW_NUMBER);
}
}
}
private List<Map<String, AdaptedToService>> checkParamsIn(Query query, Map<String, AdaptedToService> paramsIn) {
List<Map<String, AdaptedToService>> newParamsIn = new ArrayList<Map<String, AdaptedToService>>();
// In case of Call the input can be an Object and the user is passing a map from UI, so it should not split the inputs.
if(query instanceof Call) {
newParamsIn.add(paramsIn);
return newParamsIn;
}
if (paramsIn != null) {
Map<String, AdaptedToService> simpleData = new HashMap<String, AdaptedToService>();
Iterator<String> keys = paramsIn.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
AdaptedToService adaptedToService = paramsIn.get(key);
if (adaptedToService != null) {
if (adaptedToService.getValue() instanceof Map) {
Map map = (Map) adaptedToService.getValue();
populateFromMap(map, newParamsIn);
continue;
} else if (adaptedToService.getValue() instanceof List){
List list = (List)adaptedToService.getValue();
for (int i=0; i<list.size(); i++) {
populateFromMap((Map)list.get(i), newParamsIn);
}
continue;
}
}
simpleData.put(key, adaptedToService);
}
if (!simpleData.isEmpty()){
newParamsIn.add(simpleData);
}
}
return newParamsIn;
}
private void populateFromMap(Map map, List<Map<String, AdaptedToService>> newParamsIn) {
Map<String, AdaptedToService> data = new HashMap<String, AdaptedToService>();
Iterator itr = map.keySet().iterator();
while (itr.hasNext()) {
Object key = itr.next();
Object value = map.get(key);
AdaptedToService adaptedToService = null;
if (value != null) {
adaptedToService = AdaptedToService.create(value);
}
data.put(key.toString(), adaptedToService);
}
newParamsIn.add(data);
}
}