diff --git a/core/graph/src/test/java/uk/gov/gchq/gaffer/graph/GraphTest.java b/core/graph/src/test/java/uk/gov/gchq/gaffer/graph/GraphTest.java index ae42ec9d588..e937196cce2 100644 --- a/core/graph/src/test/java/uk/gov/gchq/gaffer/graph/GraphTest.java +++ b/core/graph/src/test/java/uk/gov/gchq/gaffer/graph/GraphTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 Crown Copyright + * Copyright 2016-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -342,7 +342,7 @@ public void shouldCreateNewContextInstanceWhenExecuteOperation(@Mock final Store @Test public void shouldCreateNewContextInstanceWhenExecuteOutputOperation(@Mock final Store store) - throws OperationException, IOException { + throws OperationException { // Given final Schema schema = new Schema(); given(store.getProperties()).willReturn(new StoreProperties()); @@ -365,7 +365,7 @@ public void shouldCreateNewContextInstanceWhenExecuteOutputOperation(@Mock final @Test public void shouldCreateNewContextInstanceWhenExecuteJob(@Mock final Store store) - throws OperationException, IOException { + throws OperationException { // Given final Schema schema = new Schema(); given(store.getProperties()).willReturn(new StoreProperties()); @@ -1065,7 +1065,7 @@ public void shouldNotSetGraphViewOnOperationWhenOperationIsNotAGet(@Mock final S } @Test - public void shouldThrowExceptionIfStoreClassPropertyIsNotSet() throws OperationException { + public void shouldThrowExceptionIfStoreClassPropertyIsNotSet() { try { new Graph.Builder() .config(new GraphConfig.Builder() @@ -1097,15 +1097,10 @@ public void shouldThrowExceptionIfGraphIdIsMissing() { } @Test - public void shouldThrowExceptionIfSchemaIsInvalid() throws OperationException { + public void shouldThrowExceptionIfSchemaIsInvalid() { final StoreProperties storeProperties = new StoreProperties(); storeProperties.setStoreClass(TestStoreImpl.class.getName()); - try { - new Graph.Builder() - .config(new GraphConfig.Builder() - .graphId(GRAPH_ID) - .build()) - .addSchema(new Schema.Builder() + final Schema invalidSchema = new Schema.Builder() .type("int", new TypeDefinition.Builder() .clazz(Integer.class) .aggregateFunction(new Sum()) @@ -1126,13 +1121,17 @@ public void shouldThrowExceptionIfSchemaIsInvalid() throws OperationException { .vertex("string") .property("p2", "int") .build()) - .build()) + .build(); + final GraphConfig config = new GraphConfig.Builder() + .graphId(GRAPH_ID) + .build(); + assertThatExceptionOfType(SchemaException.class) + .isThrownBy(() -> new Graph.Builder() + .config(config) + .addSchema(invalidSchema) .storeProperties(storeProperties) - .build(); - fail("exception expected"); - } catch (final SchemaException e) { - assertNotNull(e.getMessage()); - } + .build()) + .withMessageContaining("Schema is not valid"); } @Test @@ -1254,7 +1253,7 @@ private void writeToFile(final String schemaFile, final File dir) throws IOExcep } @Test - public void shouldThrowExceptionIfGraphIdIsInvalid(@Mock final StoreProperties properties) throws Exception { + void shouldThrowExceptionIfGraphIdIsInvalid(@Mock final StoreProperties properties) { try { new Graph.Builder() .config(new GraphConfig.Builder() @@ -1355,8 +1354,7 @@ public void shouldBuildGraphUsingGraphIdAndLookupSchema() throws Exception { @Test public void shouldAddHooksVarArgsAndGetGraphHooks(@Mock final GraphHook graphHook1, - @Mock final Log4jLogger graphHook2) - throws Exception { + @Mock final Log4jLogger graphHook2) { // Given final StoreProperties storeProperties = new StoreProperties(); storeProperties.setStoreClass(TestStoreImpl.class.getName()); @@ -1382,8 +1380,7 @@ public void shouldAddHooksVarArgsAndGetGraphHooks(@Mock final GraphHook graphHoo @Test public void shouldAddHookAndGetGraphHooks(@Mock final GraphHook graphHook1, - @Mock final Log4jLogger graphHook3) - throws Exception { + @Mock final Log4jLogger graphHook3) { // Given final StoreProperties storeProperties = new StoreProperties(); storeProperties.setStoreClass(TestStore.class.getName()); @@ -1417,8 +1414,7 @@ public void shouldAddHookAndGetGraphHooks(@Mock final GraphHook graphHook1, @Test public void shouldAddNamedViewResolverHookAfterNamedOperationResolver(@Mock final GraphHook graphHook1, - @Mock final Log4jLogger graphHook2) - throws Exception { + @Mock final Log4jLogger graphHook2) { // Given final StoreProperties storeProperties = new StoreProperties(); storeProperties.setStoreClass(TestStore.class.getName()); @@ -1511,7 +1507,7 @@ public void shouldAddHookFromPathAndGetGraphHooks() throws Exception { } @Test - public void shouldBuildGraphFromConfigFile() throws Exception { + void shouldBuildGraphFromConfigFile() { // Given final StoreProperties storeProperties = new StoreProperties(); storeProperties.setStoreClass(TestStoreImpl.class.getName()); @@ -1541,8 +1537,7 @@ public void shouldBuildGraphFromConfigFile() throws Exception { @Test public void shouldBuildGraphFromConfigAndMergeConfigWithExistingConfig(@Mock final GraphLibrary library1, @Mock final GraphLibrary library2, - @Mock final GraphHook hook1, @Mock final GraphHook hook2, @Mock final GraphHook hook3) - throws Exception { + @Mock final GraphHook hook1, @Mock final GraphHook hook2, @Mock final GraphHook hook3) { // Given final StoreProperties storeProperties = new StoreProperties(); storeProperties.setStoreClass(TestStoreImpl.class.getName()); @@ -1591,8 +1586,7 @@ public void shouldBuildGraphFromConfigAndMergeConfigWithExistingConfig(@Mock fin @Test public void shouldBuildGraphFromConfigAndOverrideFields(@Mock final GraphLibrary library1, @Mock final GraphLibrary library2, - @Mock final GraphHook hook1, @Mock final GraphHook hook2, @Mock final GraphHook hook3) - throws Exception { + @Mock final GraphHook hook1, @Mock final GraphHook hook2, @Mock final GraphHook hook3) { // Given final StoreProperties storeProperties = new StoreProperties(); storeProperties.setStoreClass(TestStoreImpl.class.getName()); @@ -1642,7 +1636,7 @@ public void shouldBuildGraphFromConfigAndOverrideFields(@Mock final GraphLibrary } @Test - public void shouldReturnClonedViewFromConfig() throws Exception { + void shouldReturnClonedViewFromConfig() { // Given final StoreProperties storeProperties = new StoreProperties(); storeProperties.setStoreClass(TestStoreImpl.class.getName()); @@ -1840,8 +1834,7 @@ public void shouldCorrectlySetViewForNestedOperationChain() throws OperationExce } @Test - public void shouldThrowExceptionOnExecuteWithANullContext(@Mock final OperationChain opChain) - throws OperationException { + void shouldThrowExceptionOnExecuteWithANullContext(@Mock final OperationChain opChain) { // Given final Context context = null; @@ -1860,8 +1853,7 @@ public void shouldThrowExceptionOnExecuteWithANullContext(@Mock final OperationC } @Test - public void shouldThrowExceptionOnExecuteJobWithANullContext(@Mock final OperationChain opChain) - throws OperationException { + void shouldThrowExceptionOnExecuteJobWithANullContext(@Mock final OperationChain opChain) { // Given final Context context = null; @@ -1880,8 +1872,7 @@ public void shouldThrowExceptionOnExecuteJobWithANullContext(@Mock final Operati } @Test - public void shouldThrowExceptionOnExecuteWithANullUser(@Mock final OperationChain opChain) - throws OperationException { + void shouldThrowExceptionOnExecuteWithANullUser(@Mock final OperationChain opChain) { // Given final User user = null; @@ -1900,8 +1891,7 @@ public void shouldThrowExceptionOnExecuteWithANullUser(@Mock final OperationChai } @Test - public void shouldThrowExceptionOnExecuteJobWithANullUser(@Mock final OperationChain opChain) - throws OperationException { + void shouldThrowExceptionOnExecuteJobWithANullUser(@Mock final OperationChain opChain) { // Given final User user = null; @@ -1920,8 +1910,7 @@ public void shouldThrowExceptionOnExecuteJobWithANullUser(@Mock final OperationC } @Test - public void shouldThrowExceptionOnExecuteJobUsingJobWithANullContext(@Mock final OperationChain opChain) - throws OperationException { + void shouldThrowExceptionOnExecuteJobUsingJobWithANullContext(@Mock final OperationChain opChain) { // Given final Context context = null; @@ -1942,7 +1931,7 @@ public void shouldThrowExceptionOnExecuteJobUsingJobWithANullContext(@Mock final } @Test - public void shouldThrowExceptionOnExecuteJobUsingJobWithANullOperation() throws OperationException { + void shouldThrowExceptionOnExecuteJobUsingJobWithANullOperation() { // Given final Context context = new Context(); @@ -1963,7 +1952,7 @@ public void shouldThrowExceptionOnExecuteJobUsingJobWithANullOperation() throws } @Test - public void shouldThrowExceptionOnExecuteJobUsingJobWithANullJob() throws OperationException { + void shouldThrowExceptionOnExecuteJobUsingJobWithANullJob() { // Given final Context context = new Context(); @@ -1984,8 +1973,7 @@ public void shouldThrowExceptionOnExecuteJobUsingJobWithANullJob() throws Operat } @Test - public void shouldThrowExceptionOnExecuteJobUsingJobWithANullUser(@Mock final OperationChain opChain) - throws OperationException { + void shouldThrowExceptionOnExecuteJobUsingJobWithANullUser(@Mock final OperationChain opChain) { // Given final User user = null; @@ -2744,7 +2732,7 @@ protected OperationHandler getAddElementsHandler() { } @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return null; } diff --git a/core/graph/src/test/java/uk/gov/gchq/gaffer/integration/store/TestStore.java b/core/graph/src/test/java/uk/gov/gchq/gaffer/integration/store/TestStore.java index 7a3180ee22d..66c7ea242c2 100644 --- a/core/graph/src/test/java/uk/gov/gchq/gaffer/integration/store/TestStore.java +++ b/core/graph/src/test/java/uk/gov/gchq/gaffer/integration/store/TestStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 Crown Copyright + * Copyright 2016-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -86,7 +86,7 @@ protected OperationHandler getAddElementsHandler() { } @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return null; } diff --git a/core/operation/src/main/java/uk/gov/gchq/gaffer/operation/impl/delete/DeleteElements.java b/core/operation/src/main/java/uk/gov/gchq/gaffer/operation/impl/delete/DeleteElements.java index cb42b220cff..6a6995493e9 100644 --- a/core/operation/src/main/java/uk/gov/gchq/gaffer/operation/impl/delete/DeleteElements.java +++ b/core/operation/src/main/java/uk/gov/gchq/gaffer/operation/impl/delete/DeleteElements.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Crown Copyright + * Copyright 2024-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.core.type.TypeReference; + import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -25,7 +27,9 @@ import uk.gov.gchq.gaffer.data.element.Element; import uk.gov.gchq.gaffer.operation.Operation; import uk.gov.gchq.gaffer.operation.Validatable; +import uk.gov.gchq.gaffer.operation.io.InputOutput; import uk.gov.gchq.gaffer.operation.io.MultiInput; +import uk.gov.gchq.gaffer.operation.serialisation.TypeReferenceImpl; import uk.gov.gchq.koryphe.Since; import uk.gov.gchq.koryphe.Summary; @@ -50,7 +54,8 @@ @Summary("Deletes elements") public class DeleteElements implements Validatable, - MultiInput { + MultiInput, + InputOutput, Long> { private boolean validate = true; private boolean skipInvalidElements; private Iterable elements; @@ -92,6 +97,11 @@ public void setInput(final Iterable elements) { this.elements = elements; } + @Override + public TypeReference getOutputTypeReference() { + return new TypeReferenceImpl.Long(); + } + @Override public Map getOptions() { return options; @@ -154,7 +164,7 @@ public String toString() { public static class Builder extends Operation.BaseBuilder implements Validatable.Builder, - MultiInput.Builder { + MultiInput.Builder, InputOutput.Builder, Long, Builder> { public Builder() { super(new DeleteElements()); } diff --git a/core/store/src/main/java/uk/gov/gchq/gaffer/store/Store.java b/core/store/src/main/java/uk/gov/gchq/gaffer/store/Store.java index 40d37b067a1..03e55df93c7 100644 --- a/core/store/src/main/java/uk/gov/gchq/gaffer/store/Store.java +++ b/core/store/src/main/java/uk/gov/gchq/gaffer/store/Store.java @@ -899,7 +899,7 @@ public List getOperationChainOptimisers() { * * @return the implementation of the handler for {@link uk.gov.gchq.gaffer.operation.impl.delete.DeleteElements} */ - protected abstract OperationHandler getDeleteElementsHandler(); + protected abstract OutputOperationHandler getDeleteElementsHandler(); /** * Get this Store's implementation of the handler for {@link uk.gov.gchq.gaffer.operation.DeleteAllData}. diff --git a/core/store/src/test/java/uk/gov/gchq/gaffer/store/StoreTest.java b/core/store/src/test/java/uk/gov/gchq/gaffer/store/StoreTest.java index 27ae65325b7..6e614b7c279 100644 --- a/core/store/src/test/java/uk/gov/gchq/gaffer/store/StoreTest.java +++ b/core/store/src/test/java/uk/gov/gchq/gaffer/store/StoreTest.java @@ -40,7 +40,6 @@ import uk.gov.gchq.gaffer.data.element.LazyEntity; import uk.gov.gchq.gaffer.data.element.id.EntityId; import uk.gov.gchq.gaffer.data.elementdefinition.exception.SchemaException; -import uk.gov.gchq.gaffer.exception.SerialisationException; import uk.gov.gchq.gaffer.jobtracker.Job; import uk.gov.gchq.gaffer.jobtracker.JobDetail; import uk.gov.gchq.gaffer.jobtracker.JobStatus; @@ -420,7 +419,7 @@ public void shouldCloseOperationIfExceptionThrown(@Mock final StoreProperties pr } @Test - public void shouldThrowExceptionIfOperationChainIsInvalid(@Mock final StoreProperties properties) throws OperationException, StoreException { + public void shouldThrowExceptionIfOperationChainIsInvalid(@Mock final StoreProperties properties) throws StoreException { // Given final Schema schema = createSchemaMock(); final OperationChain opChain = new OperationChain<>(); @@ -440,7 +439,7 @@ public void shouldThrowExceptionIfOperationChainIsInvalid(@Mock final StorePrope } @Test - public void shouldCallDoUnhandledOperationWhenDoOperationWithUnknownOperationClass(@Mock final StoreProperties properties) throws Exception { + void shouldCallDoUnhandledOperationWhenDoOperationWithUnknownOperationClass(@Mock final StoreProperties properties) throws Exception { // Given final Schema schema = createSchemaMock(); final Operation operation = new SetVariable.Builder().variableName("aVariable").input("inputString").build(); @@ -806,7 +805,7 @@ public void shouldExecuteOperationChainJob(@Mock final StoreProperties propertie @Test public void shouldExecuteOperationJobAndWrapJobOperationInChain(@Mock final StoreProperties properties) - throws OperationException, InterruptedException, StoreException, SerialisationException { + throws OperationException, InterruptedException, StoreException { // Given final Operation operation = new GetVariables.Builder().variableNames(Lists.newArrayList()).build(); given(properties.getJobExecutorThreadCount()).willReturn(1); @@ -1185,7 +1184,7 @@ protected OperationHandler getAddElementsHandler() { @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return null; } @@ -1286,7 +1285,7 @@ protected OperationHandler getAddElementsHandler() { @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return null; } @@ -1396,7 +1395,7 @@ protected OperationHandler getAddElementsHandler() { } @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return null; } diff --git a/core/store/src/test/java/uk/gov/gchq/gaffer/store/integration/StoreIT.java b/core/store/src/test/java/uk/gov/gchq/gaffer/store/integration/StoreIT.java index 64f4d663311..a6806cdfa09 100644 --- a/core/store/src/test/java/uk/gov/gchq/gaffer/store/integration/StoreIT.java +++ b/core/store/src/test/java/uk/gov/gchq/gaffer/store/integration/StoreIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 Crown Copyright + * Copyright 2016-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -145,7 +145,7 @@ protected OperationHandler getAddElementsHandler() { } @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return null; } diff --git a/core/store/src/test/java/uk/gov/gchq/gaffer/store/operation/handler/TestAddToGraphLibraryImpl.java b/core/store/src/test/java/uk/gov/gchq/gaffer/store/operation/handler/TestAddToGraphLibraryImpl.java index 1ce44a44781..8e5f943ad2f 100644 --- a/core/store/src/test/java/uk/gov/gchq/gaffer/store/operation/handler/TestAddToGraphLibraryImpl.java +++ b/core/store/src/test/java/uk/gov/gchq/gaffer/store/operation/handler/TestAddToGraphLibraryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 Crown Copyright + * Copyright 2017-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -74,7 +74,7 @@ protected Class getRequiredParentSerialiserClass() { } @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return null; } } diff --git a/store-implementation/accumulo-store/src/main/java/uk/gov/gchq/gaffer/accumulostore/AccumuloStore.java b/store-implementation/accumulo-store/src/main/java/uk/gov/gchq/gaffer/accumulostore/AccumuloStore.java index 8e2ea59d92f..67131661c8d 100644 --- a/store-implementation/accumulo-store/src/main/java/uk/gov/gchq/gaffer/accumulostore/AccumuloStore.java +++ b/store-implementation/accumulo-store/src/main/java/uk/gov/gchq/gaffer/accumulostore/AccumuloStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 Crown Copyright + * Copyright 2016-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -443,7 +443,7 @@ protected OutputOperationHandler> getGetTraitsHandler } @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return new DeleteElementsHandler(); } diff --git a/store-implementation/accumulo-store/src/main/java/uk/gov/gchq/gaffer/accumulostore/operation/handler/DeleteElementsHandler.java b/store-implementation/accumulo-store/src/main/java/uk/gov/gchq/gaffer/accumulostore/operation/handler/DeleteElementsHandler.java index 0ab2b3df2b9..34e39e47578 100644 --- a/store-implementation/accumulo-store/src/main/java/uk/gov/gchq/gaffer/accumulostore/operation/handler/DeleteElementsHandler.java +++ b/store-implementation/accumulo-store/src/main/java/uk/gov/gchq/gaffer/accumulostore/operation/handler/DeleteElementsHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Crown Copyright + * Copyright 2024-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ package uk.gov.gchq.gaffer.accumulostore.operation.handler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import uk.gov.gchq.gaffer.accumulostore.AccumuloStore; import uk.gov.gchq.gaffer.data.element.Element; import uk.gov.gchq.gaffer.operation.OperationException; @@ -24,20 +27,24 @@ import uk.gov.gchq.gaffer.store.Store; import uk.gov.gchq.gaffer.store.StoreException; import uk.gov.gchq.gaffer.store.ValidatedElements; -import uk.gov.gchq.gaffer.store.operation.handler.OperationHandler; +import uk.gov.gchq.gaffer.store.operation.handler.OutputOperationHandler; + +import java.util.ArrayList; +import java.util.List; -public class DeleteElementsHandler implements OperationHandler { +public class DeleteElementsHandler implements OutputOperationHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(DeleteElementsHandler.class); @Override - public Object doOperation(final DeleteElements operation, + public Long doOperation(final DeleteElements operation, final Context context, final Store store) throws OperationException { - deleteElements(operation, (AccumuloStore) store); - return null; + return deleteElements(operation, (AccumuloStore) store); } - private void deleteElements(final DeleteElements operation, final AccumuloStore store) + private Long deleteElements(final DeleteElements operation, final AccumuloStore store) throws OperationException { + final List deletedElements = new ArrayList<>(); try { final Iterable validatedElements; if (operation.isValidate()) { @@ -46,9 +53,17 @@ private void deleteElements(final DeleteElements operation, final AccumuloStore } else { validatedElements = operation.getInput(); } + + for (final Element el : validatedElements) { + deletedElements.add(el.toString()); + } + LOGGER.debug("Deleting elements: {}", deletedElements); + store.deleteElements(validatedElements); } catch (final StoreException e) { throw new OperationException("Failed to delete elements", e); } + + return (long) deletedElements.size(); } } diff --git a/store-implementation/accumulo-store/src/test/java/uk/gov/gchq/gaffer/accumulostore/integration/delete/AbstractDeletedElementsIT.java b/store-implementation/accumulo-store/src/test/java/uk/gov/gchq/gaffer/accumulostore/integration/delete/AbstractDeletedElementsIT.java index 2835ed6ae3d..14688945e1f 100644 --- a/store-implementation/accumulo-store/src/test/java/uk/gov/gchq/gaffer/accumulostore/integration/delete/AbstractDeletedElementsIT.java +++ b/store-implementation/accumulo-store/src/test/java/uk/gov/gchq/gaffer/accumulostore/integration/delete/AbstractDeletedElementsIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2024 Crown Copyright + * Copyright 2018-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -114,7 +114,7 @@ public void shouldNotReturnDeletedElements() throws Exception { assertElements((Iterable) elements, resultBefore); // When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("1")) .build()) diff --git a/store-implementation/accumulo-store/src/test/java/uk/gov/gchq/gaffer/accumulostore/operation/handler/DeleteElementsHandlerTest.java b/store-implementation/accumulo-store/src/test/java/uk/gov/gchq/gaffer/accumulostore/operation/handler/DeleteElementsHandlerTest.java index 1b7e0e05894..3447b8c66ac 100644 --- a/store-implementation/accumulo-store/src/test/java/uk/gov/gchq/gaffer/accumulostore/operation/handler/DeleteElementsHandlerTest.java +++ b/store-implementation/accumulo-store/src/test/java/uk/gov/gchq/gaffer/accumulostore/operation/handler/DeleteElementsHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Crown Copyright + * Copyright 2024-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ import uk.gov.gchq.gaffer.store.StoreException; import uk.gov.gchq.gaffer.store.ValidatedElements; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyIterable; @@ -45,7 +46,8 @@ void shouldDoOperationValidated() throws Exception { .build(); AccumuloStore store = Mockito.mock(AccumuloStore.class); - handler.doOperation(op, new Context(), store); + final Object elementCount = handler.doOperation(op, new Context(), store); + assertThat(elementCount).isEqualTo(1L); verify(store).deleteElements(any(ValidatedElements.class)); } @@ -60,7 +62,8 @@ void shouldDoOperationNotValidated() throws Exception { .build(); AccumuloStore store = Mockito.mock(AccumuloStore.class); - handler.doOperation(op, new Context(), store); + final Object elementCount = handler.doOperation(op, new Context(), store); + assertThat(elementCount).isEqualTo(1L); verify(store).deleteElements(anyIterable()); } diff --git a/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedStore.java b/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedStore.java index 6b8d4780c8b..5f58b9aff63 100644 --- a/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedStore.java +++ b/store-implementation/federated-store/src/main/java/uk/gov/gchq/gaffer/federatedstore/FederatedStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 Crown Copyright + * Copyright 2017-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -550,8 +550,8 @@ protected OutputOperationHandler> ge } @Override - protected OperationHandler getDeleteElementsHandler() { - return new FederatedNoOutputHandler<>(); + protected OutputOperationHandler getDeleteElementsHandler() { + return new FederatedOutputHandler<>(); } @Override diff --git a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedDeleteElementsTest.java b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedDeleteElementsTest.java index badad7f056b..38c8c5db433 100644 --- a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedDeleteElementsTest.java +++ b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedDeleteElementsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Crown Copyright + * Copyright 2024-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -86,7 +86,7 @@ public void setUp() throws Exception { @Test void shouldDeleteEntityFromSingleGraphWithMapStore() throws Exception { // When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("1")) .view(new View.Builder().entity(GROUP_BASIC_ENTITY).build()) @@ -108,7 +108,7 @@ void shouldDeleteEntityFromSingleGraphWithMapStore() throws Exception { @Test void shouldDeleteEdgeFromSingleGraphWithMapStore() throws Exception { // When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EdgeSeed("1", "2")) .view(new View.Builder().edge(GROUP_BASIC_EDGE).build()) @@ -130,7 +130,7 @@ void shouldDeleteEdgeFromSingleGraphWithMapStore() throws Exception { @Test void shouldDeleteEntityAndEdgesFromSingleGraphhWithMapStore() throws Exception { // Given/When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("2")) .build()) @@ -152,7 +152,7 @@ void shouldDeleteEntityAndEdgesFromSingleGraphhWithMapStore() throws Exception { @Test void shouldDeleteEntityFromBothGraphsWithMapStore() throws Exception { // When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("1")) .view(new View.Builder().entity(GROUP_BASIC_ENTITY).build()) @@ -174,7 +174,7 @@ void shouldDeleteEntityFromBothGraphsWithMapStore() throws Exception { @Test void shouldDeleteEdgeFromBothGraphsWithMapStore() throws Exception { // When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EdgeSeed("1", "2")) .view(new View.Builder().edge(GROUP_BASIC_EDGE).build()) @@ -196,7 +196,7 @@ void shouldDeleteEdgeFromBothGraphsWithMapStore() throws Exception { @Test void shouldDeleteEntityAndEdgesFromBothGraphshWithMapStore() throws Exception { // Given/When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("3")) .build()) @@ -217,7 +217,7 @@ void shouldDeleteEntityAndEdgesFromBothGraphshWithMapStore() throws Exception { @Test void shouldDeleteEntityFromSingleGraphWithAccumuloStore() throws Exception { // When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("1")) .view(new View.Builder().entity(GROUP_BASIC_ENTITY).build()) @@ -239,7 +239,7 @@ void shouldDeleteEntityFromSingleGraphWithAccumuloStore() throws Exception { @Test void shouldDeleteEdgeFromSingleGraphWithAccumuloStore() throws Exception { // When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EdgeSeed("1", "2")) .view(new View.Builder().edge(GROUP_BASIC_EDGE).build()) @@ -261,7 +261,7 @@ void shouldDeleteEdgeFromSingleGraphWithAccumuloStore() throws Exception { @Test void shouldDeleteEntityAndEdgesFromSingleGraphhWithAccumuloStore() throws Exception { // Given/When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("2")) .build()) @@ -283,7 +283,7 @@ void shouldDeleteEntityAndEdgesFromSingleGraphhWithAccumuloStore() throws Except @Test void shouldDeleteEntityFromBothGraphsWithAccumuloStore() throws Exception { // When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("1")) .view(new View.Builder().entity(GROUP_BASIC_ENTITY).build()) @@ -305,7 +305,7 @@ void shouldDeleteEntityFromBothGraphsWithAccumuloStore() throws Exception { @Test void shouldDeleteEdgeFromBothGraphsWithAccumuloStore() throws Exception { // When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EdgeSeed("1", "2")) .view(new View.Builder().edge(GROUP_BASIC_EDGE).build()) @@ -327,7 +327,7 @@ void shouldDeleteEdgeFromBothGraphsWithAccumuloStore() throws Exception { @Test void shouldDeleteEntityAndEdgesFromBothGraphshWithAccumuloStore() throws Exception { // Given/When - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("3")) .build()) diff --git a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedGetTraitsHandlerTest.java b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedGetTraitsHandlerTest.java index b06a9b35a70..58084c3920e 100644 --- a/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedGetTraitsHandlerTest.java +++ b/store-implementation/federated-store/src/test/java/uk/gov/gchq/gaffer/federatedstore/operation/handler/impl/FederatedGetTraitsHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2024 Crown Copyright + * Copyright 2018-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -288,7 +288,7 @@ protected OperationHandler getAddElementsHandler() { } @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return null; } diff --git a/store-implementation/map-store/src/main/java/uk/gov/gchq/gaffer/mapstore/MapStore.java b/store-implementation/map-store/src/main/java/uk/gov/gchq/gaffer/mapstore/MapStore.java index 528632ce895..9ab0624a971 100644 --- a/store-implementation/map-store/src/main/java/uk/gov/gchq/gaffer/mapstore/MapStore.java +++ b/store-implementation/map-store/src/main/java/uk/gov/gchq/gaffer/mapstore/MapStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2024 Crown Copyright + * Copyright 2017-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -176,7 +176,7 @@ protected OperationHandler getAddElementsHandler() { } @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return new DeleteElementsHandler(); } diff --git a/store-implementation/map-store/src/main/java/uk/gov/gchq/gaffer/mapstore/impl/DeleteElementsHandler.java b/store-implementation/map-store/src/main/java/uk/gov/gchq/gaffer/mapstore/impl/DeleteElementsHandler.java index 99e05619494..11946a28584 100644 --- a/store-implementation/map-store/src/main/java/uk/gov/gchq/gaffer/mapstore/impl/DeleteElementsHandler.java +++ b/store-implementation/map-store/src/main/java/uk/gov/gchq/gaffer/mapstore/impl/DeleteElementsHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Crown Copyright + * Copyright 2024-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,31 +31,39 @@ import uk.gov.gchq.gaffer.store.Context; import uk.gov.gchq.gaffer.store.Store; import uk.gov.gchq.gaffer.store.ValidatedElements; -import uk.gov.gchq.gaffer.store.operation.handler.OperationHandler; +import uk.gov.gchq.gaffer.store.operation.handler.OutputOperationHandler; import uk.gov.gchq.gaffer.store.schema.Schema; import uk.gov.gchq.gaffer.store.util.AggregatorUtil; +import java.util.ArrayList; +import java.util.List; + /** - * An {@link OperationHandler} for the {@link DeleteElements} operation on the - * {@link MapStore}. + * An {@link OutputOperationHandler} for the {@link DeleteElements} operation on the + * {@link MapStore}. Returns a string of how many elements have been deleted. */ -public class DeleteElementsHandler implements OperationHandler { +public class DeleteElementsHandler implements OutputOperationHandler { private static final Logger LOGGER = LoggerFactory.getLogger(DeleteElementsHandler.class); @Override - public Object doOperation(final DeleteElements deleteElements, final Context context, final Store store) { + public Long doOperation(final DeleteElements deleteElements, final Context context, final Store store) { Iterable elements = deleteElements.getInput(); if (deleteElements.isValidate()) { elements = new ValidatedElements(elements, store.getSchema(), deleteElements.isSkipInvalidElements()); } - deleteElements(elements, (MapStore) store); - return null; + return deleteElements(elements, (MapStore) store); } - private void deleteElements(final Iterable elements, final MapStore mapStore) { + private Long deleteElements(final Iterable elements, final MapStore mapStore) { final MapImpl mapImpl = mapStore.getMapImpl(); final Schema schema = mapStore.getSchema(); + final List deletedElements = new ArrayList<>(); + + for (final Element el : elements) { + deletedElements.add(el.toString()); + } + LOGGER.debug("Deleting elements: {}", deletedElements); final int bufferSize = mapStore.getProperties().getIngestBufferSize(); @@ -67,6 +75,8 @@ private void deleteElements(final Iterable elements, final Ma // Stream of lists that gets each batch Streams.toBatches(elements, bufferSize).forEach(batch -> deleteBatch(mapImpl, schema, AggregatorUtil.ingestAggregate(batch, schema))); } + + return (long) deletedElements.size(); } private void deleteBatch(final MapImpl mapImpl, final Schema schema, final Iterable elements) { diff --git a/store-implementation/map-store/src/test/java/uk/gov/gchq/gaffer/mapstore/impl/DeleteElementsHandlerTest.java b/store-implementation/map-store/src/test/java/uk/gov/gchq/gaffer/mapstore/impl/DeleteElementsHandlerTest.java index a1cca81557b..dcf80460534 100644 --- a/store-implementation/map-store/src/test/java/uk/gov/gchq/gaffer/mapstore/impl/DeleteElementsHandlerTest.java +++ b/store-implementation/map-store/src/test/java/uk/gov/gchq/gaffer/mapstore/impl/DeleteElementsHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Crown Copyright + * Copyright 2024-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,7 +76,7 @@ void shouldDeleteEntityOnlyForAggregatedGraph() throws OperationException { // Given/When // Delete Vertex A - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("A")) .view(ENTITY_VIEW) @@ -84,7 +84,8 @@ void shouldDeleteEntityOnlyForAggregatedGraph() throws OperationException { .then(new DeleteElements()) .build(); - aggregatedGraph.execute(chain, USER); + final Object deletedCount = aggregatedGraph.execute(chain, USER); + assertThat(deletedCount).isEqualTo(1L); // Then @@ -111,7 +112,7 @@ void shouldDeleteEdgeOnlyForAggregatedGraph() throws OperationException { // Given/When // Delete Edge B->C - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EdgeSeed("B", "C")) .view(EDGE_VIEW) @@ -119,7 +120,8 @@ void shouldDeleteEdgeOnlyForAggregatedGraph() throws OperationException { .then(new DeleteElements()) .build(); - aggregatedGraph.execute(chain, USER); + final Object elementCount = aggregatedGraph.execute(chain, USER); + assertThat(elementCount).isEqualTo(1L); // Then @@ -146,7 +148,7 @@ void shouldDeleteEntityOnlyForNonAggregatedGraph() throws OperationException { // Given/When // Delete Vertex A - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("A")) .view(ENTITY_VIEW) @@ -154,7 +156,8 @@ void shouldDeleteEntityOnlyForNonAggregatedGraph() throws OperationException { .then(new DeleteElements()) .build(); - nonAggregatedGraph.execute(chain, USER); + final Object elementCount = nonAggregatedGraph.execute(chain, USER); + assertThat(elementCount).isEqualTo(1L); // Then @@ -182,7 +185,7 @@ void shouldDeleteEdgeOnlyForNonAggregatedGraph() throws OperationException { // When // Delete Edge B->C - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EdgeSeed("B", "C")) .view(EDGE_VIEW) @@ -190,7 +193,8 @@ void shouldDeleteEdgeOnlyForNonAggregatedGraph() throws OperationException { .then(new DeleteElements()) .build(); - nonAggregatedGraph.execute(chain, USER); + final Object elementCount = nonAggregatedGraph.execute(chain, USER); + assertThat(elementCount).isEqualTo(1L); // Then @@ -217,14 +221,15 @@ void shouldDeleteEntityAndEdgeForAggregatedGraph() throws OperationException { // Given/When // Delete Vertex A and its edges - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("A")) .build()) .then(new DeleteElements()) .build(); - aggregatedGraph.execute(chain, USER); + final Object elementCount = aggregatedGraph.execute(chain, USER); + assertThat(elementCount).isEqualTo(2L); // Then @@ -249,14 +254,15 @@ void shouldDeleteEntityAndEdgeForNonAggregatedGraph() throws OperationException // Given/When // Delete Vertex A and its edges - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("A")) .build()) .then(new DeleteElements()) .build(); - nonAggregatedGraph.execute(chain, USER); + final Object elementCount = nonAggregatedGraph.execute(chain, USER); + assertThat(elementCount).isEqualTo(2L); // Then @@ -281,14 +287,15 @@ void shouldDeleteEntityAndAllEdgesForAggregatedGraph() throws OperationException // Given/When // Delete Vertex B and its edges - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("B")) .build()) .then(new DeleteElements()) .build(); - aggregatedGraph.execute(chain, USER); + final Object elementCount = aggregatedGraph.execute(chain, USER); + assertThat(elementCount).isEqualTo(3L); // Then @@ -313,14 +320,15 @@ void shouldDeleteEntityAndAllEdgesForNonAggregatedGraph() throws OperationExcept // Given/When // Delete Vertex B and its edges - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetElements.Builder() .input(new EntitySeed("B")) .build()) .then(new DeleteElements()) .build(); - nonAggregatedGraph.execute(chain, USER); + final Object elementCount = nonAggregatedGraph.execute(chain, USER); + assertThat(elementCount).isEqualTo(3L); // Then @@ -345,13 +353,14 @@ void shouldDeleteAll() throws OperationException { // Given/When // Delete all - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetAllElements.Builder() .build()) .then(new DeleteElements()) .build(); - aggregatedGraph.execute(chain, USER); + final Object elementCount = aggregatedGraph.execute(chain, USER); + assertThat(elementCount).isEqualTo(5L); // Then @@ -384,7 +393,7 @@ void shouldDeleteElementsInBatches() throws StoreException, OperationException { // When // Delete all - final OperationChain chain = new OperationChain.Builder() + final OperationChain chain = new OperationChain.Builder() .first(new GetAllElements.Builder() .build()) .then(new DeleteElements()) diff --git a/store-implementation/proxy-store/src/main/java/uk/gov/gchq/gaffer/proxystore/ProxyStore.java b/store-implementation/proxy-store/src/main/java/uk/gov/gchq/gaffer/proxystore/ProxyStore.java index dd49f4cb214..8dfaf951429 100644 --- a/store-implementation/proxy-store/src/main/java/uk/gov/gchq/gaffer/proxystore/ProxyStore.java +++ b/store-implementation/proxy-store/src/main/java/uk/gov/gchq/gaffer/proxystore/ProxyStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 Crown Copyright + * Copyright 2016-2025 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -366,7 +366,7 @@ protected OperationHandler getAddElementsHandler() { } @Override - protected OperationHandler getDeleteElementsHandler() { + protected OutputOperationHandler getDeleteElementsHandler() { return null; } diff --git a/store-implementation/simple-federated-store/src/main/java/uk/gov/gchq/gaffer/federated/simple/FederatedStore.java b/store-implementation/simple-federated-store/src/main/java/uk/gov/gchq/gaffer/federated/simple/FederatedStore.java index 8bd4372c0aa..80c01f077cb 100644 --- a/store-implementation/simple-federated-store/src/main/java/uk/gov/gchq/gaffer/federated/simple/FederatedStore.java +++ b/store-implementation/simple-federated-store/src/main/java/uk/gov/gchq/gaffer/federated/simple/FederatedStore.java @@ -441,8 +441,8 @@ protected OperationHandler getAddElementsHandler() { } @Override - protected OperationHandler getDeleteElementsHandler() { - return new FederatedOperationHandler<>(); + protected OutputOperationHandler getDeleteElementsHandler() { + return new FederatedOutputHandler<>(); } @Override