Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/upstream/main' into async_…
Browse files Browse the repository at this point in the history
…indexing

# Conflicts:
#	services/src/main/java/org/fao/geonet/api/processing/DatabaseProcessUtils.java
  • Loading branch information
tobias-hotz committed Dec 10, 2024
2 parents d6b9655 + cd74d3b commit c65cc71
Show file tree
Hide file tree
Showing 204 changed files with 2,288 additions and 684 deletions.
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

Thank you for contributing to GeoNetwork!

* Free-software: GeoNetwork is free-software, using the [GNU GENERAL PUBLIC LICENSE](LICENSE.md). Contributions provided by you, or your employer, are required to be compatible with this free-software license.
* Free-software: GeoNetwork is free-software, using the [GNU GENERAL PUBLIC LICENSE](LICENSE.md).
* Contributions provided by you, or your employer, are required to be compatible with this free-software license. You will therefor be asked to sign the [Contributor License Agreement](https://cla-assistant.io/geonetwork/) when you are contributing to the repositories. This process is automatically enabled when you create your first pull request via https://cla-assistant.io/.
* Pull-request: GeoNetwork uses a pull-request workflow to review and accept changes. Pull-requests must be submitted against the *main* branch first, and may be back ported as required.

# Pull requests
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@ Developer documentation located in ``README.md`` files in the code-base:
* [Software Development Documentation](/software_development/) provides instructions for setting up a development environment, building GeoNetwork, compiling user documentation, and making a releases.
* Module specific documentation can be found in each module:

## Individual Contributor Licenses signed using the CLS Assistant
[![CLA assistant](https://cla-assistant.io/readme/badge/geonetwork/geonetwork)](https://cla-assistant.io/geonetwork/geonetwork)

## Open Source Security Foundation (OpenSSF) best practices status
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8626/badge)](https://www.bestpractices.dev/projects/8626)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8626/badge)](https://www.bestpractices.dev/projects/8626)
2 changes: 1 addition & 1 deletion cachingxslt/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<parent>
<groupId>org.geonetwork-opensource</groupId>
<artifactId>geonetwork</artifactId>
<version>4.4.6-SNAPSHOT</version>
<version>4.4.7-SNAPSHOT</version>
</parent>


Expand Down
2 changes: 1 addition & 1 deletion common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<parent>
<groupId>org.geonetwork-opensource</groupId>
<artifactId>geonetwork</artifactId>
<version>4.4.6-SNAPSHOT</version>
<version>4.4.7-SNAPSHOT</version>
</parent>


Expand Down
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<parent>
<artifactId>geonetwork</artifactId>
<groupId>org.geonetwork-opensource</groupId>
<version>4.4.6-SNAPSHOT</version>
<version>4.4.7-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (C) 2001-2024 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
* Rome - Italy. email: [email protected]
*/

package org.fao.geonet.api.exception;

import java.util.Locale;

import org.fao.geonet.exceptions.LocalizedException;

public class GeonetMaxUploadSizeExceededException extends LocalizedException {

public GeonetMaxUploadSizeExceededException() {
super();
}

public GeonetMaxUploadSizeExceededException(String message) {
super(message);
}

public GeonetMaxUploadSizeExceededException(String message, Throwable cause) {
super(message, cause);
}

public GeonetMaxUploadSizeExceededException(Throwable cause) {
super(cause);
}

protected String getResourceBundleBeanQualifier() {
return "apiMessages";
}

@Override
public GeonetMaxUploadSizeExceededException withMessageKey(String messageKey) {
super.withMessageKey(messageKey);
return this;
}

@Override
public GeonetMaxUploadSizeExceededException withMessageKey(String messageKey, Object[] messageKeyArgs) {
super.withMessageKey(messageKey, messageKeyArgs);
return this;
}

@Override
public GeonetMaxUploadSizeExceededException withDescriptionKey(String descriptionKey) {
super.withDescriptionKey(descriptionKey);
return this;
}

@Override
public GeonetMaxUploadSizeExceededException withDescriptionKey(String descriptionKey, Object[] descriptionKeyArgs) {
super.withDescriptionKey(descriptionKey, descriptionKeyArgs);
return this;
}

@Override
public GeonetMaxUploadSizeExceededException withLocale(Locale locale) {
super.withLocale(locale);
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ public String toString() {

private String escapeResourceManagementExternalProperties(String value) {
return value.replace(RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR, RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_ESCAPED_SEPARATOR);
}
}

/**
* Create an encoded base 64 object id contains the following fields to uniquely identify the resource
Expand Down
45 changes: 17 additions & 28 deletions core/src/main/java/org/fao/geonet/kernel/SelectionManager.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2001-2016 Food and Agriculture Organization of the
* Copyright (C) 2001-2024 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
Expand Down Expand Up @@ -51,30 +51,30 @@
* Manage objects selection for a user session.
*/
public class SelectionManager {

public static final String SELECTION_METADATA = "metadata";
public static final String SELECTION_BUCKET = "bucket";
// Bucket name used in the search UI to store the selected the metadata
public static final String SELECTION_BUCKET = "s101";
// used to limit select all if get system setting maxrecords fails or contains value we can't parse
public static final int DEFAULT_MAXHITS = 1000;
public static final String ADD_ALL_SELECTED = "add-all";
public static final String REMOVE_ALL_SELECTED = "remove-all";
public static final String ADD_SELECTED = "add";
public static final String REMOVE_SELECTED = "remove";
public static final String CLEAR_ADD_SELECTED = "clear-add";
private Hashtable<String, Set<String>> selections = null;
private Hashtable<String, Set<String>> selections;

private SelectionManager() {
selections = new Hashtable<String, Set<String>>(0);
selections = new Hashtable<>(0);

Set<String> MDSelection = Collections
.synchronizedSet(new HashSet<String>(0));
.synchronizedSet(new HashSet<>(0));
selections.put(SELECTION_METADATA, MDSelection);
}


public Map<String, Integer> getSelectionsAndSize() {
return selections.entrySet().stream().collect(Collectors.toMap(
e -> e.getKey(),
Map.Entry::getKey,
e -> e.getValue().size()
));
}
Expand Down Expand Up @@ -183,7 +183,7 @@ public int updateSelection(String type,
// Get the selection manager or create it
Set<String> selection = this.getSelection(type);
if (selection == null) {
selection = Collections.synchronizedSet(new HashSet<String>());
selection = Collections.synchronizedSet(new HashSet<>());
this.selections.put(type, selection);
}

Expand All @@ -192,30 +192,21 @@ public int updateSelection(String type,
this.selectAll(type, context, session);
else if (selected.equals(REMOVE_ALL_SELECTED))
this.close(type);
else if (selected.equals(ADD_SELECTED) && listOfIdentifiers.size() > 0) {
else if (selected.equals(ADD_SELECTED) && !listOfIdentifiers.isEmpty()) {
// TODO ? Should we check that the element exist first ?
for (String paramid : listOfIdentifiers) {
selection.add(paramid);
}
} else if (selected.equals(REMOVE_SELECTED) && listOfIdentifiers.size() > 0) {
selection.addAll(listOfIdentifiers);
} else if (selected.equals(REMOVE_SELECTED) && !listOfIdentifiers.isEmpty()) {
for (String paramid : listOfIdentifiers) {
selection.remove(paramid);
}
} else if (selected.equals(CLEAR_ADD_SELECTED) && listOfIdentifiers.size() > 0) {
} else if (selected.equals(CLEAR_ADD_SELECTED) && !listOfIdentifiers.isEmpty()) {
this.close(type);
for (String paramid : listOfIdentifiers) {
selection.add(paramid);
}
selection.addAll(listOfIdentifiers);
}
}

// Remove empty/null element from the selection
Iterator<String> iter = selection.iterator();
while (iter.hasNext()) {
Object element = iter.next();
if (element == null)
iter.remove();
}
selection.removeIf(Objects::isNull);

return selection.size();
}
Expand All @@ -241,14 +232,12 @@ public void selectAll(String type, ServiceContext context, UserSession session)

if (StringUtils.isNotEmpty(type)) {
JsonNode request = (JsonNode) session.getProperty(Geonet.Session.SEARCH_REQUEST + type);
if (request == null) {
return;
} else {
if (request != null) {
final SearchResponse searchResponse;
try {
EsSearchManager searchManager = context.getBean(EsSearchManager.class);
searchResponse = searchManager.query(request.get("query"), FIELDLIST_UUID, 0, maxhits);
List<String> uuidList = new ArrayList();
List<String> uuidList = new ArrayList<>();
ObjectMapper objectMapper = new ObjectMapper();
for (Hit h : (List<Hit>) searchResponse.hits().hits()) {
uuidList.add((String) objectMapper.convertValue(h.source(), Map.class).get(Geonet.IndexFieldNames.UUID));
Expand Down Expand Up @@ -293,7 +282,7 @@ public Set<String> getSelection(String type) {
Set<String> sel = selections.get(type);
if (sel == null) {
Set<String> MDSelection = Collections
.synchronizedSet(new HashSet<String>(0));
.synchronizedSet(new HashSet<>(0));
selections.put(type, MDSelection);
}
return selections.get(type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,4 +549,31 @@ void setCreativeCommons(ServiceContext context, String id, String licenseurl, St
* @param dest
*/
void replaceFiles(AbstractMetadata original, AbstractMetadata dest);

/**
* Get the metadata after preforming a search and replace on it.
* @param uuid The UUID of the metadata to search for.
* @param search The string to search for.
* @param replace The string to replace the search string with.
* @return The metadata with the search and replace applied.
*/
String selectOneWithSearchAndReplace(String uuid, String search, String replace);

/**
* Get the metadata after preforming a regex search and replace on it.
* @param uuid The UUID of the metadata to search for.
* @param search The string to search for.
* @param replace The string to replace the search string with.
* @return The metadata with the search and replace applied.
*/
String selectOneWithRegexSearchAndReplaceWithFlags(String uuid, String search, String replace, String flags);

/**
* Get the metadata after preforming a regex search and replace on it.
* @param uuid The UUID of the metadata to search for.
* @param search The string to search for.
* @param replace The string to replace the search string with.
* @return The metadata with the search and replace applied.
*/
String selectOneWithRegexSearchAndReplace(String uuid, String search, String replace);
}
Original file line number Diff line number Diff line change
Expand Up @@ -1029,4 +1029,19 @@ public void cloneFiles(AbstractMetadata original, AbstractMetadata dest) {
public void replaceFiles(AbstractMetadata original, AbstractMetadata dest) {
// Empty implementation for non-draft mode as not used
}

@Override
public String selectOneWithSearchAndReplace(String uuid, String search, String replace) {
return metadataRepository.selectOneWithSearchAndReplace(uuid, search, replace);
}

@Override
public String selectOneWithRegexSearchAndReplaceWithFlags(String uuid, String search, String replace, String flags) {
return metadataRepository.selectOneWithRegexSearchAndReplaceWithFlags(uuid, search, replace, flags);
}

@Override
public String selectOneWithRegexSearchAndReplace(String uuid, String search, String replace) {
return metadataRepository.selectOneWithRegexSearchAndReplace(uuid, search, replace);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ private void cloneStoreFileUploadRequests(AbstractMetadata original, AbstractMet
metadataFileUpload.setFileSize(mfu.getFileSize());
metadataFileUpload.setUploadDate(mfu.getUploadDate());
metadataFileUpload.setUserName(mfu.getUserName());
metadataFileUpload.setDeletedDate(mfu.getDeletedDate());

repo.save(metadataFileUpload);
}
Expand All @@ -691,4 +692,31 @@ public void setListOfStatusCreatingDraft(Set<String> listOfStatusCreatingDraft)
public Set<String> getListOfStatusCreatingDraft() {
return listOfStatusToTriggerDraftCreation;
}

@Override
public String selectOneWithSearchAndReplace(String uuid, String search, String replace) {
String updatedXml = metadataDraftRepository.selectOneWithSearchAndReplace(uuid, search, replace);
if (updatedXml == null) {
updatedXml = super.selectOneWithSearchAndReplace(uuid, search, replace);
}
return updatedXml;
}

@Override
public String selectOneWithRegexSearchAndReplaceWithFlags(String uuid, String search, String replace, String flags) {
String updatedXml = metadataDraftRepository.selectOneWithRegexSearchAndReplaceWithFlags(uuid, search, replace, flags);
if (updatedXml == null) {
updatedXml = super.selectOneWithRegexSearchAndReplaceWithFlags(uuid, search, replace, flags);
}
return updatedXml;
}

@Override
public String selectOneWithRegexSearchAndReplace(String uuid, String search, String replace) {
String updatedXml = metadataDraftRepository.selectOneWithRegexSearchAndReplace(uuid, search, replace);
if (updatedXml == null) {
updatedXml = super.selectOneWithRegexSearchAndReplace(uuid, search, replace);
}
return updatedXml;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
import org.springframework.context.ApplicationContext;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.fao.geonet.kernel.setting.Settings.SYSTEM_FEEDBACK_EMAIL;
import static org.fao.geonet.util.LocalizedEmailComponent.ComponentType.*;
Expand Down Expand Up @@ -330,22 +332,24 @@ protected void notify(List<User> userToNotify, MetadataStatus status) throws Exc
);
}

LocalizedEmail localizedEmail = new LocalizedEmail(false);
localizedEmail.addComponents(emailSubjectComponent, emailMessageComponent, emailSalutationComponent);

String subject = localizedEmail.getParsedSubject(feedbackLocales);

for (User user : userToNotify) {
LocalizedEmail localizedEmail = new LocalizedEmail(false);

String userName = Joiner.on(" ").skipNulls().join(user.getName(), user.getSurname());
//If we have a userName add the salutation
String message;
if (StringUtils.isEmpty(userName)) {
localizedEmail.addComponents(emailSubjectComponent, emailMessageComponent);

message = localizedEmail.getParsedMessage(feedbackLocales);
} else {
localizedEmail.addComponents(emailSubjectComponent, emailMessageComponent, emailSalutationComponent);

Map<String, String> replacements = new HashMap<>();
replacements.put("{{userName}}", userName);
message = localizedEmail.getParsedMessage(feedbackLocales, replacements);
}
String subject = localizedEmail.getParsedSubject(feedbackLocales);
sendEmail(user.getEmail(), subject, message);
}
}
Expand Down Expand Up @@ -449,7 +453,9 @@ public static List<User> getUserToNotify(StatusValueNotificationLevel notificati
}
}
}
return users;

// Filter out users without email
return users.stream().filter(u -> StringUtils.isNotEmpty(u.getEmail())).collect(Collectors.toList());
}

public static List<Group> getGroupToNotify(StatusValueNotificationLevel notificationLevel, List<String> groupNames) {
Expand Down
Loading

0 comments on commit c65cc71

Please sign in to comment.