Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.phoebus.channelfinder.common.TextUtil;
Expand Down Expand Up @@ -204,7 +206,7 @@ public Iterable<Property> update(Iterable<Property> properties) {
return properties;
}

public void remove(String propertyName) {
public void removeBatch(String propertyName) {
requireRole(ROLES.CF_PROPERTY, propertyName);

Property existing =
Expand Down Expand Up @@ -232,6 +234,61 @@ public void removeSingle(String propertyName, String channelName) {
channelRepository.index(channel);
}

/**
* Remove property from multiple channels.
*
* <p>Best-effort processing: non-existent channels are ignored, duplicates are deduplicated. Only
* channels where the property actually existed contribute to the returned count.
*
* @param propertyName name of the property to remove
* @param channelNames list of channel names to remove property from
* @return count of channels where property was actually removed
* @throws PropertyNotFoundException if property does not exist
* @throws UnauthorizedException if user lacks CF_PROPERTY role or is not property owner
*/
public long removeBatch(String propertyName, List<String> channelNames) {
requireRole(ROLES.CF_PROPERTY, propertyName);

Property property =
propertyRepository
.findById(propertyName)
.orElseThrow(() -> new PropertyNotFoundException(propertyName));
requireOwner(property);

// Normalize and deduplicate incoming channel names
Set<String> uniqueChannelNames = new HashSet<>(channelNames);

if (uniqueChannelNames.isEmpty()) {
return 0;
}

List<Channel> existingChannels = channelRepository.findAllById(uniqueChannelNames);
long removedCount = 0;
List<Channel> modifiedChannels = new ArrayList<>();

for (Channel channel : existingChannels) {
// Check if property exists before removal
boolean hadProperty =
channel.getProperties().stream().anyMatch(p -> p.getName().equals(propertyName));

if (hadProperty) {
// Create a minimal Property object for removal (matching removeSingle pattern)
channel.removeProperty(new Property(propertyName, ""));
removedCount++;
modifiedChannels.add(channel);
audit.log(
Level.INFO,
() ->
MessageFormat.format(
"Removed property {0} from channel {1}", propertyName, channel.getName()));
}
}
if (!modifiedChannels.isEmpty()) {
channelRepository.indexAll(modifiedChannels);
}
return removedCount;
}

private void propagateRenameToChannels(
String oldPropertyName, Property updated, List<Channel> existingChannels) {
if (existingChannels.isEmpty()) return;
Expand Down
37 changes: 29 additions & 8 deletions src/main/java/org/phoebus/channelfinder/web/v0/api/IProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +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 java.util.List;
import org.phoebus.channelfinder.web.v0.dto.PropertyDto;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down Expand Up @@ -234,7 +235,7 @@ PropertyDto update(
content = @Content(schema = @Schema(implementation = ResponseStatusException.class)))
})
@DeleteMapping("/{propertyName}")
void remove(@PathVariable("propertyName") String propertyName);
void removeBatch(@PathVariable("propertyName") String propertyName);

@Operation(
summary = "Delete property from a channel",
Expand Down Expand Up @@ -263,11 +264,31 @@ void removeSingle(
@PathVariable("propertyName") String propertyName,
@PathVariable("channelName") String channelName);

/**
* Checks if 1. the property name is not null and matches the name in the body 2. the property
* owner is not null or empty 3. all the listed channels exist and have the property with a non
* null and non empty value
*
* @param property validate property
*/
@Operation(
summary = "Delete property from multiple channels",
description =
"Remove the specified property from a list of channels. Best-effort processing: non-existent channels are ignored, duplicates are deduplicated. Returns count of channels where property was actually removed.",
operationId = "deletePropertyFromChannels",
tags = {"Property"})
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "Number of channels where property was removed"),
@ApiResponse(
responseCode = "401",
description = "Unauthorized",
content = @Content(schema = @Schema(implementation = ResponseStatusException.class))),
@ApiResponse(
responseCode = "404",
description = "Property not found",
content = @Content(schema = @Schema(implementation = ResponseStatusException.class))),
@ApiResponse(
responseCode = "500",
description = "Error while trying to remove property from channels",
content = @Content(schema = @Schema(implementation = ResponseStatusException.class)))
})
@DeleteMapping("/{propertyName}/channels")
long removeBatch(
@PathVariable("propertyName") String propertyName, @RequestBody List<String> channelNames);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.phoebus.channelfinder.web.v0.controller;

import java.util.List;
import org.phoebus.channelfinder.service.PropertyService;
import org.phoebus.channelfinder.web.v0.api.IProperty;
import org.phoebus.channelfinder.web.v0.dto.PropertyDto;
Expand Down Expand Up @@ -58,12 +59,17 @@ public Iterable<PropertyDto> update(Iterable<PropertyDto> properties) {
}

@Override
public void remove(String propertyName) {
propertyService.remove(propertyName);
public void removeBatch(String propertyName) {
propertyService.removeBatch(propertyName);
}

@Override
public void removeSingle(String propertyName, String channelName) {
propertyService.removeSingle(propertyName, channelName);
}

@Override
public long removeBatch(String propertyName, List<String> channelNames) {
return propertyService.removeBatch(propertyName, channelNames);
}
}
Loading
Loading