dnet-core/dnet-modular-ui/src/main/java/eu/dnetlib/functionality/modular/ui/mdstore/MDStoreServiceInternalContr...

319 lines
13 KiB
Java

package eu.dnetlib.functionality.modular.ui.mdstore;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.xml.ws.wsaddressing.W3CEndpointReference;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import eu.dnetlib.data.mdstore.DocumentNotFoundException;
import eu.dnetlib.data.mdstore.MDStoreService;
import eu.dnetlib.data.mdstore.modular.MDFormatDescription;
import eu.dnetlib.data.mdstore.modular.MDStoreUtils;
import eu.dnetlib.data.mdstore.modular.ModularMDStoreService;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
import eu.dnetlib.enabling.resultset.client.ResultSetClientFactory;
import eu.dnetlib.functionality.modular.ui.mdstore.model.MDStoreInfo;
import eu.dnetlib.functionality.modular.ui.mdstore.model.MDStoreResult;
import eu.dnetlib.miscutils.functional.xml.ApplyXslt;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
/**
* The Class MDStoreServiceInternalController.
*/
@Controller
public class MDStoreServiceInternalController {
/**
* The Constant log.
*/
private static final Log log = LogFactory.getLog(MDStoreServiceInternalController.class);
@Value("${dnet.modular.ui.mdstore.xslt.record2document}")
private String recordXsltClasspath;
/**
* The lookup locator.
*/
@Resource
private UniqueServiceLocator serviceLocator;
@Autowired
private MDStoreUtils mdStoreUtils;
@Resource
private ResultSetClientFactory resultSetClientFactory;
@Autowired
private ModularMDStoreService mdStoreService;
private Map<String, Info> datasourceCache;
/**
* List md stores.
*
* @param map the map
* @return the list
* @throws Exception the exception
*/
@RequestMapping(value = "/ui/mdstore/listMDStores.do")
@ResponseBody
public List<MDStoreInfo> listMDStores(final ModelMap map) throws Exception {
if (datasourceCache == null) {
datasourceCache = datasourceFromMdStore();
}
final String xquery = "for $x in collection('/db/DRIVER/MDStoreDSResources/MDStoreDSResourceType') let $format := $x//METADATA_FORMAT "
+ "let $layout := $x//METADATA_FORMAT_LAYOUT let $interpretation :=$x//METADATA_FORMAT_INTERPRETATION "
+ "let $uri := $x//RESOURCE_URI/@value/string() let $id := $x//RESOURCE_IDENTIFIER/@value/string() "
+ "let $lastDate := $x//LAST_STORAGE_DATE let $size :=$x//NUMBER_OF_RECORDS "
+ "return concat($uri,'@::@',$id,'@::@',$format,'(-)',$layout, '(-)',$interpretation,'@::@',$lastDate,'@::@',$size) ";
log.debug("Executing lookup query" + xquery);
return Lists.transform(serviceLocator.getService(ISLookUpService.class).quickSearchProfile(xquery), input -> {
MDStoreInfo mdStoreInfo = MDStoreInfo.fromXqueryResult(input);
Info currentInfo = datasourceCache.get(mdStoreInfo.getId());
if (currentInfo != null) {
Map<String, String> datasourcesInvolved = mdStoreInfo.getDatasourcesInvolved();
if (datasourcesInvolved == null) {
datasourcesInvolved = Maps.newHashMap();
mdStoreInfo.setDatasourcesInvolved(datasourcesInvolved);
}
datasourcesInvolved.put("datasourceId", currentInfo.getDatasourceId());
datasourcesInvolved.put("datasourceName", currentInfo.getDatasourceName());
}
return mdStoreInfo;
});
}
@RequestMapping(value = "/ui/mdstore/reloadInfo")
@ResponseBody
public List<MDStoreInfo> reloadInfo(final ModelMap map) throws Exception {
datasourceCache = null;
return listMDStores(map);
}
@RequestMapping(value = "/ui/mdstore/getMdStoreInfo.do")
@ResponseBody
public MDStoreInfo getMdStoreInfo(final ModelMap map, @RequestParam(value = "id", required = true) final String profileId) throws Exception {
final MDStoreInfo mdStoreInfo = retrieveMDStoreInfo(profileId);
List<MDFormatDescription> indexFields = mdStoreUtils.getField(mdStoreInfo.getFormat(), mdStoreInfo.getLayout());
List<String> idFields;
if (indexFields != null) {
idFields = indexFields.stream().map(MDFormatDescription::getName).collect(Collectors.toList());
mdStoreInfo.setIndexFields(idFields);
}
return mdStoreInfo;
}
@RequestMapping(value = "/ui/mdstore/findRecords", method = RequestMethod.POST)
@ResponseBody
public MDStoreResult findRecords(final ModelMap map,
@RequestBody final Map<String, String> queryParam) throws Exception {
if (!queryParam.containsKey("mdId")) throw new MDStoreUIException("mdId parameters expected");
final String mdId = queryParam.get("mdId");
int offset = 0;
if (queryParam.containsKey("page")) {
try {
offset = Integer.parseInt(queryParam.get("page"));
queryParam.remove("page");
} catch (Exception e) {
log.error("Error on parsing page " + queryParam.get("page"));
}
}
queryParam.remove("mdId");
final MDStoreResult res = new MDStoreResult();
ClassPathResource cpr = new ClassPathResource(recordXsltClasspath);
ApplyXslt xslt = new ApplyXslt(cpr);
res.setResult(mdStoreService.getMDStoreRecords(mdId, 10, offset, queryParam).stream().map(xslt::evaluate).collect(Collectors.toList()));
//TERRIBLE HACK SHAME SANDRO SHAME!
int count = 0;
try {
count = Integer.parseInt(queryParam.get("count"));
} catch (Exception e) {
log.error(e);
}
res.setCount(count);
return res;
}
@RequestMapping(value = "/ui/mdstore/mdStoreResults")
@ResponseBody
public MDStoreResult getMDStoreResults(final ModelMap map,
@RequestParam(value = "mdId", required = true) final String mdId,
@RequestParam(value = "from", required = true) final int from,
@RequestParam(value = "id_query", required = false) final String idToQuery,
@RequestParam(value = "free_query", required = false) final String freeQuery) throws Exception {
MDStoreService mdService = serviceLocator.getService(MDStoreService.class, mdId);
ClassPathResource cpr = new ClassPathResource(recordXsltClasspath);
ApplyXslt xslt = new ApplyXslt(cpr);
MDStoreResult resultValues = new MDStoreResult();
resultValues.setCount(getMdStoreInfo(map, mdId).getSize());
if (idToQuery != null && !idToQuery.isEmpty()) {
try {
String record = mdService.deliverRecord(mdId, idToQuery);
resultValues.setResult(Lists.newArrayList(xslt.evaluate(record)));
return resultValues;
} catch (DocumentNotFoundException e) {
return null;
}
}
W3CEndpointReference epr = mdService.deliverMDRecords(mdId, null, null, null);
Iterable<String> result = resultSetClientFactory.getClient(epr);
List<String> convertedList = new ArrayList<>();
Iterator<String> it = result.iterator();
int currentCounter = 0;
while (currentCounter < from) {
if (it.hasNext()) {
it.next();
currentCounter++;
} else {
resultValues.setResult(convertedList);
return resultValues;
}
}
for (int i = 0; i < 10; i++) {
if (it.hasNext()) {
convertedList.add(xslt.evaluate(it.next()));
// convertedList.add(it.next());
} else {
break;
}
}
resultValues.setResult(convertedList);
return resultValues;
}
private Map<String, Info> datasourceFromMdStore() {
final String query = "for $x in collection('/db/DRIVER/WorkflowDSResources/WorkflowDSResourceType') where $x[.//PARAM/@category/string()='MDSTORE_ID'] " +
"return concat($x//PARAM[./@name='providerId'][1]/string(), '<::>',$x//PARAM[./@name='providerName'][1]/string(), '<::>', " +
"string-join($x//PARAM[./@category/string()='MDSTORE_ID']/string(), '--'))";
final ISLookUpService lookupService = serviceLocator.getService(ISLookUpService.class);
try {
Map<String, Info> result = Maps.newHashMap();
List<String> results = lookupService.quickSearchProfile(query);
for (String item : results) {
String[] splitted = item.split("<::>");
if (splitted != null && splitted.length == 3) {
final Info currentInfo = new Info();
currentInfo.setDatasourceId(splitted[0]);
currentInfo.setDatasourceName(splitted[1]);
final String[] mdstores = splitted[2].split("--");
if (mdstores != null) {
for (String mdstore : mdstores) {
result.put(mdstore, currentInfo);
}
}
}
}
return result;
} catch (ISLookUpException e) {
log.error(e);
return null;
}
}
private MDStoreInfo retrieveMDStoreInfo(final String identifier) {
MDStoreInfo result = null;
try {
result = null;
final String xquery = " for $x in collection('/db/DRIVER/MDStoreDSResources/MDStoreDSResourceType') "
+ " where $x//RESOURCE_IDENTIFIER/@value/string()=\"%s\" return concat($x//RESOURCE_URI/@value/string() "
+ ", '@::@',$x//RESOURCE_IDENTIFIER/@value/string() ,'@::@',$x//METADATA_FORMAT,'(-)',$x//METADATA_FORMAT_LAYOUT, "
+ " '(-)', $x//METADATA_FORMAT_INTERPRETATION ,'@::@',$x//LAST_STORAGE_DATE,'@::@',$x//NUMBER_OF_RECORDS)";
List<String> results = serviceLocator.getService(ISLookUpService.class).quickSearchProfile(String.format(xquery, identifier));
if (results != null && !results.isEmpty()) {
result = MDStoreInfo.fromXqueryResult(results.get(0));
}
} catch (ISLookUpException e) {
log.error(String.format("Error on getting information for mdstore with identifier: %s", identifier), e);
}
return result;
}
private Map<String, String> findDatasourceNameAssociatedToMdStore(final String mdStoreId) throws ISLookUpException {
final String baseQuery = "for $x in collection('/db/DRIVER/WorkflowDSResources/WorkflowDSResourceType') where $x[.//PARAM/string()='%s'] return concat($x//PARAM[./@name='providerId'][1]/string(), '<::>',$x//PARAM[./@name='providerName'][1]/string())";
final ISLookUpService lookupService = serviceLocator.getService(ISLookUpService.class);
List<String> result = lookupService.quickSearchProfile(String.format(baseQuery, mdStoreId));
Map<String, String> datasources = Maps.newHashMap();
for (String item : result) {
String[] splitted = item.split("<::>");
if (splitted != null && splitted.length == 2) {
datasources.put(splitted[0], splitted[1]);
}
}
return datasources;
}
class Info {
private String datasourceId;
private String datasourceName;
private String mdStoreId;
public String getDatasourceName() {
return datasourceName;
}
public void setDatasourceName(String datasourceName) {
this.datasourceName = datasourceName;
}
public String getDatasourceId() {
return datasourceId;
}
public void setDatasourceId(String datasourceId) {
this.datasourceId = datasourceId;
}
public String getMdStoreId() {
return mdStoreId;
}
public void setMdStoreId(String mdStoreId) {
this.mdStoreId = mdStoreId;
}
}
}