argos/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java

336 lines
20 KiB
Java

package eu.eudat.logic.managers;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import eu.eudat.data.dao.criteria.DatasetProfileCriteria;
import eu.eudat.data.entities.DatasetProfile;
import eu.eudat.data.entities.UserDatasetProfile;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.query.items.item.datasetprofile.DatasetProfileAutocompleteRequest;
import eu.eudat.data.query.items.table.datasetprofile.DatasetProfileTableRequestItem;
import eu.eudat.exceptions.datasetprofile.DatasetProfileNewVersionException;
import eu.eudat.logic.builders.model.models.DataTableDataBuilder;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.operations.DatabaseRepository;
import eu.eudat.logic.utilities.builders.XmlBuilder;
import eu.eudat.logic.utilities.documents.helpers.FileEnvelope;
import eu.eudat.logic.utilities.documents.xml.datasetProfileXml.ExportXmlBuilderDatasetProfile;
import eu.eudat.logic.utilities.documents.xml.datasetProfileXml.ImportXmlBuilderDatasetProfile;
import eu.eudat.logic.utilities.helpers.StreamDistinctBy;
import eu.eudat.models.data.components.commons.datafield.AutoCompleteData;
import eu.eudat.models.data.datasetprofile.DatasetProfileAutocompleteItem;
import eu.eudat.models.data.datasetprofile.DatasetProfileListingModel;
import eu.eudat.models.data.entities.xmlmodels.datasetprofiledefinition.Field;
import eu.eudat.models.data.externaldataset.ExternalAutocompleteFieldModel;
import eu.eudat.models.data.helpers.common.DataTableData;
import eu.eudat.models.data.listingmodels.UserInfoListingModel;
import eu.eudat.models.data.security.Principal;
import eu.eudat.queryable.QueryableList;
import eu.eudat.types.Authorities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.activation.MimetypesFileTypeMap;
import javax.transaction.Transactional;
import javax.xml.xpath.*;
import java.io.*;
import java.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class DatasetProfileManager {
private static final Logger logger = LoggerFactory.getLogger(DatasetProfileManager.class);
private ApiContext apiContext;
private DatabaseRepository databaseRepository;
private Environment environment;
private List<String> cache;
@Autowired
public DatasetProfileManager(ApiContext apiContext, Environment environment) {
this.apiContext = apiContext;
this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository();
this.environment = environment;
this.cache = new ArrayList<>();
}
@Transactional
public eu.eudat.models.data.admin.composite.DatasetProfile getDatasetProfile(String id) {
eu.eudat.data.entities.DatasetProfile profile = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(UUID.fromString(id));
eu.eudat.models.data.admin.composite.DatasetProfile datasetprofile = AdminManager.generateDatasetProfileModel(profile);
datasetprofile.setLabel(profile.getLabel());
datasetprofile.setStatus(profile.getStatus());
datasetprofile.setDescription(profile.getDescription());
datasetprofile.setLanguage(profile.getLanguage());
datasetprofile.setUsers(new ArrayList<>());
retrieveUsers(profile, datasetprofile);
return datasetprofile;
}
public List<DatasetProfileAutocompleteItem> getWithCriteria(DatasetProfileAutocompleteRequest datasetProfileAutocompleteRequest) throws IllegalAccessException, InstantiationException {
QueryableList<DatasetProfile> items = databaseRepository.getDatasetProfileDao().getWithCriteria(datasetProfileAutocompleteRequest.getCriteria());
QueryableList<DatasetProfile> pagedItems = datasetProfileAutocompleteRequest.applyPaging(items);
List<DatasetProfileAutocompleteItem> datasetProfiles = pagedItems.select(item -> new DatasetProfileAutocompleteItem().fromDataModel(item));
return datasetProfiles;
}
public DatasetProfile clone(String id) {
DatasetProfile profile = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(UUID.fromString(id));
apiContext.getOperationsContext().getDatabaseRepository().detachEntity(profile);
profile.setId(null);
MetricsManager.increaseValue("argos_dataset_templates", 1, "total");
return profile;
}
public DataTableData<DatasetProfileListingModel> getPaged(DatasetProfileTableRequestItem datasetProfileTableRequestItem, Principal principal) throws Exception {
QueryableList<DatasetProfile> items = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(datasetProfileTableRequestItem.getCriteria());
QueryableList<DatasetProfile> authItems = null;
if (principal.getAuthz().contains(Authorities.ADMIN)) {
authItems = items;
} else if (principal.getAuthz().contains(Authorities.DATASET_PROFILE_MANAGER)) {
authItems = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getAuthenticated(items, principal.getId(), null);
}
QueryableList<DatasetProfile> pagedItems = PaginationManager.applyPaging(authItems, datasetProfileTableRequestItem);
List<DatasetProfileListingModel> datasetProfiles = pagedItems.select(item -> new DatasetProfileListingModel().fromDataModel(item));
return apiContext.getOperationsContext().getBuilderFactory().getBuilder(DataTableDataBuilder.class).data(datasetProfiles).totalCount(items.count()).build();
}
public List<DatasetProfileListingModel> getAll(DatasetProfileTableRequestItem tableRequestItem) throws IllegalAccessException, InstantiationException {
QueryableList<DatasetProfile> items = databaseRepository.getDatasetProfileDao().getWithCriteria(tableRequestItem.getCriteria());
List<DatasetProfileListingModel> datasetProfiles = items.select(item -> new DatasetProfileListingModel().fromDataModel(item));
return datasetProfiles;
}
public eu.eudat.models.data.entities.xmlmodels.datasetprofiledefinition.Field queryForField(String xml, String fieldId) throws XPathExpressionException {
eu.eudat.models.data.entities.xmlmodels.datasetprofiledefinition.Field field = new Field();
Document document = XmlBuilder.fromXml(xml);
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
XPathExpression expr =
xpath.compile("//field[@id='" + fieldId + "']");
Element name = (Element) expr.evaluate(document, XPathConstants.NODE);
field.fromXml(name);
return field;
}
public List<ExternalAutocompleteFieldModel> getAutocomplete(AutoCompleteData data, String like) {
List<ExternalAutocompleteFieldModel> result = new LinkedList<>();
SimpleClientHttpRequestFactory simpleFactory = new SimpleClientHttpRequestFactory();
RestTemplate restTemplate = new RestTemplate(simpleFactory);
HttpHeaders headers = new HttpHeaders();
DocumentContext jsonContext = null;
HttpEntity<String> entity;
ResponseEntity response;
List<Map<String, String>> jsonItems;
int i = 0;
for (AutoCompleteData.AutoCompleteSingleData singleData: data.getAutoCompleteSingleDataList()) {
switch (AutoCompleteData.AutocompleteType.fromValue(singleData.getAutocompleteType())) {
case UNCACHED:
String url = singleData.getUrl();
String mediaType = "";
if (url.contains("openaire") || url.contains("zenodo")) {
mediaType = "application/json; charset=utf-8";
if (url.contains("zenodo")) {
url = url.replace("?", "/?");
}
url = url.replace("{like}", like.equals("") ? "*" : like);
url = url.replace("%20", " ");
url = url.replace("%22", "\"");
url = url.replace("&amp;", "&");
} else {
mediaType = "application/vnd.api+json; charset=utf-8";
url += "?search=" + like;
}
if (!url.contains("zenodo")) {
headers.setAccept(Collections.singletonList(MediaType.valueOf(mediaType)));
}
headers.setContentType(MediaType.APPLICATION_JSON);
entity = new HttpEntity<>("parameters", headers);
response = restTemplate.exchange(url, HttpMethod.GET, entity, Object.class);
jsonContext = JsonPath.parse(response.getBody());
jsonItems = jsonContext.read(singleData.getOptionsRoot() + "['" + singleData.getAutoCompleteOptions().getLabel() + "','" + singleData.getAutoCompleteOptions().getValue() + "','" + singleData.getAutoCompleteOptions().getSource() + "','" + "uri" + "']");
jsonItems.forEach(item -> result.add(new ExternalAutocompleteFieldModel(item.get(singleData.getAutoCompleteOptions().getValue()), item.get(singleData.getAutoCompleteOptions().getLabel()), item.get(singleData.getAutoCompleteOptions().getSource()) != null ? item.get(singleData.getAutoCompleteOptions().getSource()) : singleData.getAutoCompleteOptions().getSource(), item.get("uri"))));
break;
case CACHED:
headers.setAccept(Collections.singletonList(MediaType.valueOf("text/plain; charset=utf-8")));
headers.setContentType(MediaType.TEXT_PLAIN);
entity = new HttpEntity<>("parameters", headers);
if (this.cache.size() <= i) {
response = restTemplate.exchange(singleData.getUrl(), HttpMethod.GET, entity, String.class);
this.cache.add((String) response.getBody());
}
jsonContext = JsonPath.parse(cache.get(i));
jsonItems = jsonContext.read(singleData.getOptionsRoot() + "['" + singleData.getAutoCompleteOptions().getLabel() + "','" + singleData.getAutoCompleteOptions().getValue() + "','" + singleData.getAutoCompleteOptions().getSource() + "','" + "uri" + "']");
jsonItems.stream().filter(item -> item.get(singleData.getAutoCompleteOptions().getLabel()).toLowerCase().contains(like.toLowerCase()))
.forEach(item -> result.add(new ExternalAutocompleteFieldModel(item.get(singleData.getAutoCompleteOptions().getValue()), item.get(singleData.getAutoCompleteOptions().getLabel()), item.get(singleData.getAutoCompleteOptions().getSource()) != null ? item.get(singleData.getAutoCompleteOptions().getSource()) : singleData.getAutoCompleteOptions().getSource(), item.get("uri"))));
i++;
break;
}
}
return result.stream().sorted(Comparator.comparing(ExternalAutocompleteFieldModel::getLabel)).collect(Collectors.toList());
//return result;
}
public ResponseEntity<byte[]> getDocument(eu.eudat.models.data.user.composite.DatasetProfile datasetProfile, String label) throws IllegalAccessException, IOException, InstantiationException {
FileEnvelope envelope = getXmlDocument(datasetProfile, label);
InputStream resource = new FileInputStream(envelope.getFile());
logger.info("Mime Type of " + envelope.getFilename() + " is " +
new MimetypesFileTypeMap().getContentType(envelope.getFile()));
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentLength(envelope.getFile().length());
responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
responseHeaders.set("Content-Disposition", "attachment;filename=" + envelope.getFilename() + ".xml");
responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type");
byte[] content = org.apache.poi.util.IOUtils.toByteArray(resource);
resource.close();
Files.deleteIfExists(envelope.getFile().toPath());
return new ResponseEntity<>(content,
responseHeaders,
HttpStatus.OK);
}
public FileEnvelope getXmlDocument(eu.eudat.models.data.user.composite.DatasetProfile datatasetProfile, String label) throws InstantiationException, IllegalAccessException, IOException {
ExportXmlBuilderDatasetProfile xmlBuilder = new ExportXmlBuilderDatasetProfile();
File file = xmlBuilder.build(datatasetProfile, environment);
FileEnvelope fileEnvelope = new FileEnvelope();
fileEnvelope.setFile(file);
fileEnvelope.setFilename(label);
return fileEnvelope;
}
public eu.eudat.logic.utilities.documents.xml.datasetProfileXml.datasetProfileModel.DatasetProfile createDatasetProfileFromXml(MultipartFile multiPartFile) {
ImportXmlBuilderDatasetProfile xmlBuilder = new ImportXmlBuilderDatasetProfile();
try {
File localFile = convert(multiPartFile);
eu.eudat.logic.utilities.documents.xml.datasetProfileXml.datasetProfileModel.DatasetProfile profile = xmlBuilder.build(localFile);
Files.deleteIfExists(localFile.toPath());
MetricsManager.increaseValue("argos_dataset_templates", 1, "total");
return profile;
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
private File convert(MultipartFile file) throws IOException {
File convFile = new File(this.environment.getProperty("temp.temp") + file.getOriginalFilename());
convFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
return convFile;
}
public eu.eudat.data.entities.DatasetProfile createNewVersionDatasetProfile(String id, eu.eudat.models.data.admin.composite.DatasetProfile profile) throws Exception {
// Getting the DatasetProfile which we will create its new version.
eu.eudat.data.entities.DatasetProfile oldDatasetProfile = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(UUID.fromString(id));
// Getting the DatasetProfile with the latest Version.
DatasetProfileCriteria criteria = new DatasetProfileCriteria();
LinkedList<UUID> list = new LinkedList<>();
list.push(oldDatasetProfile.getGroupId());
criteria.setGroupIds(list);
criteria.setAllVersions(false);
QueryableList<DatasetProfile> datasetProfileQueryableList = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(criteria);
eu.eudat.data.entities.DatasetProfile latestVersionDatasetProfile = datasetProfileQueryableList.getSingle();
if (latestVersionDatasetProfile.getVersion().equals(oldDatasetProfile.getVersion())){
eu.eudat.models.data.admin.composite.DatasetProfile sortedProfile = profile.toShort();
eu.eudat.data.entities.DatasetProfile modelDefinition = AdminManager.generateViewStyleDefinition(sortedProfile, apiContext);
modelDefinition.setLabel(oldDatasetProfile.getLabel());
modelDefinition.setVersion((short) (oldDatasetProfile.getVersion() + 1));
modelDefinition.setGroupId(oldDatasetProfile.getGroupId());
modelDefinition.setLanguage(oldDatasetProfile.getLanguage());
apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().createOrUpdate(modelDefinition);
return modelDefinition;
} else {
throw new DatasetProfileNewVersionException("Version to update not the latest.");
}
}
public void storeDatasetProfileUsers(DatasetProfile entity, eu.eudat.models.data.admin.composite.DatasetProfile model) {
if (model.getUsers() != null && !model.getUsers().isEmpty()) {
if (entity.getUsers() == null) {
entity.setUsers(new HashSet<>());
}
model.getUsers().stream().filter(userInfoListingModel -> entity.getUsers().stream().filter(userDatasetProfile -> userDatasetProfile.getUser().getId().equals(userInfoListingModel.getId())).count() == 0).forEach(userInfoListingModel -> {
UserDatasetProfile userDatasetProfile1 = new UserDatasetProfile();
userDatasetProfile1.setDatasetProfile(entity);
UserInfo userInfo1 = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(userInfoListingModel.getId());
userDatasetProfile1.setUser(userInfo1);
userDatasetProfile1.setRole(1);
apiContext.getOperationsContext().getDatabaseRepository().getUserDatasetProfileDao().createOrUpdate(userDatasetProfile1);
});
}
if (entity.getUsers() != null && !entity.getUsers().isEmpty()) {
entity.getUsers().stream().filter(userDatasetProfile -> model.getUsers().stream().filter(userInfoListingModel -> userDatasetProfile.getUser().getId().equals(userInfoListingModel.getId())).count() == 0).forEach(userDatasetProfile -> {
userDatasetProfile.setRole(2);
apiContext.getOperationsContext().getDatabaseRepository().getUserDatasetProfileDao().createOrUpdate(userDatasetProfile);
});
}
}
@Transactional
public void retrieveUsers(DatasetProfile entity, eu.eudat.models.data.admin.composite.DatasetProfile model) {
if (entity.getUsers() != null && !entity.getUsers().isEmpty()) {
model.setUsers(entity.getUsers().stream().filter(userDatasetProfile -> userDatasetProfile.getRole() < 2).map(userDatasetProfile -> {
UserInfoListingModel userInfoListingModel = new UserInfoListingModel();
userInfoListingModel.setId(userDatasetProfile.getUser().getId());
userInfoListingModel.setName(userDatasetProfile.getUser().getName());
userInfoListingModel.setEmail(userDatasetProfile.getUser().getEmail());
userInfoListingModel.setRole(userDatasetProfile.getRole());
return userInfoListingModel;
}).collect(Collectors.toList()));
}
}
public long countAlldraft() {
DatasetProfileCriteria criteria = new DatasetProfileCriteria();
criteria.setStatus(0);
return apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(criteria).count();
}
public long countAllFinalized() {
DatasetProfileCriteria criteria = new DatasetProfileCriteria();
criteria.setStatus(1);
return apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(criteria).count();
}
@Transactional
public long countAllUsed() {
DatasetProfileCriteria criteria = new DatasetProfileCriteria();
criteria.setStatus(1);
criteria.setAllVersions(false);
List<DatasetProfile> datasetProfiles = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(criteria).toList();
return datasetProfiles.stream().filter(StreamDistinctBy.distinctByKey(DatasetProfile::getId)).filter(datasetProfile -> !datasetProfile.getDataset().isEmpty()).count();
}
}