Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix: check to determine if asset can be deleted #1408

Merged
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
1 change: 1 addition & 0 deletions common/util/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ publishing {
create<MavenPublication>("common-util") {
artifactId = "common-util"
from(components["java"])
artifacts.forEach { a -> println(a.file) }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ public class ReflectionUtil {
private static final String CLOSING_BRACKET = "]";

/**
* Utility function to get value of a field from an object. For field names currently the dot notation and array indexers are supported:
* Utility function to get value of a field from an object. For field names currently the dot notation and array
* indexers are supported:
* <pre>
* someObject.someValue
* someObject[2].someValue //someObject must impement the List interface
* </pre>
*
* @param object The object
* @param object The object
* @param propertyName The name of the field
* @return The field's value.
* @throws ReflectionException if the field does not exist or is not accessible
Expand All @@ -53,6 +54,9 @@ public static <T> T getFieldValue(String propertyName, Object object) {
var field = propertyName.substring(0, dotIx);
var rest = propertyName.substring(dotIx + 1);
object = getFieldValue(field, object);
if (object == null) {
return null;
}
return getFieldValue(rest, object);
} else if (propertyName.matches(ARRAY_INDEXER_REGEX)) { //array indexer
var openingBracketIx = propertyName.indexOf(OPENING_BRACKET);
Expand Down Expand Up @@ -82,10 +86,10 @@ public static <T> T getFieldValue(String propertyName, Object object) {


/**
* Utility function to get value of a field from an object. Essentially the same as {@link ReflectionUtil#getFieldValue(String, Object)}
* but it does not throw an exception
* Utility function to get value of a field from an object. Essentially the same as
* {@link ReflectionUtil#getFieldValue(String, Object)} but it does not throw an exception
*
* @param object The object
* @param object The object
* @param propertyName The name of the field
* @return The field's value. Returns null if the field does not exist or is inaccessible.
*/
Expand Down Expand Up @@ -118,9 +122,10 @@ public static <T> Comparator<T> propertyComparator(boolean isAscending, String p


/**
* Gets a field with a given name from all declared fields of a class including supertypes. Will include protected and private fields.
* Gets a field with a given name from all declared fields of a class including supertypes. Will include protected
* and private fields.
*
* @param clazz The class of the object
* @param clazz The class of the object
* @param fieldName The fieldname
* @return A field with the given name, null if the field does not exist
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2020 - 2022 Microsoft Corporation
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*
*/

package org.eclipse.dataspaceconnector.common.reflection;

public class AnotherObject {
private final String anotherDescription;

public AnotherObject(String desc) {
anotherDescription = desc;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,24 @@ void getFieldRecursive_whenNotDeclared() {
assertThat(ReflectionUtil.getFieldRecursive(to.getClass(), "notExist")).isNull();
}

@Test
void getFieldValue_whenParentExist() {
var to = new TestObjectSubSubclass("test-desc", 1, "foobar");
to.setAnotherObject(new AnotherObject("another-desc"));

String fieldValue = ReflectionUtil.getFieldValue("anotherObject.anotherDescription", to);
assertThat(fieldValue).isEqualTo("another-desc");
}

@Test
void getFieldValue_whenParentNotExist() {
var to = new TestObjectSubSubclass("test-desc", 1, "foobar");
to.setAnotherObject(null);

String fieldValue = ReflectionUtil.getFieldValue("anotherObject.anotherDescription", to);
assertThat(fieldValue).isNull();
}

@Test
void getFieldValue_withArrayIndex() {
var to1 = new TestObject("to1", 420);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

public class TestObjectSubSubclass extends TestObjectSubclass {
private final String description;
private AnotherObject anotherObject;

public TestObjectSubSubclass(String description, int priority, String testProperty) {
super(description, priority, testProperty);
Expand All @@ -26,4 +27,12 @@ public TestObjectSubSubclass(String description, int priority, String testProper
public String getDescription() {
return description;
}

public AnotherObject getAnotherObject() {
return anotherObject;
}

public void setAnotherObject(AnotherObject anotherObject) {
this.anotherObject = anotherObject;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.lang.String.format;
import static java.util.stream.Collectors.toList;

/**
* An in-memory, threadsafe process store.
* This implementation is intended for testing purposes only.
* An in-memory, threadsafe process store. This implementation is intended for testing purposes only.
*/
public class InMemoryContractNegotiationStore implements ContractNegotiationStore {

Expand Down Expand Up @@ -124,6 +124,14 @@ public void delete(String processId) {
return lockManager.readLock(() -> agreementQueryResolver.query(getAgreements(), querySpec));
}

@Override
public Stream<ContractNegotiation> getNegotiationsWithAgreementOnAsset(String assetId) {
var filter = format("contractAgreement.assetId = %s", assetId);
var query = QuerySpec.Builder.newInstance().filter(filter).build();

return queryNegotiations(query);
}

@Override
public @NotNull List<ContractNegotiation> nextForState(int state, int max) {
return lockManager.readLock(() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.dataspaceconnector.spi.query.SortOrder;
import org.eclipse.dataspaceconnector.spi.types.domain.contract.agreement.ContractAgreement;
import org.eclipse.dataspaceconnector.spi.types.domain.contract.negotiation.ContractNegotiation;
import org.eclipse.dataspaceconnector.spi.types.domain.contract.negotiation.ContractNegotiationStates;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -28,6 +29,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -320,6 +322,57 @@ void queryAgreements_verifySorting_invalidProperty() {
assertThat(store.queryAgreements(query)).isEmpty();
}

@Test
void getNegotiationsWithAgreementOnAsset_negotiationWithAgreement() {
var agreement = createAgreementBuilder().id("contract1").build();
var negotiation = createNegotiationBuilder("negotiation1").contractAgreement(agreement).build();
var assetId = agreement.getAssetId();

store.save(negotiation);

var result = store.getNegotiationsWithAgreementOnAsset(assetId).collect(Collectors.toList());

assertThat(result).hasSize(1).usingRecursiveFieldByFieldElementComparator().containsOnly(negotiation);
}

@Test
void getNegotiationsWithAgreementOnAsset_negotiationWithoutAgreement() {
var assetId = UUID.randomUUID().toString();
var negotiation = ContractNegotiation.Builder.newInstance()
.type(ContractNegotiation.Type.CONSUMER)
.id("negotiation1")
.contractAgreement(null)
.correlationId("corr-negotiation1")
.state(ContractNegotiationStates.REQUESTED.code())
.counterPartyAddress("consumer")
.counterPartyId("consumerId")
.protocol("ids-multipart")
.build();

store.save(negotiation);

var result = store.getNegotiationsWithAgreementOnAsset(assetId).collect(Collectors.toList());

assertThat(result).isEmpty();
assertThat(store.queryAgreements(QuerySpec.none())).isEmpty();
}

@Test
void getNegotiationsWithAgreementOnAsset_multipleNegotiationsSameAsset() {
var assetId = UUID.randomUUID().toString();
var negotiation1 = createNegotiationBuilder("negotiation1").contractAgreement(createAgreementBuilder().id("contract1").assetId(assetId).build()).build();
var negotiation2 = createNegotiationBuilder("negotiation2").contractAgreement(createAgreementBuilder().id("contract2").assetId(assetId).build()).build();

store.save(negotiation1);
store.save(negotiation2);

var result = store.getNegotiationsWithAgreementOnAsset(assetId).collect(Collectors.toList());

assertThat(result).hasSize(2)
.extracting(ContractNegotiation::getId).containsExactlyInAnyOrder("negotiation1", "negotiation2");

}

@NotNull
private ContractNegotiation requestingNegotiation() {
var negotiation = createNegotiation(UUID.randomUUID().toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,23 @@ public Collection<Asset> query(QuerySpec query) {
return transactionContext.execute(() -> index.queryAssets(query).collect(toList()));
}

@Override
public ServiceResult<Asset> create(Asset asset, DataAddress dataAddress) {
return transactionContext.execute(() -> {
if (findById(asset.getId()) == null) {
loader.accept(asset, dataAddress);
return ServiceResult.success(asset);
} else {
return ServiceResult.conflict(format("Asset %s cannot be created because it already exist", asset.getId()));
}
});
}

@Override
public ServiceResult<Asset> delete(String assetId) {
return transactionContext.execute(() -> {
var filter = format("contractAgreement.assetId = %s", assetId);
var query = QuerySpec.Builder.newInstance().filter(filter).build();

var negotiationsOnAsset = contractNegotiationStore.queryNegotiations(query);
var negotiationsOnAsset = contractNegotiationStore.getNegotiationsWithAgreementOnAsset(assetId);
if (negotiationsOnAsset.findAny().isPresent()) {
return ServiceResult.conflict(format("Asset %s cannot be deleted as it is referenced by at least one contract agreement", assetId));
}
Expand All @@ -70,16 +80,4 @@ public ServiceResult<Asset> delete(String assetId) {
return ServiceResult.success(deleted);
});
}

@Override
public ServiceResult<Asset> create(Asset asset, DataAddress dataAddress) {
return transactionContext.execute(() -> {
if (findById(asset.getId()) == null) {
loader.accept(asset, dataAddress);
return ServiceResult.success(asset);
} else {
return ServiceResult.conflict(format("Asset %s cannot be created because it already exist", asset.getId()));
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

class AssetServiceImplTest {
Expand Down Expand Up @@ -73,15 +74,17 @@ void query_shouldRelyOnAssetIndex() {

@Test
void createAsset_shouldCreateAssetIfItDoesNotAlreadyExist() {
var asset = createAsset("assetId");
when(index.findById("assetId")).thenReturn(null);
var dataAddress = DataAddress.Builder.newInstance().type("addressType").build();
var assetId = "assetId";
var asset = createAsset(assetId);
when(index.findById(assetId)).thenReturn(null);
var addressType = "addressType";
var dataAddress = DataAddress.Builder.newInstance().type(addressType).build();

var inserted = service.create(asset, dataAddress);

assertThat(inserted.succeeded()).isTrue();
assertThat(inserted.getContent()).matches(hasId("assetId"));
verify(loader).accept(argThat(it -> "assetId".equals(it.getId())), argThat(it -> "addressType".equals(it.getType())));
assertThat(inserted.getContent()).matches(hasId(assetId));
verify(loader).accept(argThat(it -> assetId.equals(it.getId())), argThat(it -> addressType.equals(it.getType())));
}

@Test
Expand Down Expand Up @@ -120,16 +123,18 @@ void delete_shouldNotDeleteIfAssetIsAlreadyPartOfAnAgreement() {
.id(UUID.randomUUID().toString())
.providerAgentId(UUID.randomUUID().toString())
.consumerAgentId(UUID.randomUUID().toString())
.assetId("assetId")
.assetId(asset.getId())
.policy(Policy.Builder.newInstance().build())
.build())
.build();
when(contractNegotiationStore.queryNegotiations(any())).thenReturn(Stream.of(contractNegotiation));
when(contractNegotiationStore.getNegotiationsWithAgreementOnAsset(any())).thenReturn(Stream.of(contractNegotiation));

var deleted = service.delete("assetId");

assertThat(deleted.failed()).isTrue();
assertThat(deleted.getFailure().getReason()).isEqualTo(CONFLICT);
verify(contractNegotiationStore).getNegotiationsWithAgreementOnAsset(any());
verifyNoMoreInteractions(contractNegotiationStore);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.lang.String.format;
import static java.util.Optional.ofNullable;
import static net.jodah.failsafe.Failsafe.with;

Expand Down Expand Up @@ -162,6 +163,14 @@ public void delete(String negotiationId) {
.filter(Objects::nonNull);
}

@Override
public Stream<ContractNegotiation> getNegotiationsWithAgreementOnAsset(String assetId) {
var filter = format("contractAgreement.assetId = %s", assetId);
var query = QuerySpec.Builder.newInstance().filter(filter).build();

return queryNegotiations(query);
}

@Override
public @NotNull List<ContractNegotiation> nextForState(int state, int max) {

Expand Down
Loading