diff --git a/src/main/java/org/phoebus/channelfinder/exceptions/StorageException.java b/src/main/java/org/phoebus/channelfinder/exceptions/StorageException.java new file mode 100644 index 00000000..1fc968e9 --- /dev/null +++ b/src/main/java/org/phoebus/channelfinder/exceptions/StorageException.java @@ -0,0 +1,12 @@ +package org.phoebus.channelfinder.exceptions; + +public class StorageException extends RuntimeException { + + public StorageException(String message) { + super(message); + } + + public StorageException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/phoebus/channelfinder/repository/ChannelRepository.java b/src/main/java/org/phoebus/channelfinder/repository/ChannelRepository.java index 29689d2a..0c77bc21 100644 --- a/src/main/java/org/phoebus/channelfinder/repository/ChannelRepository.java +++ b/src/main/java/org/phoebus/channelfinder/repository/ChannelRepository.java @@ -57,20 +57,16 @@ import org.phoebus.channelfinder.entity.Scroll; import org.phoebus.channelfinder.entity.SearchResult; import org.phoebus.channelfinder.entity.Tag; +import org.phoebus.channelfinder.exceptions.ChannelValidationException; +import org.phoebus.channelfinder.exceptions.StorageException; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; import org.springframework.data.repository.CrudRepository; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Repository; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.server.ResponseStatusException; // Jackson 2 required by elasticsearch-java 8.x JacksonJsonpMapper — migrate with ES 9 @Repository -@Configuration public class ChannelRepository implements CrudRepository { private static final Logger logger = Logger.getLogger(ChannelRepository.class.getName()); @@ -126,7 +122,7 @@ public Channel index(Channel channel) { } catch (Exception e) { String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_CHANNEL, channel.toLog()); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message, e); } return null; } @@ -176,8 +172,7 @@ channel, new JacksonJsonpMapper(objectMapper))))) } catch (IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_CHANNELS, chunk); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException( - HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message, e); } return Collections.emptyList(); })); @@ -218,7 +213,7 @@ public Channel save(String channelName, Channel channel) { } catch (Exception e) { String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_CHANNEL, channel.toLog()); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message, e); } return null; } @@ -310,8 +305,7 @@ public Iterable saveAll(Iterable channels) { String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_CHANNELS, channels); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException( - HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message, e); } return Collections.emptyList(); })); @@ -354,7 +348,7 @@ public Optional findById(String channelName) { } catch (ElasticsearchException | IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_FIND_CHANNEL, channelName); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.NOT_FOUND, message, null); + throw new StorageException(message, e); } } @@ -383,8 +377,7 @@ public boolean existsByIds(List channelIds) { .containsAll(channelIds); } catch (ElasticsearchException | IOException e) { logger.log(Level.SEVERE, TextUtil.FAILED_TO_FIND_ALL_CHANNELS, e); - throw new ResponseStatusException( - HttpStatus.INTERNAL_SERVER_ERROR, TextUtil.FAILED_TO_FIND_ALL_CHANNELS, null); + throw new StorageException(TextUtil.FAILED_TO_FIND_ALL_CHANNELS, e); } } @@ -404,7 +397,7 @@ public boolean existsById(String channelName) { String message = MessageFormat.format(TextUtil.FAILED_TO_CHECK_IF_CHANNEL_EXISTS, channelName); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message, e); } } @@ -440,14 +433,13 @@ public List findAllById(Iterable channelIds) { return response.hits().hits().stream().map(Hit::source).collect(Collectors.toList()); } catch (ElasticsearchException | IOException e) { logger.log(Level.SEVERE, TextUtil.FAILED_TO_FIND_ALL_CHANNELS, e); - throw new ResponseStatusException( - HttpStatus.INTERNAL_SERVER_ERROR, TextUtil.FAILED_TO_FIND_ALL_CHANNELS, null); + throw new StorageException(TextUtil.FAILED_TO_FIND_ALL_CHANNELS, e); } } @Override public long count() { - return this.count(new LinkedMultiValueMap<>()); + return this.count(Map.of()); } /** @@ -468,7 +460,7 @@ public void deleteById(String channelName) { } catch (ElasticsearchException | IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_DELETE_CHANNEL, channelName); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message, e); } } @@ -516,7 +508,7 @@ public void deleteAll() { * @param searchParameters channel search parameters * @return matching channels */ - public SearchResult search(MultiValueMap searchParameters) { + public SearchResult search(Map> searchParameters) { BuiltQuery builtQuery = getBuiltQuery(searchParameters); Integer finalSize = builtQuery.size; Integer finalFrom = builtQuery.from; @@ -527,7 +519,7 @@ public SearchResult search(MultiValueMap searchParameters) { TextUtil.SEARCH_FAILED_CAUSE, searchParameters, "Max search window exceeded, use the " + scrollResourceUri + " api."); - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, message); + throw new ChannelValidationException(message); } try { @@ -554,11 +546,11 @@ public SearchResult search(MultiValueMap searchParameters) { String message = MessageFormat.format(TextUtil.SEARCH_FAILED_CAUSE, searchParameters, e.getMessage()); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, e); + throw new StorageException(message, e); } } - private BuiltQuery getBuiltQuery(MultiValueMap searchParameters) { + private BuiltQuery getBuiltQuery(Map> searchParameters) { BoolQuery.Builder boolQuery = new BoolQuery.Builder(); int size = esService.getES_QUERY_SIZE(); int from = 0; @@ -726,7 +718,7 @@ private record BuiltQuery( * @param searchParameters channel search parameters * @return count of the number of matches to the provided query */ - public long count(MultiValueMap searchParameters) { + public long count(Map> searchParameters) { BuiltQuery builtQuery = getBuiltQuery(searchParameters); try { @@ -742,7 +734,7 @@ public long count(MultiValueMap searchParameters) { String message = MessageFormat.format(TextUtil.COUNT_FAILED_CAUSE, searchParameters, e.getMessage()); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, e); + throw new StorageException(message, e); } } @@ -754,9 +746,7 @@ public long count(MultiValueMap searchParameters) { * @return count of the number of matches to the provided query */ public long countByProperty(String propertyName, String propertyValue) { - MultiValueMap params = new LinkedMultiValueMap<>(); - params.add(propertyName, propertyValue == null ? "*" : propertyValue); - return this.count(params); + return this.count(Map.of(propertyName, List.of(propertyValue == null ? "*" : propertyValue))); } /** @@ -766,9 +756,7 @@ public long countByProperty(String propertyName, String propertyValue) { * @return count of the number of matches to the provided query */ public long countByTag(String tagName) { - MultiValueMap params = new LinkedMultiValueMap<>(); - params.add("~tag", tagName); - return this.count(params); + return this.count(Map.of("~tag", List.of(tagName))); } /** @@ -779,7 +767,7 @@ public long countByTag(String tagName) { * @param searchParameters channel search parameters * @return next page with its cursor */ - public Scroll scroll(String scrollId, MultiValueMap searchParameters) { + public Scroll scroll(String scrollId, Map> searchParameters) { BuiltQuery builtQuery = getBuiltQuery(searchParameters); try { SearchRequest.Builder builder = @@ -800,7 +788,7 @@ public Scroll scroll(String scrollId, MultiValueMap searchParame } catch (IOException | ElasticsearchException e) { String message = MessageFormat.format(TextUtil.SEARCH_FAILED_CAUSE, searchParameters, e.getMessage()); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, e); + throw new StorageException(message, e); } } diff --git a/src/main/java/org/phoebus/channelfinder/repository/PropertyRepository.java b/src/main/java/org/phoebus/channelfinder/repository/PropertyRepository.java index 8c1792c7..f4ba7445 100644 --- a/src/main/java/org/phoebus/channelfinder/repository/PropertyRepository.java +++ b/src/main/java/org/phoebus/channelfinder/repository/PropertyRepository.java @@ -26,7 +26,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.text.MessageFormat; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; @@ -36,20 +38,15 @@ import org.phoebus.channelfinder.entity.Channel; import org.phoebus.channelfinder.entity.Property; import org.phoebus.channelfinder.entity.Property.OnlyNameOwnerProperty; +import org.phoebus.channelfinder.exceptions.StorageException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Configuration; import org.springframework.data.repository.CrudRepository; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Repository; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.server.ResponseStatusException; // Jackson 2 required by elasticsearch-java 8.x JacksonJsonpMapper — migrate with ES 9 @Repository -@Configuration public class PropertyRepository implements CrudRepository { private static final Logger logger = Logger.getLogger(PropertyRepository.class.getName()); @@ -108,7 +105,7 @@ public List indexAll(List properties) { } catch (IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_PROPERTIES, properties); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } return null; } @@ -142,7 +139,7 @@ public S save(String propertyName, S property) { } catch (Exception e) { String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_PROPERTY, property.toLog()); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } return null; } @@ -197,7 +194,7 @@ public Iterable saveAll(Iterable properties) { } catch (IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_UPDATE_SAVE_PROPERTIES, properties); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } return null; } @@ -232,9 +229,8 @@ public Optional findById(String propertyName, boolean withChannels) { logger.log( Level.CONFIG, () -> MessageFormat.format(TextUtil.PROPERTY_FOUND, property.getName())); if (withChannels) { - MultiValueMap params = new LinkedMultiValueMap<>(); - params.add(property.getName(), "*"); - property.setChannels(channelRepository.search(params).channels()); + property.setChannels( + channelRepository.search(Map.of(property.getName(), List.of("*"))).channels()); } return Optional.of(property); } else { @@ -245,7 +241,7 @@ public Optional findById(String propertyName, boolean withChannels) { } catch (ElasticsearchException | IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_FIND_PROPERTY, propertyName); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.NOT_FOUND, message, null); + throw new StorageException(message); } } @@ -258,7 +254,7 @@ public boolean existsById(String id) { } catch (ElasticsearchException | IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_CHECK_IF_PROPERTY_EXISTS, id); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } } @@ -280,8 +276,7 @@ public Iterable findAll() { return response.hits().hits().stream().map(Hit::source).toList(); } catch (ElasticsearchException | IOException e) { logger.log(Level.SEVERE, TextUtil.FAILED_TO_FIND_ALL_PROPERTIES, e); - throw new ResponseStatusException( - HttpStatus.INTERNAL_SERVER_ERROR, TextUtil.FAILED_TO_FIND_ALL_PROPERTIES, null); + throw new StorageException(TextUtil.FAILED_TO_FIND_ALL_PROPERTIES); } } @@ -306,8 +301,7 @@ public List findAllById(Iterable propertyIds) { return response.hits().hits().stream().map(Hit::source).toList(); } catch (ElasticsearchException | IOException e) { logger.log(Level.SEVERE, TextUtil.FAILED_TO_FIND_ALL_PROPERTIES, e); - throw new ResponseStatusException( - HttpStatus.INTERNAL_SERVER_ERROR, TextUtil.FAILED_TO_FIND_ALL_PROPERTIES, null); + throw new StorageException(TextUtil.FAILED_TO_FIND_ALL_PROPERTIES); } } @@ -322,7 +316,7 @@ public long count() { String message = MessageFormat.format(TextUtil.COUNT_FAILED_CAUSE, "", e.getMessage()); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, e); + throw new StorageException(message, e); } } @@ -346,8 +340,8 @@ public void deleteById(String propertyName) { // Remove the Property from Channels BulkRequest.Builder br = new BulkRequest.Builder().refresh(Refresh.True); - MultiValueMap params = new LinkedMultiValueMap<>(); - params.add(propertyName, "*"); + Map> params = new LinkedHashMap<>(); + params.put(propertyName, List.of("*")); List channels = channelRepository.search(params).channels(); while (channels.size() > 0) { for (Channel channel : channels) { @@ -380,15 +374,15 @@ public void deleteById(String propertyName) { } catch (IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_DELETE_PROPERTY, propertyName); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } - params.set("~search_after", channels.get(channels.size() - 1).getName()); + params.put("~search_after", List.of(channels.get(channels.size() - 1).getName())); channels = channelRepository.search(params).channels(); } } catch (ElasticsearchException | IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_DELETE_PROPERTY, propertyName); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } } diff --git a/src/main/java/org/phoebus/channelfinder/repository/TagRepository.java b/src/main/java/org/phoebus/channelfinder/repository/TagRepository.java index da9ae87a..8649b954 100644 --- a/src/main/java/org/phoebus/channelfinder/repository/TagRepository.java +++ b/src/main/java/org/phoebus/channelfinder/repository/TagRepository.java @@ -27,7 +27,9 @@ import java.io.IOException; import java.text.MessageFormat; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; @@ -37,20 +39,15 @@ import org.phoebus.channelfinder.entity.Channel; import org.phoebus.channelfinder.entity.Tag; import org.phoebus.channelfinder.entity.Tag.OnlyTag; +import org.phoebus.channelfinder.exceptions.StorageException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Configuration; import org.springframework.data.repository.CrudRepository; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Repository; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.server.ResponseStatusException; // Jackson 2 required by elasticsearch-java 8.x JacksonJsonpMapper — migrate with ES 9 @Repository -@Configuration public class TagRepository implements CrudRepository { private static final Logger logger = Logger.getLogger(TagRepository.class.getName()); @@ -110,7 +107,7 @@ public List indexAll(List tags) { } catch (IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_TAGS, tags); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } return Collections.emptyList(); } @@ -141,7 +138,7 @@ public S save(String tagName, S tag) { } catch (ElasticsearchException | IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_UPDATE_SAVE_TAG, tag.toLog()); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } return null; } @@ -192,7 +189,7 @@ public Iterable saveAll(Iterable tags) { } catch (IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_TAGS, tags); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } return null; } @@ -224,9 +221,8 @@ public Optional findById(String tagId, boolean withChannels) { Tag tag = response.source(); logger.log(Level.CONFIG, () -> MessageFormat.format(TextUtil.TAG_FOUND, tag.getName())); if (withChannels) { - MultiValueMap params = new LinkedMultiValueMap<>(); - params.add("~tag", tag.getName()); - tag.setChannels(channelRepository.search(params).channels()); + tag.setChannels( + channelRepository.search(Map.of("~tag", List.of(tag.getName()))).channels()); } return Optional.of(tag); } else { @@ -236,7 +232,7 @@ public Optional findById(String tagId, boolean withChannels) { } catch (ElasticsearchException | IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_FIND_TAG, tagId); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.NOT_FOUND, message, null); + throw new StorageException(message); } } @@ -249,7 +245,7 @@ public boolean existsById(String id) { } catch (ElasticsearchException | IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_CHECK_IF_TAG_EXISTS, id); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } } @@ -271,8 +267,7 @@ public Iterable findAll() { return response.hits().hits().stream().map(Hit::source).toList(); } catch (ElasticsearchException | IOException e) { logger.log(Level.SEVERE, TextUtil.FAILED_TO_FIND_ALL_TAGS, e); - throw new ResponseStatusException( - HttpStatus.INTERNAL_SERVER_ERROR, TextUtil.FAILED_TO_FIND_ALL_TAGS, null); + throw new StorageException(TextUtil.FAILED_TO_FIND_ALL_TAGS); } } @@ -296,8 +291,7 @@ public List findAllById(Iterable tagIds) { return response.hits().hits().stream().map(Hit::source).toList(); } catch (ElasticsearchException | IOException e) { logger.log(Level.SEVERE, TextUtil.FAILED_TO_FIND_ALL_TAGS, e); - throw new ResponseStatusException( - HttpStatus.INTERNAL_SERVER_ERROR, TextUtil.FAILED_TO_FIND_ALL_TAGS, null); + throw new StorageException(TextUtil.FAILED_TO_FIND_ALL_TAGS); } } @@ -312,7 +306,7 @@ public long count() { String message = MessageFormat.format(TextUtil.COUNT_FAILED_CAUSE, "", e.getMessage()); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, e); + throw new StorageException(message, e); } } @@ -333,8 +327,8 @@ public void deleteById(String tagName) { logger.log(Level.CONFIG, () -> MessageFormat.format(TextUtil.DELETE_TAG, tagName)); } BulkRequest.Builder br = new BulkRequest.Builder().refresh(Refresh.True); - MultiValueMap params = new LinkedMultiValueMap<>(); - params.add("~tag", tagName); + Map> params = new LinkedHashMap<>(); + params.put("~tag", List.of(tagName)); List channels = channelRepository.search(params).channels(); while (!channels.isEmpty()) { @@ -367,16 +361,16 @@ public void deleteById(String tagName) { } catch (IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_DELETE_TAG, tagName); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } - params.set("~search_after", channels.get(channels.size() - 1).getName()); + params.put("~search_after", List.of(channels.get(channels.size() - 1).getName())); channels = channelRepository.search(params).channels(); } } catch (ElasticsearchException | IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_DELETE_TAG, tagName); logger.log(Level.SEVERE, message, e); - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); + throw new StorageException(message); } } diff --git a/src/main/java/org/phoebus/channelfinder/service/ChannelFinderEpicsService.java b/src/main/java/org/phoebus/channelfinder/service/ChannelFinderEpicsService.java index d553b0a1..4c693927 100644 --- a/src/main/java/org/phoebus/channelfinder/service/ChannelFinderEpicsService.java +++ b/src/main/java/org/phoebus/channelfinder/service/ChannelFinderEpicsService.java @@ -4,6 +4,7 @@ import jakarta.annotation.PreDestroy; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -24,8 +25,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.ComponentScan; import org.springframework.stereotype.Service; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; /** * A pva RPC service for channelfinder @@ -106,7 +105,7 @@ public HandlerQuery(PVAStructure args, ChannelRepository channelRepository) { public PVAStructure run() throws MustBeArrayException { - MultiValueMap searchParameters = new LinkedMultiValueMap<>(); + Map> searchParameters = new LinkedHashMap<>(); PVAURI uri = PVAURI.fromStructure(args); Map query; try { diff --git a/src/main/java/org/phoebus/channelfinder/service/ChannelProcessorService.java b/src/main/java/org/phoebus/channelfinder/service/ChannelProcessorService.java index 846b9684..e13ce37f 100644 --- a/src/main/java/org/phoebus/channelfinder/service/ChannelProcessorService.java +++ b/src/main/java/org/phoebus/channelfinder/service/ChannelProcessorService.java @@ -1,7 +1,9 @@ package org.phoebus.channelfinder.service; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Spliterator; @@ -20,8 +22,6 @@ import org.springframework.core.task.TaskExecutor; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; @Service public class ChannelProcessorService { @@ -57,12 +57,12 @@ public long processAllChannels() { "User does not have the proper authorization to perform this operation: /process/all"); } logger.log(Level.INFO, "Calling processor on ALL channels in ChannelFinder"); - MultiValueMap searchParameters = new LinkedMultiValueMap<>(); - searchParameters.add("~name", "*"); + Map> searchParameters = new LinkedHashMap<>(); + searchParameters.put("~name", List.of("*")); return processChannelsByQuery(searchParameters); } - public long processChannelsByQuery(MultiValueMap allRequestParams) { + public long processChannelsByQuery(Map> allRequestParams) { long channelCount = 0; Scroll scrollResult = channelScrollService.search(null, allRequestParams); channelCount += scrollResult.getChannels().size(); diff --git a/src/main/java/org/phoebus/channelfinder/service/ChannelScrollService.java b/src/main/java/org/phoebus/channelfinder/service/ChannelScrollService.java index 68369ace..3ae08cbb 100644 --- a/src/main/java/org/phoebus/channelfinder/service/ChannelScrollService.java +++ b/src/main/java/org/phoebus/channelfinder/service/ChannelScrollService.java @@ -1,9 +1,10 @@ package org.phoebus.channelfinder.service; +import java.util.List; +import java.util.Map; import org.phoebus.channelfinder.entity.Scroll; import org.phoebus.channelfinder.repository.ChannelRepository; import org.springframework.stereotype.Service; -import org.springframework.util.MultiValueMap; @Service public class ChannelScrollService { @@ -14,7 +15,7 @@ public ChannelScrollService(ChannelRepository channelRepository) { this.channelRepository = channelRepository; } - public Scroll search(String scrollId, MultiValueMap searchParameters) { + public Scroll search(String scrollId, Map> searchParameters) { return channelRepository.scroll(scrollId, searchParameters); } } diff --git a/src/main/java/org/phoebus/channelfinder/service/ChannelService.java b/src/main/java/org/phoebus/channelfinder/service/ChannelService.java index c3b874fc..0fadcbe6 100644 --- a/src/main/java/org/phoebus/channelfinder/service/ChannelService.java +++ b/src/main/java/org/phoebus/channelfinder/service/ChannelService.java @@ -25,7 +25,6 @@ import org.phoebus.channelfinder.service.AuthorizationService.ROLES; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; -import org.springframework.util.MultiValueMap; @Service public class ChannelService { @@ -52,15 +51,15 @@ public ChannelService( this.channelProcessorService = channelProcessorService; } - public List query(MultiValueMap allRequestParams) { + public List query(Map> allRequestParams) { return channelRepository.search(allRequestParams).channels(); } - public SearchResult combinedQuery(MultiValueMap allRequestParams) { + public SearchResult combinedQuery(Map> allRequestParams) { return channelRepository.search(allRequestParams); } - public long queryCount(MultiValueMap allRequestParams) { + public long queryCount(Map> allRequestParams) { return channelRepository.count(allRequestParams); } diff --git a/src/main/java/org/phoebus/channelfinder/service/MetricsService.java b/src/main/java/org/phoebus/channelfinder/service/MetricsService.java index e064d4a9..9e5cc3c4 100644 --- a/src/main/java/org/phoebus/channelfinder/service/MetricsService.java +++ b/src/main/java/org/phoebus/channelfinder/service/MetricsService.java @@ -7,6 +7,7 @@ import jakarta.annotation.PostConstruct; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -20,8 +21,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; @Service public class MetricsService { @@ -46,7 +45,7 @@ public class MetricsService { private final TagRepository tagRepository; private final MeterRegistry meterRegistry; - private Map, AtomicLong> propertyMetrics; + private Map>, AtomicLong> propertyMetrics; private Map tagMetrics; @Value("${metrics.tags}") @@ -84,8 +83,7 @@ public MetricsService( @PostConstruct private void registerGaugeMetrics() { - Gauge.builder( - CF_TOTAL_CHANNEL_COUNT, () -> channelRepository.count(new LinkedMultiValueMap<>())) + Gauge.builder(CF_TOTAL_CHANNEL_COUNT, () -> channelRepository.count(Map.of())) .description(METRIC_DESCRIPTION_TOTAL_CHANNEL_COUNT) .register(meterRegistry); Gauge.builder(CF_PROPERTY_COUNT, propertyRepository::count) @@ -113,28 +111,28 @@ private void registerTagMetrics() { } } - public static List> generateAllMultiValueMaps( + public static List>> generateAllMultiValueMaps( Map> properties) { - List> allMultiValueMaps = new ArrayList<>(); + List>> allQueryParams = new ArrayList<>(); if (properties.isEmpty()) { return List.of(); } List>> entries = new ArrayList<>(properties.entrySet()); - generateCombinations(entries, 0, new LinkedMultiValueMap<>(), allMultiValueMaps); + generateCombinations(entries, 0, new LinkedHashMap<>(), allQueryParams); - return allMultiValueMaps; + return allQueryParams; } private static void generateCombinations( List>> entries, int index, - MultiValueMap currentMap, - List> allMultiValueMaps) { + Map> currentMap, + List>> allQueryParams) { if (index == entries.size()) { - allMultiValueMaps.add(new LinkedMultiValueMap<>(currentMap)); + allQueryParams.add(new LinkedHashMap<>(currentMap)); return; } @@ -142,33 +140,27 @@ private static void generateCombinations( String key = currentEntry.getKey(); List values = currentEntry.getValue(); - // Add the other options for (String value : values) { - LinkedMultiValueMap nextMapWithValue = new LinkedMultiValueMap<>(currentMap); + Map> nextMap = new LinkedHashMap<>(currentMap); if (value.startsWith(NEGATE)) { - nextMapWithValue.add(key + NEGATE, value.substring(1)); + nextMap.computeIfAbsent(key + NEGATE, k -> new ArrayList<>()).add(value.substring(1)); } else { - nextMapWithValue.add(key, value); + nextMap.computeIfAbsent(key, k -> new ArrayList<>()).add(value); } - generateCombinations(entries, index + 1, nextMapWithValue, allMultiValueMaps); + generateCombinations(entries, index + 1, nextMap, allQueryParams); } } - private List metricTagsFromMultiValueMap(MultiValueMap multiValueMap) { + private List metricTagsFrom(Map> queryParams) { List metricTags = new ArrayList<>(); - for (Map.Entry entry : multiValueMap.toSingleValueMap().entrySet()) { + for (Map.Entry> entry : queryParams.entrySet()) { + String firstValue = entry.getValue().isEmpty() ? "" : entry.getValue().get(0); if (entry.getKey().endsWith(NEGATE)) { - if (entry.getValue().equals("*")) { - metricTags.add( - new ImmutableTag(entry.getKey().substring(0, entry.getKey().length() - 1), NOT_SET)); - } else { - metricTags.add( - new ImmutableTag( - entry.getKey().substring(0, entry.getKey().length() - 1), - NEGATE + entry.getValue())); - } + String tagKey = entry.getKey().substring(0, entry.getKey().length() - 1); + metricTags.add( + new ImmutableTag(tagKey, firstValue.equals("*") ? NOT_SET : NEGATE + firstValue)); } else { - metricTags.add(new ImmutableTag(entry.getKey(), entry.getValue())); + metricTags.add(new ImmutableTag(entry.getKey(), firstValue)); } } return metricTags; @@ -177,7 +169,7 @@ private List metricTagsFromMultiValueMap(MultiValueMap mult private void registerPropertyMetrics() { Map> properties = parseProperties(); - List> combinations = generateAllMultiValueMaps(properties); + List>> combinations = generateAllMultiValueMaps(properties); propertyMetrics = combinations.stream() @@ -187,7 +179,7 @@ private void registerPropertyMetrics() { map -> Gauge.builder(CF_CHANNEL_COUNT, propertyMetrics, m -> m.get(map).doubleValue()) .description(METRIC_DESCRIPTION_CHANNEL_COUNT) - .tags(metricTagsFromMultiValueMap(map)) + .tags(metricTagsFrom(map)) .register(meterRegistry)); } @@ -198,7 +190,7 @@ private void updateTagMetrics() { } private void updatePropertyMetrics() { - for (Map.Entry, AtomicLong> propertyMetricEntry : + for (Map.Entry>, AtomicLong> propertyMetricEntry : propertyMetrics.entrySet()) { propertyMetricEntry.getValue().set(channelRepository.count(propertyMetricEntry.getKey())); } diff --git a/src/main/java/org/phoebus/channelfinder/service/PropertyService.java b/src/main/java/org/phoebus/channelfinder/service/PropertyService.java index 95dfd95b..d9e6614c 100644 --- a/src/main/java/org/phoebus/channelfinder/service/PropertyService.java +++ b/src/main/java/org/phoebus/channelfinder/service/PropertyService.java @@ -157,7 +157,7 @@ public Property update(String propertyName, Property property) { propagateRenameToChannels(propertyName, updated, chans); if (!property.getChannels().isEmpty()) { - List chanList = saveAndRetainProperty(property.getChannels(), propertyName); + List chanList = saveAndRetainProperty(property.getChannels(), updated.getName()); if (!chanList.isEmpty()) updated.setChannels(chanList); } diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/V0ExceptionHandler.java b/src/main/java/org/phoebus/channelfinder/web/v0/V0ExceptionHandler.java index ef3e3a17..f92db4ef 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/V0ExceptionHandler.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/V0ExceptionHandler.java @@ -6,6 +6,7 @@ import org.phoebus.channelfinder.exceptions.ChannelValidationException; import org.phoebus.channelfinder.exceptions.PropertyNotFoundException; import org.phoebus.channelfinder.exceptions.PropertyValidationException; +import org.phoebus.channelfinder.exceptions.StorageException; import org.phoebus.channelfinder.exceptions.TagNotFoundException; import org.phoebus.channelfinder.exceptions.TagValidationException; import org.phoebus.channelfinder.exceptions.UnauthorizedException; @@ -86,6 +87,13 @@ public ResponseStatusException handleMessageNotReadable(HttpMessageNotReadableEx return new ResponseStatusException(HttpStatus.BAD_REQUEST, "Malformed request body"); } + @ExceptionHandler(StorageException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ResponseStatusException handleStorage(StorageException ex) { + logger.log(Level.SEVERE, ex.getMessage(), ex); + return new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage()); + } + @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ResponseStatusException handleUnexpected(Exception ex) { diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannel.java b/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannel.java index 4295d710..88c7197c 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannel.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannel.java @@ -10,8 +10,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import java.util.List; -import org.phoebus.channelfinder.entity.Channel; -import org.phoebus.channelfinder.entity.SearchResult; +import org.phoebus.channelfinder.web.v0.dto.ChannelDto; +import org.phoebus.channelfinder.web.v0.dto.SearchResultDto; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -36,7 +36,8 @@ public interface IChannel { responseCode = "200", description = "List of channels", content = - @Content(array = @ArraySchema(schema = @Schema(implementation = Channel.class)))), + @Content( + array = @ArraySchema(schema = @Schema(implementation = ChannelDto.class)))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -47,7 +48,7 @@ public interface IChannel { content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @GetMapping - List query( + List query( @Parameter(description = SEARCH_PARAM_DESCRIPTION) @RequestParam MultiValueMap allRequestParams); @@ -64,7 +65,8 @@ List query( description = "The number of matches for the query, and the first 10k channels", content = @Content( - array = @ArraySchema(schema = @Schema(implementation = SearchResult.class)))), + array = + @ArraySchema(schema = @Schema(implementation = SearchResultDto.class)))), @ApiResponse( responseCode = "400", description = "Invalid request - response size exceeded", @@ -75,7 +77,7 @@ List query( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @GetMapping("/combined") - SearchResult combinedQuery( + SearchResultDto combinedQuery( @Parameter(description = SEARCH_PARAM_DESCRIPTION) @RequestParam MultiValueMap allRequestParams); @@ -110,14 +112,14 @@ long queryCount( @ApiResponse( responseCode = "200", description = "Channel with the specified name", - content = @Content(schema = @Schema(implementation = Channel.class))), + content = @Content(schema = @Schema(implementation = ChannelDto.class))), @ApiResponse( responseCode = "404", description = "Channel not found", content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @GetMapping("/{channelName}") - Channel read(@PathVariable("channelName") String channelName); + ChannelDto read(@PathVariable("channelName") String channelName); @Operation( summary = "Create or replace a channel", @@ -129,7 +131,7 @@ long queryCount( @ApiResponse( responseCode = "200", description = "The created/replaced channel", - content = @Content(schema = @Schema(implementation = Channel.class))), + content = @Content(schema = @Schema(implementation = ChannelDto.class))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -148,7 +150,8 @@ long queryCount( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PutMapping("/{channelName}") - Channel create(@PathVariable("channelName") String channelName, @RequestBody Channel channel); + ChannelDto create( + @PathVariable("channelName") String channelName, @RequestBody ChannelDto channel); @Operation( summary = "Create or replace multiple channels", @@ -161,7 +164,8 @@ long queryCount( responseCode = "200", description = "The created/replaced channels", content = - @Content(array = @ArraySchema(schema = @Schema(implementation = Channel.class)))), + @Content( + array = @ArraySchema(schema = @Schema(implementation = ChannelDto.class)))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -180,7 +184,7 @@ long queryCount( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PutMapping - Iterable create(@RequestBody Iterable channels); + Iterable create(@RequestBody Iterable channels); @Operation( summary = "Update a channel", @@ -193,7 +197,7 @@ long queryCount( @ApiResponse( responseCode = "200", description = "The updated channel", - content = @Content(schema = @Schema(implementation = Channel.class))), + content = @Content(schema = @Schema(implementation = ChannelDto.class))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -212,7 +216,8 @@ long queryCount( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PostMapping("/{channelName}") - Channel update(@PathVariable("channelName") String channelName, @RequestBody Channel channel); + ChannelDto update( + @PathVariable("channelName") String channelName, @RequestBody ChannelDto channel); @Operation( summary = "Update multiple channels", @@ -225,7 +230,7 @@ long queryCount( @ApiResponse( responseCode = "200", description = "The updated channels", - content = @Content(schema = @Schema(implementation = Channel.class))), + content = @Content(schema = @Schema(implementation = ChannelDto.class))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -244,7 +249,7 @@ long queryCount( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PostMapping() - Iterable update(@RequestBody Iterable channels); + Iterable update(@RequestBody Iterable channels); @Operation( summary = "Delete a channel", diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannelProcessor.java b/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannelProcessor.java index 417a02b9..e8178040 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannelProcessor.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannelProcessor.java @@ -10,8 +10,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import java.util.List; -import org.phoebus.channelfinder.entity.Channel; import org.phoebus.channelfinder.service.model.archiver.ChannelProcessorInfo; +import org.phoebus.channelfinder.web.v0.dto.ChannelDto; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -92,7 +92,7 @@ long processChannels( MultiValueMap allRequestParams); @PutMapping("/process/channels") - void processChannels(List channels); + void processChannels(List channels); @Operation(summary = "Set if the processor is enabled or not") @PutMapping( diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannelScroll.java b/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannelScroll.java index f0a77e4e..ccc7de93 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannelScroll.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/api/IChannelScroll.java @@ -7,7 +7,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import org.phoebus.channelfinder.common.CFResourceDescriptors; -import org.phoebus.channelfinder.entity.Scroll; +import org.phoebus.channelfinder.web.v0.dto.ScrollDto; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -26,14 +26,14 @@ public interface IChannelScroll { @ApiResponse( responseCode = "200", description = "Scroll that contains a collection of channel instances", - content = @Content(schema = @Schema(implementation = Scroll.class))), + content = @Content(schema = @Schema(implementation = ScrollDto.class))), @ApiResponse( responseCode = "500", description = "Error while trying to list channels", content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @GetMapping - Scroll query( + ScrollDto query( @Parameter(description = CFResourceDescriptors.SEARCH_PARAM_DESCRIPTION) @RequestParam MultiValueMap allRequestParams); @@ -48,14 +48,14 @@ Scroll query( @ApiResponse( responseCode = "200", description = "Scroll List of channels", - content = @Content(schema = @Schema(implementation = Scroll.class))), + content = @Content(schema = @Schema(implementation = ScrollDto.class))), @ApiResponse( responseCode = "500", description = "Error while trying to list channels", content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @GetMapping("/{scrollId}") - Scroll query( + ScrollDto query( @Parameter(description = "Scroll ID from previous query") @PathVariable("scrollId") String scrollId, @Parameter(description = CFResourceDescriptors.SEARCH_PARAM_DESCRIPTION) @RequestParam diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/api/IProperty.java b/src/main/java/org/phoebus/channelfinder/web/v0/api/IProperty.java index a6b707ac..e5757774 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/api/IProperty.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/api/IProperty.java @@ -6,7 +6,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -import org.phoebus.channelfinder.entity.Property; +import org.phoebus.channelfinder.web.v0.dto.PropertyDto; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -29,14 +29,15 @@ public interface IProperty { responseCode = "200", description = "List of properties", content = - @Content(array = @ArraySchema(schema = @Schema(implementation = Property.class)))), + @Content( + array = @ArraySchema(schema = @Schema(implementation = PropertyDto.class)))), @ApiResponse( responseCode = "500", description = "Error while listing properties", content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @GetMapping - Iterable list(); + Iterable list(); @Operation( summary = "Get property by name", @@ -48,14 +49,14 @@ public interface IProperty { @ApiResponse( responseCode = "200", description = "Fetch property by propertyName", - content = @Content(schema = @Schema(implementation = Property.class))), + content = @Content(schema = @Schema(implementation = PropertyDto.class))), @ApiResponse( responseCode = "404", description = "Property not found", content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @GetMapping("/{propertyName}") - Property read( + PropertyDto read( @PathVariable("propertyName") String propertyName, @RequestParam(value = "withChannels", defaultValue = "true") boolean withChannels); @@ -69,7 +70,7 @@ Property read( @ApiResponse( responseCode = "200", description = "Property created", - content = @Content(schema = @Schema(implementation = Property.class))), + content = @Content(schema = @Schema(implementation = PropertyDto.class))), @ApiResponse( responseCode = "401", description = "Unauthorized", @@ -84,8 +85,8 @@ Property read( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PutMapping("/{propertyName}") - Property create( - @PathVariable("propertyName") String propertyName, @RequestBody Property property); + PropertyDto create( + @PathVariable("propertyName") String propertyName, @RequestBody PropertyDto property); @Operation( summary = "Create multiple properties", @@ -97,7 +98,7 @@ Property create( @ApiResponse( responseCode = "200", description = "Properties created", - content = @Content(schema = @Schema(implementation = Property.class))), + content = @Content(schema = @Schema(implementation = PropertyDto.class))), @ApiResponse( responseCode = "401", description = "Unauthorized", @@ -108,7 +109,7 @@ Property create( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PutMapping() - Iterable create(@RequestBody Iterable properties); + Iterable create(@RequestBody Iterable properties); @Operation( summary = "Add property to a single channel", @@ -121,7 +122,7 @@ Property create( @ApiResponse( responseCode = "200", description = "Property added to the channel", - content = @Content(schema = @Schema(implementation = Property.class))), + content = @Content(schema = @Schema(implementation = PropertyDto.class))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -140,10 +141,10 @@ Property create( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PutMapping("/{propertyName}/{channelName}") - Property addSingle( + PropertyDto addSingle( @PathVariable("propertyName") String propertyName, @PathVariable("channelName") String channelName, - @RequestBody Property property); + @RequestBody PropertyDto property); @Operation( summary = "Update a property", @@ -156,7 +157,7 @@ Property addSingle( @ApiResponse( responseCode = "200", description = "Property updated", - content = @Content(schema = @Schema(implementation = Property.class))), + content = @Content(schema = @Schema(implementation = PropertyDto.class))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -175,8 +176,8 @@ Property addSingle( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PostMapping("/{propertyName}") - Property update( - @PathVariable("propertyName") String propertyName, @RequestBody Property property); + PropertyDto update( + @PathVariable("propertyName") String propertyName, @RequestBody PropertyDto property); @Operation( summary = "Update multiple properties", @@ -189,7 +190,8 @@ Property update( responseCode = "200", description = "Properties updated", content = - @Content(array = @ArraySchema(schema = @Schema(implementation = Property.class)))), + @Content( + array = @ArraySchema(schema = @Schema(implementation = PropertyDto.class)))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -208,7 +210,7 @@ Property update( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PostMapping() - Iterable update(@RequestBody Iterable properties); + Iterable update(@RequestBody Iterable properties); @Operation( summary = "Delete a property", diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/api/ITag.java b/src/main/java/org/phoebus/channelfinder/web/v0/api/ITag.java index efe63431..8f8401f5 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/api/ITag.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/api/ITag.java @@ -6,7 +6,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -import org.phoebus.channelfinder.entity.Tag; +import org.phoebus.channelfinder.web.v0.dto.TagDto; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -28,14 +28,15 @@ public interface ITag { @ApiResponse( responseCode = "200", description = "List all Tags", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Tag.class)))), + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = TagDto.class)))), @ApiResponse( responseCode = "500", description = "Error while trying to list all Tags", content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @GetMapping - Iterable list(); + Iterable list(); @Operation( summary = "Get tag by name", @@ -47,14 +48,14 @@ public interface ITag { @ApiResponse( responseCode = "200", description = "Finding Tag by tagName", - content = @Content(schema = @Schema(implementation = Tag.class))), + content = @Content(schema = @Schema(implementation = TagDto.class))), @ApiResponse( responseCode = "404", description = "Tag not found", content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @GetMapping("/{tagName}") - Tag read( + TagDto read( @PathVariable("tagName") String tagName, @RequestParam(value = "withChannels", defaultValue = "true") boolean withChannels); @@ -68,7 +69,7 @@ Tag read( @ApiResponse( responseCode = "200", description = "Tag created and updated", - content = @Content(schema = @Schema(implementation = Tag.class))), + content = @Content(schema = @Schema(implementation = TagDto.class))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -87,7 +88,7 @@ Tag read( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PutMapping("/{tagName}") - Tag create(@PathVariable("tagName") String tagName, @RequestBody Tag tag); + TagDto create(@PathVariable("tagName") String tagName, @RequestBody TagDto tag); @Operation( summary = "Create multiple tags", @@ -99,7 +100,8 @@ Tag read( @ApiResponse( responseCode = "200", description = "Tags created", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Tag.class)))), + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = TagDto.class)))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -118,7 +120,7 @@ Tag read( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PutMapping() - Iterable create(@RequestBody Iterable tags); + Iterable create(@RequestBody Iterable tags); @Operation( summary = "Add tag to a single channel", @@ -130,7 +132,7 @@ Tag read( @ApiResponse( responseCode = "200", description = "Tags added to a single channel", - content = @Content(schema = @Schema(implementation = Tag.class))), + content = @Content(schema = @Schema(implementation = TagDto.class))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -149,7 +151,7 @@ Tag read( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PutMapping("/{tagName}/{channelName}") - Tag addSingle( + TagDto addSingle( @PathVariable("tagName") String tagName, @PathVariable("channelName") String channelName); @Operation( @@ -163,7 +165,7 @@ Tag addSingle( @ApiResponse( responseCode = "200", description = "Tag updated", - content = @Content(schema = @Schema(implementation = Tag.class))), + content = @Content(schema = @Schema(implementation = TagDto.class))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -182,7 +184,7 @@ Tag addSingle( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PostMapping("/{tagName}") - Tag update(@PathVariable("tagName") String tagName, @RequestBody Tag tag); + TagDto update(@PathVariable("tagName") String tagName, @RequestBody TagDto tag); @Operation( summary = "Update multiple tags", @@ -195,7 +197,8 @@ Tag addSingle( @ApiResponse( responseCode = "200", description = "Tags updated", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = Tag.class)))), + content = + @Content(array = @ArraySchema(schema = @Schema(implementation = TagDto.class)))), @ApiResponse( responseCode = "400", description = "Invalid request", @@ -214,7 +217,7 @@ Tag addSingle( content = @Content(schema = @Schema(implementation = ResponseStatusException.class))) }) @PostMapping() - Iterable update(@RequestBody Iterable tags); + Iterable update(@RequestBody Iterable tags); @Operation( summary = "Delete a tag", diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelController.java b/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelController.java index ab094ad1..52ec8b2c 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelController.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelController.java @@ -1,10 +1,11 @@ package org.phoebus.channelfinder.web.v0.controller; import java.util.List; -import org.phoebus.channelfinder.entity.Channel; -import org.phoebus.channelfinder.entity.SearchResult; import org.phoebus.channelfinder.service.ChannelService; import org.phoebus.channelfinder.web.v0.api.IChannel; +import org.phoebus.channelfinder.web.v0.dto.ChannelDto; +import org.phoebus.channelfinder.web.v0.dto.SearchResultDto; +import org.phoebus.channelfinder.web.v0.mapper.ChannelMapper; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.RequestMapping; @@ -22,13 +23,15 @@ public ChannelController(ChannelService channelService) { } @Override - public List query(MultiValueMap allRequestParams) { - return channelService.query(allRequestParams); + public List query(MultiValueMap allRequestParams) { + return channelService.query(allRequestParams).stream().map(ChannelMapper::toDto).toList(); } @Override - public SearchResult combinedQuery(MultiValueMap allRequestParams) { - return channelService.combinedQuery(allRequestParams); + public SearchResultDto combinedQuery(MultiValueMap allRequestParams) { + var result = channelService.combinedQuery(allRequestParams); + return new SearchResultDto( + result.channels().stream().map(ChannelMapper::toDto).toList(), result.count()); } @Override @@ -37,28 +40,28 @@ public long queryCount(MultiValueMap allRequestParams) { } @Override - public Channel read(String channelName) { - return channelService.read(channelName); + public ChannelDto read(String channelName) { + return ChannelMapper.toDto(channelService.read(channelName)); } @Override - public Channel create(String channelName, Channel channel) { - return channelService.create(channelName, channel); + public ChannelDto create(String channelName, ChannelDto channel) { + return ChannelMapper.toDto(channelService.create(channelName, ChannelMapper.toDomain(channel))); } @Override - public Iterable create(Iterable channels) { - return channelService.create(channels); + public Iterable create(Iterable channels) { + return ChannelMapper.toDtos(channelService.create(ChannelMapper.toDomains(channels))); } @Override - public Channel update(String channelName, Channel channel) { - return channelService.update(channelName, channel); + public ChannelDto update(String channelName, ChannelDto channel) { + return ChannelMapper.toDto(channelService.update(channelName, ChannelMapper.toDomain(channel))); } @Override - public Iterable update(Iterable channels) { - return channelService.update(channels); + public Iterable update(Iterable channels) { + return ChannelMapper.toDtos(channelService.update(ChannelMapper.toDomains(channels))); } @Override diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelProcessorController.java b/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelProcessorController.java index a6ff5b5c..54da43a6 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelProcessorController.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelProcessorController.java @@ -1,10 +1,11 @@ package org.phoebus.channelfinder.web.v0.controller; import java.util.List; -import org.phoebus.channelfinder.entity.Channel; import org.phoebus.channelfinder.service.ChannelProcessorService; import org.phoebus.channelfinder.service.model.archiver.ChannelProcessorInfo; import org.phoebus.channelfinder.web.v0.api.IChannelProcessor; +import org.phoebus.channelfinder.web.v0.dto.ChannelDto; +import org.phoebus.channelfinder.web.v0.mapper.ChannelMapper; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.RequestMapping; @@ -42,8 +43,8 @@ public long processChannels(MultiValueMap allRequestParams) { } @Override - public void processChannels(List channels) { - channelProcessorService.sendToProcessors(channels); + public void processChannels(List channels) { + channelProcessorService.sendToProcessors(ChannelMapper.toDomains(channels)); } @Override diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelScrollController.java b/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelScrollController.java index fe8c6b9d..fd2f0c67 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelScrollController.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/controller/ChannelScrollController.java @@ -1,8 +1,9 @@ package org.phoebus.channelfinder.web.v0.controller; -import org.phoebus.channelfinder.entity.Scroll; import org.phoebus.channelfinder.service.ChannelScrollService; import org.phoebus.channelfinder.web.v0.api.IChannelScroll; +import org.phoebus.channelfinder.web.v0.dto.ScrollDto; +import org.phoebus.channelfinder.web.v0.mapper.ChannelMapper; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.RequestMapping; @@ -20,12 +21,17 @@ public ChannelScrollController(ChannelScrollService channelScrollService) { } @Override - public Scroll query(MultiValueMap allRequestParams) { - return channelScrollService.search(null, allRequestParams); + public ScrollDto query(MultiValueMap allRequestParams) { + return toScrollDto(channelScrollService.search(null, allRequestParams)); } @Override - public Scroll query(String scrollId, MultiValueMap searchParameters) { - return channelScrollService.search(scrollId, searchParameters); + public ScrollDto query(String scrollId, MultiValueMap searchParameters) { + return toScrollDto(channelScrollService.search(scrollId, searchParameters)); + } + + private static ScrollDto toScrollDto(org.phoebus.channelfinder.entity.Scroll scroll) { + return new ScrollDto( + scroll.getId(), scroll.getChannels().stream().map(ChannelMapper::toDto).toList()); } } diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/controller/PropertyController.java b/src/main/java/org/phoebus/channelfinder/web/v0/controller/PropertyController.java index f794a640..8bb15cb9 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/controller/PropertyController.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/controller/PropertyController.java @@ -1,8 +1,9 @@ package org.phoebus.channelfinder.web.v0.controller; -import org.phoebus.channelfinder.entity.Property; import org.phoebus.channelfinder.service.PropertyService; import org.phoebus.channelfinder.web.v0.api.IProperty; +import org.phoebus.channelfinder.web.v0.dto.PropertyDto; +import org.phoebus.channelfinder.web.v0.mapper.PropertyMapper; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -19,38 +20,41 @@ public PropertyController(PropertyService propertyService) { } @Override - public Iterable list() { - return propertyService.list(); + public Iterable list() { + return PropertyMapper.toDtos(propertyService.list()); } @Override - public Property read(String propertyName, boolean withChannels) { - return propertyService.read(propertyName, withChannels); + public PropertyDto read(String propertyName, boolean withChannels) { + return PropertyMapper.toDto(propertyService.read(propertyName, withChannels)); } @Override - public Property create(String propertyName, Property property) { - return propertyService.create(propertyName, property); + public PropertyDto create(String propertyName, PropertyDto property) { + return PropertyMapper.toDto( + propertyService.create(propertyName, PropertyMapper.toDomain(property))); } @Override - public Iterable create(Iterable properties) { - return propertyService.create(properties); + public Iterable create(Iterable properties) { + return PropertyMapper.toDtos(propertyService.create(PropertyMapper.toDomains(properties))); } @Override - public Property addSingle(String propertyName, String channelName, Property property) { - return propertyService.addSingle(propertyName, channelName, property); + public PropertyDto addSingle(String propertyName, String channelName, PropertyDto property) { + return PropertyMapper.toDto( + propertyService.addSingle(propertyName, channelName, PropertyMapper.toDomain(property))); } @Override - public Property update(String propertyName, Property property) { - return propertyService.update(propertyName, property); + public PropertyDto update(String propertyName, PropertyDto property) { + return PropertyMapper.toDto( + propertyService.update(propertyName, PropertyMapper.toDomain(property))); } @Override - public Iterable update(Iterable properties) { - return propertyService.update(properties); + public Iterable update(Iterable properties) { + return PropertyMapper.toDtos(propertyService.update(PropertyMapper.toDomains(properties))); } @Override diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/controller/TagController.java b/src/main/java/org/phoebus/channelfinder/web/v0/controller/TagController.java index f9532c1d..b240dea6 100644 --- a/src/main/java/org/phoebus/channelfinder/web/v0/controller/TagController.java +++ b/src/main/java/org/phoebus/channelfinder/web/v0/controller/TagController.java @@ -1,8 +1,9 @@ package org.phoebus.channelfinder.web.v0.controller; -import org.phoebus.channelfinder.entity.Tag; import org.phoebus.channelfinder.service.TagService; import org.phoebus.channelfinder.web.v0.api.ITag; +import org.phoebus.channelfinder.web.v0.dto.TagDto; +import org.phoebus.channelfinder.web.v0.mapper.TagMapper; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -19,38 +20,38 @@ public TagController(TagService tagService) { } @Override - public Iterable list() { - return tagService.list(); + public Iterable list() { + return TagMapper.toDtos(tagService.list()); } @Override - public Tag read(String tagName, boolean withChannels) { - return tagService.read(tagName, withChannels); + public TagDto read(String tagName, boolean withChannels) { + return TagMapper.toDto(tagService.read(tagName, withChannels)); } @Override - public Tag create(String tagName, Tag tag) { - return tagService.create(tagName, tag); + public TagDto create(String tagName, TagDto tag) { + return TagMapper.toDto(tagService.create(tagName, TagMapper.toDomain(tag))); } @Override - public Iterable create(Iterable tags) { - return tagService.create(tags); + public Iterable create(Iterable tags) { + return TagMapper.toDtos(tagService.create(TagMapper.toDomains(tags))); } @Override - public Tag addSingle(String tagName, String channelName) { - return tagService.addSingle(tagName, channelName); + public TagDto addSingle(String tagName, String channelName) { + return TagMapper.toDto(tagService.addSingle(tagName, channelName)); } @Override - public Tag update(String tagName, Tag tag) { - return tagService.update(tagName, tag); + public TagDto update(String tagName, TagDto tag) { + return TagMapper.toDto(tagService.update(tagName, TagMapper.toDomain(tag))); } @Override - public Iterable update(Iterable tags) { - return tagService.update(tags); + public Iterable update(Iterable tags) { + return TagMapper.toDtos(tagService.update(TagMapper.toDomains(tags))); } @Override diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/dto/ChannelDto.java b/src/main/java/org/phoebus/channelfinder/web/v0/dto/ChannelDto.java new file mode 100644 index 00000000..5971691d --- /dev/null +++ b/src/main/java/org/phoebus/channelfinder/web/v0/dto/ChannelDto.java @@ -0,0 +1,17 @@ +package org.phoebus.channelfinder.web.v0.dto; + +import java.util.ArrayList; +import java.util.List; + +public record ChannelDto( + String name, String owner, List properties, List tags) { + + public ChannelDto { + properties = properties != null ? properties : new ArrayList<>(); + tags = tags != null ? tags : new ArrayList<>(); + } + + public ChannelDto(String name, String owner) { + this(name, owner, new ArrayList<>(), new ArrayList<>()); + } +} diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/dto/PropertyDto.java b/src/main/java/org/phoebus/channelfinder/web/v0/dto/PropertyDto.java new file mode 100644 index 00000000..b5b5f46a --- /dev/null +++ b/src/main/java/org/phoebus/channelfinder/web/v0/dto/PropertyDto.java @@ -0,0 +1,15 @@ +package org.phoebus.channelfinder.web.v0.dto; + +import java.util.ArrayList; +import java.util.List; + +public record PropertyDto(String name, String owner, String value, List channels) { + + public PropertyDto { + channels = channels != null ? channels : new ArrayList<>(); + } + + public PropertyDto(String name, String owner, String value) { + this(name, owner, value, new ArrayList<>()); + } +} diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/dto/ScrollDto.java b/src/main/java/org/phoebus/channelfinder/web/v0/dto/ScrollDto.java new file mode 100644 index 00000000..ad9ed64c --- /dev/null +++ b/src/main/java/org/phoebus/channelfinder/web/v0/dto/ScrollDto.java @@ -0,0 +1,5 @@ +package org.phoebus.channelfinder.web.v0.dto; + +import java.util.List; + +public record ScrollDto(String id, List channels) {} diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/dto/SearchResultDto.java b/src/main/java/org/phoebus/channelfinder/web/v0/dto/SearchResultDto.java new file mode 100644 index 00000000..83c94701 --- /dev/null +++ b/src/main/java/org/phoebus/channelfinder/web/v0/dto/SearchResultDto.java @@ -0,0 +1,5 @@ +package org.phoebus.channelfinder.web.v0.dto; + +import java.util.List; + +public record SearchResultDto(List channels, long count) {} diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/dto/TagDto.java b/src/main/java/org/phoebus/channelfinder/web/v0/dto/TagDto.java new file mode 100644 index 00000000..096c23da --- /dev/null +++ b/src/main/java/org/phoebus/channelfinder/web/v0/dto/TagDto.java @@ -0,0 +1,15 @@ +package org.phoebus.channelfinder.web.v0.dto; + +import java.util.ArrayList; +import java.util.List; + +public record TagDto(String name, String owner, List channels) { + + public TagDto { + channels = channels != null ? channels : new ArrayList<>(); + } + + public TagDto(String name, String owner) { + this(name, owner, new ArrayList<>()); + } +} diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/mapper/ChannelMapper.java b/src/main/java/org/phoebus/channelfinder/web/v0/mapper/ChannelMapper.java new file mode 100644 index 00000000..e1c1da98 --- /dev/null +++ b/src/main/java/org/phoebus/channelfinder/web/v0/mapper/ChannelMapper.java @@ -0,0 +1,36 @@ +package org.phoebus.channelfinder.web.v0.mapper; + +import java.util.List; +import java.util.stream.StreamSupport; +import org.phoebus.channelfinder.entity.Channel; +import org.phoebus.channelfinder.web.v0.dto.ChannelDto; + +public final class ChannelMapper { + + private ChannelMapper() {} + + public static ChannelDto toDto(Channel channel) { + return new ChannelDto( + channel.getName(), + channel.getOwner(), + channel.getProperties().stream().map(PropertyMapper::toDto).toList(), + channel.getTags().stream().map(TagMapper::toDto).toList()); + } + + public static Channel toDomain(ChannelDto dto) { + Channel channel = new Channel(); + channel.setName(dto.name()); + channel.setOwner(dto.owner()); + channel.setProperties(dto.properties().stream().map(PropertyMapper::toDomain).toList()); + channel.setTags(dto.tags().stream().map(TagMapper::toDomain).toList()); + return channel; + } + + public static List toDtos(Iterable channels) { + return StreamSupport.stream(channels.spliterator(), false).map(ChannelMapper::toDto).toList(); + } + + public static List toDomains(Iterable dtos) { + return StreamSupport.stream(dtos.spliterator(), false).map(ChannelMapper::toDomain).toList(); + } +} diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/mapper/PropertyMapper.java b/src/main/java/org/phoebus/channelfinder/web/v0/mapper/PropertyMapper.java new file mode 100644 index 00000000..6a551096 --- /dev/null +++ b/src/main/java/org/phoebus/channelfinder/web/v0/mapper/PropertyMapper.java @@ -0,0 +1,39 @@ +package org.phoebus.channelfinder.web.v0.mapper; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.StreamSupport; +import org.phoebus.channelfinder.entity.Property; +import org.phoebus.channelfinder.web.v0.dto.ChannelDto; +import org.phoebus.channelfinder.web.v0.dto.PropertyDto; + +public final class PropertyMapper { + + private PropertyMapper() {} + + public static PropertyDto toDto(Property property) { + List channels = + property.getChannels().isEmpty() + ? new ArrayList<>() + : property.getChannels().stream().map(ChannelMapper::toDto).toList(); + return new PropertyDto(property.getName(), property.getOwner(), property.getValue(), channels); + } + + public static Property toDomain(PropertyDto dto) { + Property property = new Property(dto.name(), dto.owner(), dto.value()); + if (!dto.channels().isEmpty()) { + property.setChannels(dto.channels().stream().map(ChannelMapper::toDomain).toList()); + } + return property; + } + + public static List toDtos(Iterable properties) { + return StreamSupport.stream(properties.spliterator(), false) + .map(PropertyMapper::toDto) + .toList(); + } + + public static List toDomains(Iterable dtos) { + return StreamSupport.stream(dtos.spliterator(), false).map(PropertyMapper::toDomain).toList(); + } +} diff --git a/src/main/java/org/phoebus/channelfinder/web/v0/mapper/TagMapper.java b/src/main/java/org/phoebus/channelfinder/web/v0/mapper/TagMapper.java new file mode 100644 index 00000000..ccba824d --- /dev/null +++ b/src/main/java/org/phoebus/channelfinder/web/v0/mapper/TagMapper.java @@ -0,0 +1,37 @@ +package org.phoebus.channelfinder.web.v0.mapper; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.StreamSupport; +import org.phoebus.channelfinder.entity.Tag; +import org.phoebus.channelfinder.web.v0.dto.ChannelDto; +import org.phoebus.channelfinder.web.v0.dto.TagDto; + +public final class TagMapper { + + private TagMapper() {} + + public static TagDto toDto(Tag tag) { + List channels = + tag.getChannels().isEmpty() + ? new ArrayList<>() + : tag.getChannels().stream().map(ChannelMapper::toDto).toList(); + return new TagDto(tag.getName(), tag.getOwner(), channels); + } + + public static Tag toDomain(TagDto dto) { + Tag tag = new Tag(dto.name(), dto.owner()); + if (!dto.channels().isEmpty()) { + tag.setChannels(dto.channels().stream().map(ChannelMapper::toDomain).toList()); + } + return tag; + } + + public static List toDtos(Iterable tags) { + return StreamSupport.stream(tags.spliterator(), false).map(TagMapper::toDto).toList(); + } + + public static List toDomains(Iterable dtos) { + return StreamSupport.stream(dtos.spliterator(), false).map(TagMapper::toDomain).toList(); + } +} diff --git a/src/test/java/org/phoebus/channelfinder/ChannelControllerIT.java b/src/test/java/org/phoebus/channelfinder/ChannelControllerIT.java index 71d36c1e..538f67cb 100644 --- a/src/test/java/org/phoebus/channelfinder/ChannelControllerIT.java +++ b/src/test/java/org/phoebus/channelfinder/ChannelControllerIT.java @@ -23,6 +23,7 @@ import org.phoebus.channelfinder.repository.TagRepository; import org.phoebus.channelfinder.web.v0.api.IChannel; import org.phoebus.channelfinder.web.v0.controller.ChannelController; +import org.phoebus.channelfinder.web.v0.mapper.ChannelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; import org.springframework.security.test.context.support.WithMockUser; @@ -52,9 +53,9 @@ void readXmlChannel() { Channel testChannel0 = new Channel("testChannel0", "testOwner", testProperties, testTags); cleanupTestChannels = Arrays.asList(testChannel0); - Channel createdChannel = channelManager.create(testChannel0.getName(), testChannel0); + Channel createdChannel = apiCreate(testChannel0.getName(), testChannel0); - Channel readChannel = channelManager.read(createdChannel.getName()); + Channel readChannel = apiRead(createdChannel.getName()); // verify the channel was read as expected Assertions.assertEquals(createdChannel, readChannel, "Failed to read the channel"); } @@ -74,7 +75,7 @@ void createXmlChannel() { cleanupTestChannels = Arrays.asList(testChannel0); // Create a simple channel - Channel createdChannel0 = channelManager.create(testChannel0.getName(), testChannel0); + Channel createdChannel0 = apiCreate(testChannel0.getName(), testChannel0); // verify the channel was created as expected Assertions.assertEquals(testChannel0, createdChannel0, "Failed to create the channel"); @@ -84,7 +85,7 @@ void createXmlChannel() { // Update the test channel with a new owner testChannel0.setOwner("updateTestOwner"); - Channel updatedChannel0 = channelManager.create(testChannel0.getName(), testChannel0); + Channel updatedChannel0 = apiCreate(testChannel0.getName(), testChannel0); // verify the channel was created as expected Assertions.assertEquals(testChannel0, updatedChannel0, "Failed to create the channel"); } @@ -96,8 +97,8 @@ void renameByCreateXmlChannel() { Channel testChannel1 = new Channel("testChannel1", "testOwner"); cleanupTestChannels = Arrays.asList(testChannel0, testChannel1); - Channel createdChannel = channelManager.create(testChannel0.getName(), testChannel0); - createdChannel = channelManager.create(testChannel0.getName(), testChannel1); + Channel createdChannel = apiCreate(testChannel0.getName(), testChannel0); + createdChannel = apiCreate(testChannel0.getName(), testChannel1); // verify that the old channel "testChannel0" was replaced with the new "testChannel1" Assertions.assertEquals(testChannel1, createdChannel, "Failed to create the channel"); // verify that the old channel is no longer present @@ -112,7 +113,7 @@ void createXmlChannel2() { Channel testChannel0 = new Channel("testChannel0", "testOwner", testProperties, testTags); cleanupTestChannels = Arrays.asList(testChannel0); - Channel createdChannel = channelManager.create(testChannel0.getName(), testChannel0); + apiCreate(testChannel0.getName(), testChannel0); try { Channel foundChannel = channelRepository.findById(testChannel0.getName()).get(); Assertions.assertEquals( @@ -132,7 +133,7 @@ void createXmlChannel2() { // Update the test channel with a new owner testChannel0.setOwner("updateTestOwner"); - createdChannel = channelManager.create(testChannel0.getName(), testChannel0); + apiCreate(testChannel0.getName(), testChannel0); try { Channel foundChannel = channelRepository.findById(testChannel0.getName()).get(); Assertions.assertEquals( @@ -156,9 +157,9 @@ void renameByCreateXmlChannel2() { cleanupTestChannels = Arrays.asList(testChannel0, testChannel1); // Create the testChannel0 - Channel createdChannel = channelManager.create(testChannel0.getName(), testChannel0); + apiCreate(testChannel0.getName(), testChannel0); // update the testChannel0 with testChannel1 - createdChannel = channelManager.create(testChannel0.getName(), testChannel1); + apiCreate(testChannel0.getName(), testChannel1); // verify that the old channel "testChannel0" was replaced with the new "testChannel1" try { Channel foundChannel = channelRepository.findById(testChannel1.getName()).get(); @@ -181,7 +182,7 @@ void createXmlChannels() { List testChannels = Arrays.asList(testChannel0, testChannel1, testChannel2); cleanupTestChannels = testChannels; - Iterable createdChannels = channelManager.create(testChannels); + apiCreate(testChannels); List foundChannels = new ArrayList(); testChannels.forEach( chan -> foundChannels.add(channelRepository.findById(chan.getName()).get())); @@ -200,14 +201,16 @@ void createXmlChannelsWithOverride() { cleanupTestChannels = testChannels; // Create a set of original channels to be overriden - channelManager.create(testChannels); + apiCreate(testChannels); // Now update the test channels testChannel0.setOwner("testOwner-updated"); testChannel1.setTags(Collections.emptyList()); testChannel1.setProperties(Collections.emptyList()); List updatedTestChannels = Arrays.asList(testChannel0, testChannel1); - channelManager.create(updatedTestChannels); + apiCreate(updatedTestChannels); + // Owner does not change for existing channels on create-override + testChannel0.setOwner("testOwner"); List foundChannels = new ArrayList(); testChannels.forEach( chan -> foundChannels.add(channelRepository.findById(chan.getName()).get())); @@ -229,7 +232,7 @@ void updateXmlChannel() { // Update on a non-existing channel should result in the creation of that channel // 1. Test a simple channel - Channel returnedChannel = channelManager.update(testChannel0.getName(), testChannel0); + Channel returnedChannel = apiUpdate(testChannel0.getName(), testChannel0); Assertions.assertEquals( testChannel0, returnedChannel, "Failed to update channel " + testChannel0); Assertions.assertEquals( @@ -237,7 +240,7 @@ void updateXmlChannel() { channelRepository.findById(testChannel0.getName()).get(), "Failed to update channel " + testChannel0); // 2. Test a channel with tags and props - returnedChannel = channelManager.update(testChannel1.getName(), testChannel1); + returnedChannel = apiUpdate(testChannel1.getName(), testChannel1); Assertions.assertEquals( testChannel1, returnedChannel, "Failed to update channel " + testChannel1); Assertions.assertEquals( @@ -247,7 +250,7 @@ void updateXmlChannel() { // Update the channel owner testChannel0.setOwner("newTestOwner"); - returnedChannel = channelManager.update(testChannel0.getName(), testChannel0); + returnedChannel = apiUpdate(testChannel0.getName(), testChannel0); Assertions.assertEquals( testChannel0, returnedChannel, "Failed to update channel " + testChannel0); Assertions.assertEquals( @@ -255,7 +258,7 @@ void updateXmlChannel() { channelRepository.findById(testChannel0.getName()).get(), "Failed to update channel " + testChannel0); testChannel1.setOwner("newTestOwner"); - returnedChannel = channelManager.update(testChannel1.getName(), testChannel1); + returnedChannel = apiUpdate(testChannel1.getName(), testChannel1); Assertions.assertEquals( testChannel1, returnedChannel, "Failed to update channel " + testChannel1); Assertions.assertEquals( @@ -275,11 +278,11 @@ void renameByUpdateXmlChannel() { cleanupTestChannels = Arrays.asList(testChannel0, testChannel1, testChannel2, testChannel3); // Create the testChannels - Channel createdChannel = channelManager.create(testChannel0.getName(), testChannel0); - Channel createdChannelWithItems = channelManager.create(testChannel2.getName(), testChannel2); + apiCreate(testChannel0.getName(), testChannel0); + apiCreate(testChannel2.getName(), testChannel2); // update the testChannels - Channel renamedChannel = channelManager.update(testChannel0.getName(), testChannel1); - Channel renamedChannelWithItems = channelManager.update(testChannel2.getName(), testChannel3); + apiUpdate(testChannel0.getName(), testChannel1); + apiUpdate(testChannel2.getName(), testChannel3); // verify that the old channels were replaced by the new ones try { @@ -318,7 +321,7 @@ void updateXmlChannelItems() { cleanupTestChannels = Arrays.asList(testChannel0); // Create the testChannel - Channel createdChannel = channelManager.create(testChannel0.getName(), testChannel0); + apiCreate(testChannel0.getName(), testChannel0); // set up the new testChannel testProperties.get(1).setValue("newValue"); @@ -330,7 +333,7 @@ void updateXmlChannelItems() { Arrays.asList(testTags.get(1), testTags.get(2))); // update the testChannel - Channel updatedChannel = channelManager.update(testChannel0.getName(), testChannel0); + apiUpdate(testChannel0.getName(), testChannel0); Channel expectedChannel = new Channel("testChannel0", "testOwner", testProperties, testTags); Channel foundChannel = channelRepository.findById("testChannel0").get(); @@ -370,7 +373,7 @@ void updateMultipleXmlChannels() { cleanupTestChannels = testChannels; // Update on non-existing channels should result in the creation of those channels - Iterable returnedChannels = channelManager.update(testChannels); + apiUpdate(testChannels); // 1. Test a simple channel Assertions.assertEquals( testChannel0, @@ -382,10 +385,12 @@ void updateMultipleXmlChannels() { channelRepository.findById(testChannel1.getName()).get(), "Failed to update channel " + testChannel1); - // Update the channel owner + // Owner does not change for existing channels on batch update testChannel0.setOwner("newTestOwner"); testChannel1.setOwner("newTestOwner"); - returnedChannels = channelManager.update(testChannels); + apiUpdate(testChannels); + testChannel0.setOwner("testOwner"); + testChannel1.setOwner("testOwner"); Assertions.assertEquals( testChannel0, channelRepository.findById(testChannel0.getName()).get(), @@ -416,7 +421,7 @@ void updateMultipleXmlChannelsWithItems() { cleanupTestChannels = testChannels; // Create the testChannel - Iterable createdChannels = channelManager.create(testChannels); + apiCreate(testChannels); // set up the new testChannel testProperties.forEach(prop -> prop.setValue("newValue")); @@ -435,7 +440,7 @@ void updateMultipleXmlChannelsWithItems() { testChannels = Arrays.asList(testChannel0, testChannel1); // update the testChannel - Iterable updatedChannels = channelManager.update(testChannels); + apiUpdate(testChannels); // set up the expected testChannels testChannel0 = @@ -494,7 +499,7 @@ void deleteXmlChannel() { Channel testChannel0 = new Channel("testChannel0", "testOwner"); cleanupTestChannels = Arrays.asList(testChannel0); - channelManager.create(testChannel0.getName(), testChannel0); + apiCreate(testChannel0.getName(), testChannel0); channelManager.remove(testChannel0.getName()); // verify the channel was deleted as expected Assertions.assertFalse( @@ -562,4 +567,24 @@ void setupAll() { void tearDown() throws IOException { ElasticConfigIT.teardown(esService); } + + private Channel apiCreate(String name, Channel channel) { + return ChannelMapper.toDomain(channelManager.create(name, ChannelMapper.toDto(channel))); + } + + private Iterable apiCreate(Iterable channels) { + return ChannelMapper.toDomains(channelManager.create(ChannelMapper.toDtos(channels))); + } + + private Channel apiRead(String name) { + return ChannelMapper.toDomain(channelManager.read(name)); + } + + private Channel apiUpdate(String name, Channel channel) { + return ChannelMapper.toDomain(channelManager.update(name, ChannelMapper.toDto(channel))); + } + + private Iterable apiUpdate(Iterable channels) { + return ChannelMapper.toDomains(channelManager.update(ChannelMapper.toDtos(channels))); + } } diff --git a/src/test/java/org/phoebus/channelfinder/ChannelScrollControllerIT.java b/src/test/java/org/phoebus/channelfinder/ChannelScrollControllerIT.java index 5d682c82..77058597 100644 --- a/src/test/java/org/phoebus/channelfinder/ChannelScrollControllerIT.java +++ b/src/test/java/org/phoebus/channelfinder/ChannelScrollControllerIT.java @@ -9,13 +9,13 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.phoebus.channelfinder.configuration.ElasticConfig; import org.phoebus.channelfinder.configuration.PopulateDBConfiguration; -import org.phoebus.channelfinder.entity.Channel; -import org.phoebus.channelfinder.entity.Scroll; import org.phoebus.channelfinder.repository.ChannelRepository; import org.phoebus.channelfinder.repository.PropertyRepository; import org.phoebus.channelfinder.repository.TagRepository; import org.phoebus.channelfinder.web.v0.api.IChannelScroll; import org.phoebus.channelfinder.web.v0.controller.ChannelScrollController; +import org.phoebus.channelfinder.web.v0.dto.ChannelDto; +import org.phoebus.channelfinder.web.v0.dto.ScrollDto; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; import org.springframework.test.context.ContextConfiguration; @@ -83,33 +83,32 @@ void searchNameTest() throws InterruptedException { MultiValueMap searchParameters = new LinkedMultiValueMap(); // Search for a single unique channel searchParameters.add("~name", channelNames.get(0)); - Scroll scrollResult = channelScroll.query(searchParameters); - List result = new ArrayList<>(scrollResult.getChannels()); - while (scrollResult.getChannels().size() == 100) { - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); - result.addAll(scrollResult.getChannels()); + ScrollDto scrollResult = channelScroll.query(searchParameters); + List result = new ArrayList<>(scrollResult.channels()); + while (scrollResult.channels().size() == 100) { + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); + result.addAll(scrollResult.channels()); } - Assertions.assertTrue( - result.size() == 1 && result.get(0).getName().equals(channelNames.get(0))); + Assertions.assertTrue(result.size() == 1 && result.get(0).name().equals(channelNames.get(0))); // Search for all channels via wildcards searchParameters.clear(); searchParameters.add("~name", "BR:C001-BI:2{BLA}Pos:?-RB"); scrollResult = channelScroll.query(searchParameters); - result = new ArrayList<>(scrollResult.getChannels()); - while (scrollResult.getChannels().size() == 100) { - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); - result.addAll(scrollResult.getChannels()); + result = new ArrayList<>(scrollResult.channels()); + while (scrollResult.channels().size() == 100) { + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); + result.addAll(scrollResult.channels()); } Assertions.assertSame(2, result.size(), "Expected 2 but got " + result.size()); searchParameters.clear(); searchParameters.add("~name", "BR:C001-BI:?{BLA}Pos:*"); scrollResult = channelScroll.query(searchParameters); - result = new ArrayList<>(scrollResult.getChannels()); - while (scrollResult.getChannels().size() == 100) { - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); - result.addAll(scrollResult.getChannels()); + result = new ArrayList<>(scrollResult.channels()); + while (scrollResult.channels().size() == 100) { + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); + result.addAll(scrollResult.channels()); } Assertions.assertSame(4, result.size(), "Expected 4 but got " + result.size()); @@ -117,10 +116,10 @@ void searchNameTest() throws InterruptedException { searchParameters.clear(); searchParameters.add("~name", "SR*"); scrollResult = channelScroll.query(searchParameters); - result = new ArrayList<>(scrollResult.getChannels()); - while (scrollResult.getChannels().size() == 100) { - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); - result.addAll(scrollResult.getChannels()); + result = new ArrayList<>(scrollResult.channels()); + while (scrollResult.channels().size() == 100) { + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); + result.addAll(scrollResult.channels()); } Assertions.assertEquals(1000, result.size(), "Expected 1000 but got " + result.size()); @@ -128,20 +127,20 @@ void searchNameTest() throws InterruptedException { searchParameters.clear(); searchParameters.add("~name", "SR*|BR*"); scrollResult = channelScroll.query(searchParameters); - result = new ArrayList<>(scrollResult.getChannels()); - while (scrollResult.getChannels().size() == 100) { - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); - result.addAll(scrollResult.getChannels()); + result = new ArrayList<>(scrollResult.channels()); + while (scrollResult.channels().size() == 100) { + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); + result.addAll(scrollResult.channels()); } Assertions.assertEquals(1500, result.size(), "Expected 1500 but got " + result.size()); searchParameters.clear(); searchParameters.add("~name", "SR*,BR*"); scrollResult = channelScroll.query(searchParameters); - result = new ArrayList<>(scrollResult.getChannels()); - while (scrollResult.getChannels().size() == 100) { - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); - result.addAll(scrollResult.getChannels()); + result = new ArrayList<>(scrollResult.channels()); + while (scrollResult.channels().size() == 100) { + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); + result.addAll(scrollResult.channels()); } Assertions.assertEquals(1500, result.size(), "Expected 1500 but got " + result.size()); @@ -155,10 +154,10 @@ void searchNameTest() throws InterruptedException { searchParameters.add("~tag", "group" + id + "_" + val_bucket.get(index)); scrollResult = channelScroll.query(searchParameters); - result = new ArrayList<>(scrollResult.getChannels()); - while (scrollResult.getChannels().size() == 100) { - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); - result.addAll(scrollResult.getChannels()); + result = new ArrayList<>(scrollResult.channels()); + while (scrollResult.channels().size() == 100) { + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); + result.addAll(scrollResult.channels()); } Assertions.assertEquals( val_bucket.get(index), @@ -181,10 +180,10 @@ void searchNameTest() throws InterruptedException { searchParameters.add("group" + id, String.valueOf(val_bucket.get(index))); scrollResult = channelScroll.query(searchParameters); - result = new ArrayList<>(scrollResult.getChannels()); - while (scrollResult.getChannels().size() == 100) { - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); - result.addAll(scrollResult.getChannels()); + result = new ArrayList<>(scrollResult.channels()); + while (scrollResult.channels().size() == 100) { + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); + result.addAll(scrollResult.channels()); } Assertions.assertEquals( val_bucket.get(index), diff --git a/src/test/java/org/phoebus/channelfinder/ChannelScrollControllerSearchIT.java b/src/test/java/org/phoebus/channelfinder/ChannelScrollControllerSearchIT.java index 1fd6970e..3ab5da05 100644 --- a/src/test/java/org/phoebus/channelfinder/ChannelScrollControllerSearchIT.java +++ b/src/test/java/org/phoebus/channelfinder/ChannelScrollControllerSearchIT.java @@ -11,11 +11,11 @@ import org.junit.jupiter.api.TestInstance; import org.phoebus.channelfinder.configuration.ElasticConfig; import org.phoebus.channelfinder.configuration.PopulateDBConfiguration; -import org.phoebus.channelfinder.entity.Scroll; import org.phoebus.channelfinder.repository.PropertyRepository; import org.phoebus.channelfinder.repository.TagRepository; import org.phoebus.channelfinder.web.v0.api.IChannelScroll; import org.phoebus.channelfinder.web.v0.controller.ChannelScrollController; +import org.phoebus.channelfinder.web.v0.dto.ScrollDto; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; import org.springframework.test.context.ContextConfiguration; @@ -71,7 +71,7 @@ void searchNameTest() { searchParameters.add("~size", "100"); long start = System.currentTimeMillis(); - Scroll scrollResult = channelScroll.query(searchParameters); + ScrollDto scrollResult = channelScroll.query(searchParameters); logger.log( Level.INFO, "Completed the first scroll request in : " + (System.currentTimeMillis() - start) + "ms"); @@ -83,28 +83,28 @@ void searchNameTest() { "Retrieved channels " + totalResult + " to " - + (totalResult + scrollResult.getChannels().size()) + + (totalResult + scrollResult.channels().size()) + " in : " + (System.currentTimeMillis() - start) + "ms"); avg100 = (avg100 + (System.currentTimeMillis() - start)) / 2; - totalResult += scrollResult.getChannels().size(); + totalResult += scrollResult.channels().size(); start = System.currentTimeMillis(); - while (scrollResult.getChannels().size() == 100) { - logger.log(Level.INFO, "Retireval id: " + scrollResult.getId()); - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); + while (scrollResult.channels().size() == 100) { + logger.log(Level.INFO, "Retireval id: " + scrollResult.id()); + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); logger.log( Level.INFO, "Retrieved channels " + totalResult + " to " - + (totalResult + scrollResult.getChannels().size()) + + (totalResult + scrollResult.channels().size()) + " in : " + (System.currentTimeMillis() - start) + "ms"); avg100 = (avg100 + (System.currentTimeMillis() - start)) / 2; - totalResult += scrollResult.getChannels().size(); + totalResult += scrollResult.channels().size(); start = System.currentTimeMillis(); } logger.log(Level.INFO, "total result = " + totalResult); @@ -125,28 +125,28 @@ void searchNameTest() { "Retrieved channels " + totalResult + " to " - + (totalResult + scrollResult.getChannels().size()) + + (totalResult + scrollResult.channels().size()) + " in : " + (System.currentTimeMillis() - start) + "ms"); avg1000 = (avg1000 + (System.currentTimeMillis() - start)) / 2; - totalResult += scrollResult.getChannels().size(); + totalResult += scrollResult.channels().size(); start = System.currentTimeMillis(); - while (scrollResult.getChannels().size() == 1000) { - logger.log(Level.INFO, "Retireval id: " + scrollResult.getId()); - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); + while (scrollResult.channels().size() == 1000) { + logger.log(Level.INFO, "Retireval id: " + scrollResult.id()); + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); logger.log( Level.INFO, "Retrieved channels " + totalResult + " to " - + (totalResult + scrollResult.getChannels().size()) + + (totalResult + scrollResult.channels().size()) + " in : " + (System.currentTimeMillis() - start) + "ms"); avg1000 = (avg1000 + (System.currentTimeMillis() - start)) / 2; - totalResult += scrollResult.getChannels().size(); + totalResult += scrollResult.channels().size(); start = System.currentTimeMillis(); } logger.log(Level.INFO, "total result = " + totalResult); @@ -168,27 +168,27 @@ void searchNameTest() { "Retrieved channels " + totalResult + " to " - + (totalResult + scrollResult.getChannels().size()) + + (totalResult + scrollResult.channels().size()) + " in : " + (System.currentTimeMillis() - start) + "ms"); avg10000 = (avg10000 + (System.currentTimeMillis() - start)) / 2; - totalResult += scrollResult.getChannels().size(); + totalResult += scrollResult.channels().size(); start = System.currentTimeMillis(); - while (scrollResult.getChannels().size() == 10000) { - scrollResult = channelScroll.query(scrollResult.getId(), searchParameters); + while (scrollResult.channels().size() == 10000) { + scrollResult = channelScroll.query(scrollResult.id(), searchParameters); logger.log( Level.FINE, "Retrieved channels " + totalResult + " to " - + (totalResult + scrollResult.getChannels().size()) + + (totalResult + scrollResult.channels().size()) + " in : " + (System.currentTimeMillis() - start) + "ms"); avg10000 = (avg10000 + (System.currentTimeMillis() - start)) / 2; - totalResult += scrollResult.getChannels().size(); + totalResult += scrollResult.channels().size(); start = System.currentTimeMillis(); } logger.log(Level.INFO, "total result = " + totalResult); diff --git a/src/test/java/org/phoebus/channelfinder/MetricsServiceTest.java b/src/test/java/org/phoebus/channelfinder/MetricsServiceTest.java index 1bd55dbb..3f993634 100644 --- a/src/test/java/org/phoebus/channelfinder/MetricsServiceTest.java +++ b/src/test/java/org/phoebus/channelfinder/MetricsServiceTest.java @@ -7,8 +7,6 @@ import java.util.Map; import org.junit.jupiter.api.Test; import org.phoebus.channelfinder.service.MetricsService; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; class MetricsServiceTest { @@ -18,8 +16,7 @@ void testGenerateAllMultiValueMaps_example1() { Map.of( "a", List.of("b", "c"), "d", List.of("e", "!*")); - List> allMaps = - MetricsService.generateAllMultiValueMaps(properties); + List>> allMaps = MetricsService.generateAllMultiValueMaps(properties); assertEquals(4, allMaps.size()); @@ -36,14 +33,12 @@ void testGenerateAllMultiValueMaps_example2() { "x", List.of("y", "z"), "p", List.of("q"), "r", List.of("s", "t")); - List> allMaps = - MetricsService.generateAllMultiValueMaps(properties); + List>> allMaps = MetricsService.generateAllMultiValueMaps(properties); - assertEquals(2 * 2, allMaps.size()); // 2 options (value or null) for each of 2 keys + assertEquals(2 * 2, allMaps.size()); - // Just a basic check, exhaustive check would be large boolean foundExpectedCombination = false; - for (MultiValueMap map : allMaps) { + for (Map> map : allMaps) { if (map.get("x").contains("y") && map.get("p").contains("q") && map.get("r").contains("s")) { foundExpectedCombination = true; break; @@ -55,39 +50,21 @@ void testGenerateAllMultiValueMaps_example2() { @Test void testGenerateAllMultiValueMaps_emptyList() { Map> properties = Map.of("m", List.of()); - List> allMaps = - MetricsService.generateAllMultiValueMaps(properties); + List>> allMaps = MetricsService.generateAllMultiValueMaps(properties); - assertEquals(0, allMaps.size()); // One with m=null, one with m implicitly null (not present) + assertEquals(0, allMaps.size()); } @Test void testGenerateAllMultiValueMaps_emptyMap() { Map> properties = Map.of(); - List> allMaps = - MetricsService.generateAllMultiValueMaps(properties); + List>> allMaps = MetricsService.generateAllMultiValueMaps(properties); assertEquals(0, allMaps.size()); } - // Helper method to create a MultiValueMap for easier assertion - private MultiValueMap createMap( + private Map> createMap( String key1, String value1, String key2, String value2) { - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - if (key1 != null) { - map.add(key1, value1); - } - if (key2 != null) { - map.add(key2, value2); - } - return map; - } - - private MultiValueMap createMap(String key, String value) { - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - if (key != null) { - map.add(key, value); - } - return map; + return Map.of(key1, List.of(value1), key2, List.of(value2)); } } diff --git a/src/test/java/org/phoebus/channelfinder/PropertyControllerIT.java b/src/test/java/org/phoebus/channelfinder/PropertyControllerIT.java index 49f7020a..381f6e97 100644 --- a/src/test/java/org/phoebus/channelfinder/PropertyControllerIT.java +++ b/src/test/java/org/phoebus/channelfinder/PropertyControllerIT.java @@ -24,6 +24,7 @@ import org.phoebus.channelfinder.repository.PropertyRepository; import org.phoebus.channelfinder.web.v0.api.IProperty; import org.phoebus.channelfinder.web.v0.controller.PropertyController; +import org.phoebus.channelfinder.web.v0.mapper.PropertyMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; import org.springframework.security.test.context.support.WithMockUser; @@ -99,8 +100,8 @@ void listXmlProperties() { new ArrayList()))); List testProperties = Arrays.asList(testProperty0, testProperty1); - Iterable createdProperties = propertyManager.create(testProperties); - Iterable propertyList = propertyManager.list(); + Iterable createdProperties = apiCreate(testProperties); + Iterable propertyList = apiList(); for (Property property : createdProperties) { property.setChannels(new ArrayList()); } @@ -122,24 +123,24 @@ void readXmlProperty() { new Property(testProperty1.getName(), testProperty1.getOwner(), "value")), new ArrayList()))); - Property createdProperty0 = propertyManager.create(testProperty0.getName(), testProperty0); - Property createdProperty1 = propertyManager.create(testProperty1.getName(), testProperty1); + Property createdProperty0 = apiCreate(testProperty0.getName(), testProperty0); + Property createdProperty1 = apiCreate(testProperty1.getName(), testProperty1); // verify the created properties are read as expected // retrieve the testProperty0 without channels - Property retrievedProperty = propertyManager.read(createdProperty0.getName(), false); + Property retrievedProperty = apiRead(createdProperty0.getName(), false); Assertions.assertEquals(createdProperty0, retrievedProperty, "Failed to read the property"); // retrieve the testProperty0 with channels - retrievedProperty = propertyManager.read(createdProperty0.getName(), true); + retrievedProperty = apiRead(createdProperty0.getName(), true); Assertions.assertEquals( createdProperty0, retrievedProperty, "Failed to read the property w/ channels"); - retrievedProperty = propertyManager.read(createdProperty1.getName(), false); + retrievedProperty = apiRead(createdProperty1.getName(), false); // verify the property was read as expected testProperty1.setChannels(new ArrayList()); Assertions.assertEquals(testProperty1, retrievedProperty, "Failed to read the property"); - retrievedProperty = propertyManager.read(createdProperty1.getName(), true); + retrievedProperty = apiRead(createdProperty1.getName(), true); // verify the property was read as expected Assertions.assertEquals( createdProperty1, retrievedProperty, "Failed to read the property w/ channels"); @@ -167,7 +168,7 @@ void createXmlProperty() { Property testProperty0 = new Property("testProperty0", "testOwner"); // Create a simple property - Property createdProperty = propertyManager.create(testProperty0.getName(), testProperty0); + Property createdProperty = apiCreate(testProperty0.getName(), testProperty0); Assertions.assertEquals(testProperty0, createdProperty, "Failed to create the property"); // Tag createdTag1 = tagManager.create("fakeTag", copy(testTag1)); @@ -176,7 +177,7 @@ void createXmlProperty() { // Update the test property with a new owner Property updatedTestProperty0 = new Property("testProperty0", "updateTestOwner"); - createdProperty = propertyManager.create(testProperty0.getName(), updatedTestProperty0); + createdProperty = apiCreate(testProperty0.getName(), updatedTestProperty0); Assertions.assertEquals(updatedTestProperty0, createdProperty, "Failed to create the property"); } @@ -186,8 +187,8 @@ void renameByCreateXmlProperty() { Property testProperty0 = new Property("testProperty0", "testOwner"); Property testProperty1 = new Property("testProperty1", "testOwner"); - Property createdProperty = propertyManager.create(testProperty0.getName(), testProperty0); - createdProperty = propertyManager.create(testProperty0.getName(), testProperty1); + Property createdProperty = apiCreate(testProperty0.getName(), testProperty0); + createdProperty = apiCreate(testProperty0.getName(), testProperty1); // verify that the old property "testProperty0" was replaced with the new "testProperty1" Assertions.assertEquals(testProperty1, createdProperty, "Failed to create the property"); // verify that the old property is no longer present @@ -213,7 +214,7 @@ void createXmlProperty2() { new ArrayList()))); Property createdProperty = - propertyManager.create(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiCreate(testProperty0WithChannels.getName(), testProperty0WithChannels); try { Property foundProperty = propertyRepository.findById(testProperty0WithChannels.getName(), true).get(); @@ -236,8 +237,7 @@ void createXmlProperty2() { Property updatedTestProperty0WithChannels = new Property("testProperty0WithChannels", "updateTestOwner"); createdProperty = - propertyManager.create( - testProperty0WithChannels.getName(), updatedTestProperty0WithChannels); + apiCreate(testProperty0WithChannels.getName(), updatedTestProperty0WithChannels); try { Property foundProperty = propertyRepository.findById(testProperty0WithChannels.getName(), true).get(); @@ -283,10 +283,9 @@ void renameByCreateXmlProperty2() { // Create the testProperty0WithChannels Property createdProperty = - propertyManager.create(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiCreate(testProperty0WithChannels.getName(), testProperty0WithChannels); // update the testProperty0WithChannels with testProperty1WithChannels - createdProperty = - propertyManager.create(testProperty0WithChannels.getName(), testProperty1WithChannels); + createdProperty = apiCreate(testProperty0WithChannels.getName(), testProperty1WithChannels); try { Property foundProperty = propertyRepository.findById(testProperty1WithChannels.getName(), true).get(); @@ -353,7 +352,7 @@ void createXmlProperties() { testProperty1WithChannels, testProperty2WithChannels); - Iterable createdProperties = propertyManager.create(testProperties); + apiCreate(testProperties); List foundProperties = new ArrayList(); testProperties.forEach( prop -> foundProperties.add(propertyRepository.findById(prop.getName(), true).get())); @@ -403,7 +402,7 @@ void createXmlPropertiesWithOverride() { List testProperties = Arrays.asList(testProperty0, testProperty0WithChannels); // Create a set of original properties to be overriden - propertyManager.create(testProperties); + apiCreate(testProperties); // Now update the test properties testProperty0.setOwner("testOwner-updated"); testProperty0WithChannels.setOwner("testOwner-updated"); @@ -420,11 +419,12 @@ void createXmlPropertiesWithOverride() { new ArrayList()))); List updatedTestProperties = Arrays.asList(testProperty0, testProperty0WithChannels); - propertyManager.create(updatedTestProperties); + apiCreate(updatedTestProperties); - // set owner back to original since it shouldn't change + // set owner back to original since it shouldn't change; also normalize channel property owners testProperty0.setOwner("testOwner"); testProperty0WithChannels.setOwner("testOwner"); + testProperty0WithChannels.getChannels().get(0).getProperties().get(0).setOwner("testOwner"); List foundProperties = new ArrayList(); testProperties.forEach( @@ -456,7 +456,7 @@ void addSingleXmlProperty() { propertyRepository.index(testProperty0); testProperty0.setValue("value"); - propertyManager.addSingle(testProperty0.getName(), "testChannel0", testProperty0); + apiAddSingle(testProperty0.getName(), "testChannel0", testProperty0); Assertions.assertTrue( channelRepository.findById("testChannel0").get().getProperties().stream() .anyMatch( @@ -489,7 +489,7 @@ void updateXmlProperty() { // Update on a non-existing property should result in the creation of that property // 1. Test a simple property - Property returnedProperty = propertyManager.update(testProperty0.getName(), testProperty0); + Property returnedProperty = apiUpdate(testProperty0.getName(), testProperty0); Assertions.assertEquals( testProperty0, returnedProperty, "Failed to update property " + testProperty0); Assertions.assertEquals( @@ -497,8 +497,7 @@ void updateXmlProperty() { propertyRepository.findById(testProperty0.getName()).get(), "Failed to update property " + testProperty0); // 2. Test a property with channels - returnedProperty = - propertyManager.update(testProperty0WithChannels.getName(), testProperty0WithChannels); + returnedProperty = apiUpdate(testProperty0WithChannels.getName(), testProperty0WithChannels); Assertions.assertEquals( testProperty0WithChannels, returnedProperty, @@ -510,7 +509,7 @@ void updateXmlProperty() { // Update the property owner testProperty0.setOwner("newTestOwner"); - returnedProperty = propertyManager.update(testProperty0.getName(), testProperty0); + returnedProperty = apiUpdate(testProperty0.getName(), testProperty0); Assertions.assertEquals( testProperty0, returnedProperty, "Failed to update property " + testProperty0); Assertions.assertEquals( @@ -529,8 +528,7 @@ void updateXmlProperty() { testProperty0WithChannels.getOwner(), "value")), new ArrayList()))); - returnedProperty = - propertyManager.update(testProperty0WithChannels.getName(), testProperty0WithChannels); + returnedProperty = apiUpdate(testProperty0WithChannels.getName(), testProperty0WithChannels); Assertions.assertEquals( testProperty0WithChannels, returnedProperty, @@ -594,9 +592,9 @@ void updateXmlPropertyOnChan() { "newValueX")), EMPTY_LIST))); - propertyManager.create(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiCreate(testProperty0WithChannels.getName(), testProperty0WithChannels); // change name and owner on existing channel, add to new channel - propertyManager.update(testProperty0WithChannels.getName(), testProperty1WithChannels); + apiUpdate(testProperty0WithChannels.getName(), testProperty1WithChannels); Property expectedProperty = new Property("testProperty1WithChannels", "updateTestOwner"); expectedProperty.setChannels( @@ -713,13 +711,11 @@ void renameByUpdateXmlProperty() { new ArrayList()))); // Create the original properties - Property createdProperty = propertyManager.create(testProperty0.getName(), testProperty0); - Property createdPropertyWithChannels = - propertyManager.create(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiCreate(testProperty0.getName(), testProperty0); + apiCreate(testProperty0WithChannels.getName(), testProperty0WithChannels); // update the properties with new names, 0 -> 1 - Property updatedProperty = propertyManager.create(testProperty0.getName(), testProperty1); - Property updatedPropertyWithChannels = - propertyManager.create(testProperty0WithChannels.getName(), testProperty1WithChannels); + apiCreate(testProperty0.getName(), testProperty1); + apiCreate(testProperty0WithChannels.getName(), testProperty1WithChannels); // verify that the old property "testProperty0" was replaced with the new "testProperty1" try { @@ -758,7 +754,7 @@ void renameByUpdateXmlProperty() { void updatePropertyTest1() { // A test property with only name and owner Property testProperty0 = new Property("testProperty0", "testOwner"); - propertyManager.create(testProperty0.getName(), testProperty0); + apiCreate(testProperty0.getName(), testProperty0); // Updating a property with no channels, the new channels should be added to the property // Add testChannel0 to testProperty0 which has no channels testProperty0.setChannels( @@ -769,7 +765,7 @@ void updatePropertyTest1() { Arrays.asList( new Property(testProperty0.getName(), testProperty0.getOwner(), "value")), new ArrayList()))); - Property returnedTag = propertyManager.update(testProperty0.getName(), testProperty0); + Property returnedTag = apiUpdate(testProperty0.getName(), testProperty0); Assertions.assertEquals( testProperty0, returnedTag, "Failed to update property " + testProperty0); Assertions.assertEquals( @@ -797,7 +793,7 @@ void updatePropertyTest2() { testProperty0WithChannels.getOwner(), "value")), new ArrayList()))); - propertyManager.create(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiCreate(testProperty0WithChannels.getName(), testProperty0WithChannels); // Updating a property with existing channels, the new channels should be added without // affecting existing channels // testProperty0WithChannels already has testChannel0, the update operation should append the @@ -814,7 +810,7 @@ void updatePropertyTest2() { "value")), new ArrayList()))); Property returnedTag = - propertyManager.update(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiUpdate(testProperty0WithChannels.getName(), testProperty0WithChannels); Assertions.assertEquals( testProperty0WithChannels, returnedTag, @@ -865,7 +861,7 @@ void updatePropertyTest3() { testProperty0WithChannels.getOwner(), "value")), new ArrayList()))); - propertyManager.create(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiCreate(testProperty0WithChannels.getName(), testProperty0WithChannels); // testProperty0WithChannels already has testChannel0, the update request (which repeats the // testChannel0) // should append the testChannel1 while leaving the existing channel unaffected. @@ -890,7 +886,7 @@ void updatePropertyTest3() { "value")), new ArrayList()))); Property returnedTag = - propertyManager.update(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiUpdate(testProperty0WithChannels.getName(), testProperty0WithChannels); Assertions.assertEquals( testProperty0WithChannels, returnedTag, @@ -930,13 +926,13 @@ void updatePropertyTest4() { testProperty0WithChannels.getOwner(), "value")), new ArrayList()))); - propertyManager.create(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiCreate(testProperty0WithChannels.getName(), testProperty0WithChannels); // Updating a property with existing channels, the new channels should be added without // affecting existing channels // testProperty0WithChannels already has testChannel0 & testChannel1, the update request should // be a NOP. Property returnedTag = - propertyManager.update(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiUpdate(testProperty0WithChannels.getName(), testProperty0WithChannels); Assertions.assertEquals( testProperty0WithChannels, returnedTag, @@ -976,7 +972,7 @@ void updatePropertyTest5() { testProperty0WithChannels.getOwner(), "value")), new ArrayList()))); - propertyManager.create(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiCreate(testProperty0WithChannels.getName(), testProperty0WithChannels); // Updating a property with existing channels, the new channels should be added without // affecting existing channels // testProperty0WithChannels already has testChannel0 & testChannel1, the update request should @@ -993,7 +989,7 @@ void updatePropertyTest5() { "value")), new ArrayList()))); Property returnedTag = - propertyManager.update(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiUpdate(testProperty0WithChannels.getName(), testProperty0WithChannels); Assertions.assertEquals( testProperty0WithChannels, returnedTag, @@ -1072,8 +1068,8 @@ void updatePropertyWithChannelsTest() { "property1channel1")), new ArrayList()))); - propertyManager.create(testProperty0WithChannels.getName(), testProperty0WithChannels); - propertyManager.create(testProperty1WithChannels.getName(), testProperty1WithChannels); + apiCreate(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiCreate(testProperty1WithChannels.getName(), testProperty1WithChannels); Property newValueProperty = new Property( @@ -1091,7 +1087,7 @@ void updatePropertyWithChannelsTest() { newValueProperty.getOwner(), "newValueProperty")), new ArrayList()))); - propertyManager.update(newValueProperty.getName(), newValueProperty); + apiUpdate(newValueProperty.getName(), newValueProperty); List expected0Properties = List.of( @@ -1150,7 +1146,7 @@ void updateMultipleProperties() { "value")), new ArrayList()))); - propertyManager.update(Arrays.asList(testProperty0, testProperty0WithChannels)); + apiUpdate(Arrays.asList(testProperty0, testProperty0WithChannels)); // Query ChannelFinder and verify updated channels and properties Property foundProperty = propertyRepository.findById(testProperty0.getName(), true).get(); Assertions.assertEquals( @@ -1212,7 +1208,7 @@ void updateMultipleXmlPropertiesOnChan() { "valueX")), new ArrayList()))); - propertyManager.create(Arrays.asList(testProperty0WithChannels, testProperty1WithChannels)); + apiCreate(Arrays.asList(testProperty0WithChannels, testProperty1WithChannels)); // change owners and add channels and change values testProperty0WithChannels.setOwner("updateTestOwner"); testProperty0WithChannels.setChannels( @@ -1258,7 +1254,7 @@ void updateMultipleXmlPropertiesOnChan() { EMPTY_LIST))); // update both properties - propertyManager.update(Arrays.asList(testProperty0WithChannels, testProperty1WithChannels)); + apiUpdate(Arrays.asList(testProperty0WithChannels, testProperty1WithChannels)); // create expected properties // verify that the properties were updated @@ -1339,7 +1335,7 @@ void deleteXmlProperty() { EMPTY_LIST))); List testProperties = Arrays.asList(testProperty0, testProperty0WithChannels); - Iterable createdProperties = propertyManager.create(testProperties); + apiCreate(testProperties); propertyManager.remove(testProperty0.getName()); // verify the property was deleted as expected @@ -1376,7 +1372,7 @@ void deleteXmlPropertyFromChannel() { new ArrayList()))); Property createdProperty = - propertyManager.create(testProperty0WithChannels.getName(), testProperty0WithChannels); + apiCreate(testProperty0WithChannels.getName(), testProperty0WithChannels); propertyManager.removeSingle(testProperty0WithChannels.getName(), testChannel0.getName()); // verify the property was only removed from the single test channel @@ -1395,4 +1391,33 @@ void deleteXmlPropertyFromChannel() { }), "Failed to delete the property from channel"); } + + private Property apiCreate(String name, Property property) { + return PropertyMapper.toDomain(propertyManager.create(name, PropertyMapper.toDto(property))); + } + + private Iterable apiCreate(Iterable properties) { + return PropertyMapper.toDomains(propertyManager.create(PropertyMapper.toDtos(properties))); + } + + private Property apiRead(String name, boolean withChannels) { + return PropertyMapper.toDomain(propertyManager.read(name, withChannels)); + } + + private Iterable apiList() { + return PropertyMapper.toDomains(propertyManager.list()); + } + + private Property apiUpdate(String name, Property property) { + return PropertyMapper.toDomain(propertyManager.update(name, PropertyMapper.toDto(property))); + } + + private void apiUpdate(Iterable properties) { + propertyManager.update(PropertyMapper.toDtos(properties)); + } + + private Property apiAddSingle(String propertyName, String channelName, Property property) { + return PropertyMapper.toDomain( + propertyManager.addSingle(propertyName, channelName, PropertyMapper.toDto(property))); + } } diff --git a/src/test/java/org/phoebus/channelfinder/TagControllerIT.java b/src/test/java/org/phoebus/channelfinder/TagControllerIT.java index 3d2f833c..67c25167 100644 --- a/src/test/java/org/phoebus/channelfinder/TagControllerIT.java +++ b/src/test/java/org/phoebus/channelfinder/TagControllerIT.java @@ -24,6 +24,7 @@ import org.phoebus.channelfinder.repository.TagRepository; import org.phoebus.channelfinder.web.v0.api.ITag; import org.phoebus.channelfinder.web.v0.controller.TagController; +import org.phoebus.channelfinder.web.v0.mapper.TagMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; import org.springframework.security.test.context.support.WithMockUser; @@ -61,9 +62,9 @@ void listXmlTags() { testTag1.setChannels(testChannels()); List testTags = Arrays.asList(testTag0, testTag1); - Iterable createdTags = tagManager.create(testTags); + Iterable createdTags = apiCreate(testTags); - Iterable tagList = tagManager.list(); + Iterable tagList = apiList(); for (Tag tag : createdTags) { tag.setChannels(new ArrayList<>()); } @@ -78,23 +79,23 @@ void readXmlTag() { Tag testTag1 = new Tag("testTag1", "testOwner"); testTag1.setChannels(testChannels()); - Tag createdTag0 = tagManager.create(testTag0.getName(), testTag0); - Tag createdTag1 = tagManager.create(testTag1.getName(), testTag1); + Tag createdTag0 = apiCreate(testTag0.getName(), testTag0); + Tag createdTag1 = apiCreate(testTag1.getName(), testTag1); // verify the created tags are read as expected // Retrieve the testTag0 without channels - Tag retrievedTag = tagManager.read(createdTag0.getName(), false); + Tag retrievedTag = apiRead(createdTag0.getName(), false); Assertions.assertEquals(createdTag0, retrievedTag, "Failed to read the tag"); // Retrieve the testTag0 with channels - retrievedTag = tagManager.read(createdTag0.getName(), true); + retrievedTag = apiRead(createdTag0.getName(), true); Assertions.assertEquals(createdTag0, retrievedTag, "Failed to read the tag w/ channels"); // Retrieve the testTag1 without channels - retrievedTag = tagManager.read(createdTag1.getName(), false); + retrievedTag = apiRead(createdTag1.getName(), false); testTag1.setChannels(new ArrayList<>()); Assertions.assertEquals(testTag1, retrievedTag, "Failed to read the tag"); // Retrieve the testTag1 with channels - retrievedTag = tagManager.read(createdTag1.getName(), true); + retrievedTag = apiRead(createdTag1.getName(), true); Assertions.assertEquals(createdTag1, retrievedTag, "Failed to read the tag w/ channels"); } @@ -118,12 +119,12 @@ void createXmlTag() { Tag testTag0 = new Tag("testTag0", "testOwner"); // Create a simple tag - Tag createdTag = tagManager.create(testTag0.getName(), testTag0); + Tag createdTag = apiCreate(testTag0.getName(), testTag0); Assertions.assertEquals(testTag0, createdTag, "Failed to create the tag"); // Update the test tag with a new owner Tag updatedTestTag0 = new Tag("testTag0", "updateTestOwner"); - createdTag = tagManager.create(testTag0.getName(), copy(updatedTestTag0)); + createdTag = apiCreate(testTag0.getName(), copy(updatedTestTag0)); Assertions.assertEquals(updatedTestTag0, createdTag, "Failed to create the tag"); } @@ -133,8 +134,8 @@ void renameByCreateXmlTag() { Tag testTag0 = new Tag("testTag0", "testOwner"); Tag testTag1 = new Tag("testTag1", "testOwner"); - tagManager.create(testTag0.getName(), testTag0); - Tag createdTag = tagManager.create(testTag0.getName(), testTag1); + apiCreate(testTag0.getName(), testTag0); + Tag createdTag = apiCreate(testTag0.getName(), testTag1); // verify that the old tag "testTag0" was replaced with the new "testTag1" Assertions.assertEquals(testTag1, createdTag, "Failed to create the tag"); // verify that the old tag is no longer present @@ -148,7 +149,7 @@ void createXmlTag2() { Tag testTag0WithChannels = new Tag("testTag0WithChannels", "testOwner"); testTag0WithChannels.setChannels(testChannels()); - tagManager.create(testTag0WithChannels.getName(), testTag0WithChannels); + apiCreate(testTag0WithChannels.getName(), testTag0WithChannels); try { Tag foundTag = tagRepository.findById(testTag0WithChannels.getName(), true).get(); Tag expectedTag = new Tag("testTag0WithChannels", "testOwner"); @@ -178,7 +179,7 @@ void createXmlTag2() { Tag updatedTestTag0WithChannels = new Tag("testTag0WithChannels", "updateTestOwner"); - tagManager.create(testTag0WithChannels.getName(), copy(updatedTestTag0WithChannels)); + apiCreate(testTag0WithChannels.getName(), copy(updatedTestTag0WithChannels)); try { Tag foundTag = tagRepository.findById(updatedTestTag0WithChannels.getName(), true).get(); // verify the tag was created as expected @@ -199,9 +200,9 @@ void renameByCreateXmlTag2() { testTag1WithChannels.setChannels(testChannels()); // Create the testTag0WithChannels - tagManager.create(testTag0WithChannels.getName(), copy(testTag0WithChannels)); + apiCreate(testTag0WithChannels.getName(), copy(testTag0WithChannels)); // update the testTag0WithChannels with testTag1WithChannels - tagManager.create(testTag0WithChannels.getName(), copy(testTag1WithChannels)); + apiCreate(testTag0WithChannels.getName(), copy(testTag1WithChannels)); try { Tag foundTag = tagRepository.findById(testTag1WithChannels.getName(), true).get(); Assertions.assertFalse( @@ -245,7 +246,7 @@ void createXmlTags() { testTag1WithChannels, testTag2WithChannels); - tagManager.create(copy(testTags)); + apiCreate(copy(testTags)); List foundTags = new ArrayList(); testTags.forEach(tag -> foundTags.add(tagRepository.findById(tag.getName(), true).get())); Assertions.assertTrue(foundTags.contains(testTag0), "Failed to create the tags testTag0 "); @@ -281,15 +282,15 @@ void createXmlTagsWithOverride() { List testTags = Arrays.asList(testTag0, testTag0WithChannels); // Create a set of original tags to be overriden - tagManager.create("testTag0", copy(testTag0)); - tagManager.create("testTag0WithChannels", copy(testTag0WithChannels)); + apiCreate("testTag0", copy(testTag0)); + apiCreate("testTag0WithChannels", copy(testTag0WithChannels)); // Now update the test tags testTag0.setOwner("testOwner-updated"); testTag0WithChannels.setOwner("testOwner-updated"); testTag0WithChannels.setChannels(Arrays.asList(testChannel1)); List updatedTestTags = Arrays.asList(testTag0, testTag0WithChannels); - Iterable createdTags = tagManager.create(copy(updatedTestTags)); + apiCreate(copy(updatedTestTags)); // set owner back to original since it shouldn't change testTag0.setOwner("testOwner"); @@ -321,7 +322,7 @@ void addSingleXmlTag() { Tag testTag0 = new Tag("testTag0", "testOwner"); tagRepository.index(testTag0); - tagManager.addSingle(testTag0.getName(), "testChannel0"); + apiAddSingle(testTag0.getName(), "testChannel0"); Assertions.assertTrue( channelRepository.findById("testChannel0").get().getTags().stream() .anyMatch(t -> t.getName().equals(testTag0.getName())), @@ -339,14 +340,14 @@ void updateXmlTag() { // Update on a non-existing tag should result in the creation of that tag // 1. Test a simple tag - Tag returnedTag = tagManager.update(testTag0.getName(), copy(testTag0)); + Tag returnedTag = apiUpdate(testTag0.getName(), copy(testTag0)); Assertions.assertEquals(testTag0, returnedTag, "Failed to update tag " + testTag0); Assertions.assertEquals( testTag0, tagRepository.findById(testTag0.getName()).get(), "Failed to update tag " + testTag0); // 2. Test a tag with channels - returnedTag = tagManager.update(testTag0WithChannels.getName(), copy(testTag0WithChannels)); + returnedTag = apiUpdate(testTag0WithChannels.getName(), copy(testTag0WithChannels)); Assertions.assertTrue( returnedTag.getName().equalsIgnoreCase(testTag0WithChannels.getName()) && returnedTag.getChannels().size() == 1, @@ -358,14 +359,14 @@ void updateXmlTag() { // Update the tag owner testTag0.setOwner("newTestOwner"); - returnedTag = tagManager.update(testTag0.getName(), copy(testTag0)); + returnedTag = apiUpdate(testTag0.getName(), copy(testTag0)); Assertions.assertEquals(testTag0, returnedTag, "Failed to update tag " + testTag0); Assertions.assertEquals( testTag0, tagRepository.findById(testTag0.getName()).get(), "Failed to update tag " + testTag0); testTag0WithChannels.setOwner("newTestOwner"); - returnedTag = tagManager.update(testTag0WithChannels.getName(), copy(testTag0WithChannels)); + returnedTag = apiUpdate(testTag0WithChannels.getName(), copy(testTag0WithChannels)); Assertions.assertTrue( returnedTag.getName().equalsIgnoreCase(testTag0WithChannels.getName()) && returnedTag.getChannels().size() == 1, @@ -392,9 +393,9 @@ void updateXmlTagOnChan() { testTag1WithChannels.setChannels( Arrays.asList(testChannels().get(1), new Channel("testChannelX", "testOwner"))); - tagManager.create(testTag0WithChannels.getName(), testTag0WithChannels); + apiCreate(testTag0WithChannels.getName(), testTag0WithChannels); // change name and owner on existing channel, add to new channel - tagManager.update(testTag0WithChannels.getName(), testTag1WithChannels); + apiUpdate(testTag0WithChannels.getName(), testTag1WithChannels); Tag expectedTag = new Tag("testTag1WithChannels", "updateTestOwner"); expectedTag.setChannels( @@ -457,13 +458,11 @@ void renameByUpdateXmlTag() { testTag1WithChannels.setChannels(testChannels()); // Create the original tags - Tag createdTag = tagManager.create(testTag0.getName(), testTag0); - Tag createdTagWithChannels = - tagManager.create(testTag0WithChannels.getName(), testTag0WithChannels); + apiCreate(testTag0.getName(), testTag0); + apiCreate(testTag0WithChannels.getName(), testTag0WithChannels); // update the tags with new names, 0 -> 1 - Tag updatedTag = tagManager.update(testTag0.getName(), testTag1); - Tag updatedTagWithChannels = - tagManager.update(testTag0WithChannels.getName(), testTag1WithChannels); + apiUpdate(testTag0.getName(), testTag1); + apiUpdate(testTag0WithChannels.getName(), testTag1WithChannels); // verify that the old tag "testTag0" was replaced with the new "testTag1" Optional foundTag = tagRepository.findById(testTag1.getName()); @@ -493,11 +492,11 @@ void renameByUpdateXmlTag() { void updateTagTest1() { // A test tag with only name and owner Tag testTag0 = new Tag("testTag0", "testOwner"); - tagManager.create(testTag0.getName(), testTag0); + apiCreate(testTag0.getName(), testTag0); // Updating a tag with no channels, the new channels should be added to the tag // Add testChannel0 to testTag0 which has no channels testTag0.setChannels(Arrays.asList(testChannels().get(0))); - Tag returnedTag = tagManager.update(testTag0.getName(), copy(testTag0)); + Tag returnedTag = apiUpdate(testTag0.getName(), copy(testTag0)); Assertions.assertEquals( returnedTag, tagRepository.findById(testTag0.getName(), true).get(), @@ -513,14 +512,14 @@ void updateTagTest2() { // A test tag with testChannel0 Tag testTag0 = new Tag("testTag0", "testOwner"); testTag0.setChannels(Arrays.asList(testChannels().get(0))); - Tag createdTag = tagManager.create(testTag0.getName(), testTag0); + Tag createdTag = apiCreate(testTag0.getName(), testTag0); Assertions.assertSame(1, createdTag.getChannels().size(), "Failed to update tag " + testTag0); // Updating a tag with existing channels, the new channels should be added without affecting // existing channels // testTag0 already has testChannel0, the update operation should append the testChannel1 while // leaving the existing channel unaffected. testTag0.setChannels(Arrays.asList(testChannels().get(1))); - Tag returnedTag = tagManager.update(testTag0.getName(), copy(testTag0)); + apiUpdate(testTag0.getName(), copy(testTag0)); // Query ChannelFinder and verify updated channels and tags Tag foundTag = tagRepository.findById(testTag0.getName(), true).get(); @@ -537,12 +536,12 @@ void updateTagTest3() { Tag testTag0 = new Tag("testTag0", "testOwner"); testTag0.setChannels(Arrays.asList(testChannels().get(0))); - tagManager.create(testTag0.getName(), testTag0); + apiCreate(testTag0.getName(), testTag0); // testTag0 already has testChannel0, the update request (which repeats the testChannel0) should // append // the testChannel1 while leaving the existing channel unaffected. testTag0.setChannels(testChannels()); - tagManager.update(testTag0.getName(), copy(testTag0)); + apiUpdate(testTag0.getName(), copy(testTag0)); // Query ChannelFinder and verify updated channels and tags Tag foundTag = tagRepository.findById(testTag0.getName(), true).get(); @@ -578,12 +577,12 @@ void updateTagTest4() { // existing channels // testTag0 already has testChannel0 & testChannel1, the update request should be a NOP. testTag0.setChannels(testChannels()); - Tag returnedTag = tagManager.update(testTag0.getName(), copy(testTag0)); + Tag returnedTag = apiUpdate(testTag0.getName(), copy(testTag0)); Assertions.assertSame(2, returnedTag.getChannels().size(), "Failed to update tag " + testTag0); // Query ChannelFinder and verify updated channels and tags Tag foundTag = tagRepository.findById(testTag0.getName(), true).get(); - Tag expectedTag = tagManager.create(testTag0.getName(), testTag0); + Tag expectedTag = apiCreate(testTag0.getName(), testTag0); expectedTag.setChannels( Arrays.asList( new Channel( @@ -608,13 +607,13 @@ void updateTagTest5() { // A test tag with testChannel0,testChannel1 Tag testTag0 = new Tag("testTag0", "testOwner"); testTag0.setChannels(testChannels()); - Tag expectedTag = tagManager.create(testTag0.getName(), testTag0); + Tag expectedTag = apiCreate(testTag0.getName(), testTag0); // Updating a tag with existing channels, the new channels should be added without affecting // existing channels // testTag0 already has testChannel0 & testChannel1, the update operation should be a NOP. testTag0.setChannels(Arrays.asList(testChannels().get(0))); - Tag returnedTag = tagManager.update(testTag0.getName(), copy(testTag0)); + Tag returnedTag = apiUpdate(testTag0.getName(), copy(testTag0)); Assertions.assertSame(2, returnedTag.getChannels().size(), "Failed to update tag " + testTag0); // Query ChannelFinder and verify updated channels and tags Tag foundTag = tagRepository.findById(testTag0.getName(), true).get(); @@ -645,7 +644,7 @@ void updateMultipleTags() { testTag0WithChannels.setChannels(testChannels()); Iterable returnedTag = - tagManager.update(Arrays.asList(copy(testTag0), copy(testTag0WithChannels))); + apiUpdate(Arrays.asList(copy(testTag0), copy(testTag0WithChannels))); // Query ChannelFinder and verify updated channels and tags Optional foundTag = tagRepository.findById(testTag0.getName(), true); Assertions.assertTrue( @@ -670,7 +669,7 @@ void updateMultipleXmlTagsOnChan() { Tag testTag1WithChannels = new Tag("testTag1WithChannels", "testOwner"); testTag1WithChannels.setChannels(Arrays.asList(testChannels().get(1), testChannelX)); - tagManager.create(Arrays.asList(testTag0WithChannels, testTag1WithChannels)); + apiCreate(Arrays.asList(testTag0WithChannels, testTag1WithChannels)); // change owners and add channels testTag0WithChannels.setOwner("updateTestOwner"); testTag0WithChannels.setChannels(Arrays.asList(testChannels().get(1), testChannelX)); @@ -678,7 +677,7 @@ void updateMultipleXmlTagsOnChan() { testTag1WithChannels.setChannels(Arrays.asList(testChannels().get(0), testChannelX)); // update both tags - tagManager.update(Arrays.asList(testTag0WithChannels, testTag1WithChannels)); + apiUpdate(Arrays.asList(testTag0WithChannels, testTag1WithChannels)); // verify that the tags were updated Tag foundTag0 = tagRepository.findById(testTag0WithChannels.getName(), true).get(); @@ -729,7 +728,7 @@ void deleteXmlTag() { testTag1.setChannels(testChannels()); List testTags = Arrays.asList(testTag0, testTag1); - Iterable createdTags = tagManager.create(testTags); + apiCreate(testTags); tagManager.remove(testTag0.getName()); // verify the tag was deleted as expected @@ -754,7 +753,7 @@ void deleteXmlTagFromChannel() { Tag testTag1 = new Tag("testTag1", "testOwner"); testTag1.setChannels(testChannels()); - Tag createdTag = tagManager.create(testTag1.getName(), testTag1); + apiCreate(testTag1.getName(), testTag1); tagManager.removeSingle(testTag1.getName(), testChannels().get(0).getName()); // verify the tag was only removed from the single test channel @@ -825,4 +824,32 @@ private static List copy(List tags) { tags.forEach(tag -> copy.add(copy(tag))); return copy; } + + private Tag apiCreate(String name, Tag tag) { + return TagMapper.toDomain(tagManager.create(name, TagMapper.toDto(tag))); + } + + private Iterable apiCreate(Iterable tags) { + return TagMapper.toDomains(tagManager.create(TagMapper.toDtos(tags))); + } + + private Tag apiRead(String name, boolean withChannels) { + return TagMapper.toDomain(tagManager.read(name, withChannels)); + } + + private Iterable apiList() { + return TagMapper.toDomains(tagManager.list()); + } + + private Tag apiUpdate(String name, Tag tag) { + return TagMapper.toDomain(tagManager.update(name, TagMapper.toDto(tag))); + } + + private Iterable apiUpdate(Iterable tags) { + return TagMapper.toDomains(tagManager.update(TagMapper.toDtos(tags))); + } + + private Tag apiAddSingle(String tagName, String channelName) { + return TagMapper.toDomain(tagManager.addSingle(tagName, channelName)); + } } diff --git a/src/test/java/org/phoebus/channelfinder/epics/EpicsRPCRequestIT.java b/src/test/java/org/phoebus/channelfinder/epics/EpicsRPCRequestIT.java index 4cea3488..d79b49d3 100644 --- a/src/test/java/org/phoebus/channelfinder/epics/EpicsRPCRequestIT.java +++ b/src/test/java/org/phoebus/channelfinder/epics/EpicsRPCRequestIT.java @@ -23,6 +23,9 @@ import org.phoebus.channelfinder.web.v0.api.IChannel; import org.phoebus.channelfinder.web.v0.api.IProperty; import org.phoebus.channelfinder.web.v0.api.ITag; +import org.phoebus.channelfinder.web.v0.mapper.ChannelMapper; +import org.phoebus.channelfinder.web.v0.mapper.PropertyMapper; +import org.phoebus.channelfinder.web.v0.mapper.TagMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; import org.springframework.security.test.context.support.WithMockUser; @@ -77,16 +80,17 @@ void testRPCService() throws ExecutionException, InterruptedException, TimeoutEx Property testProperty0 = new Property("testProperty0", "testOwner", "testPropertyValue0"); Property testProperty1 = new Property("testProperty1", "testOwner", "testPropertyValue1"); List properties = List.of(testProperty0, testProperty1); - propertyManager.create(properties); + propertyManager.create(PropertyMapper.toDtos(properties)); testChannel0.setProperties(properties); // Create tag Tag tag = new Tag("testTag", "testOwner"); - tagManager.create(List.of(tag)); + tagManager.create(TagMapper.toDtos(List.of(tag))); testChannel0.setTags(List.of(tag)); // Create a simple channel - Channel createdChannel0 = channelManager.create(testChannel0.getName(), testChannel0); + ChannelMapper.toDomain( + channelManager.create(testChannel0.getName(), ChannelMapper.toDto(testChannel0))); Channel expectedChannel = new Channel("testChannel0", "testOwner");