• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FIWARE / contract-management / #28

28 Jan 2025 01:52PM UTC coverage: 0.982%. Remained the same
#28

push

web-flow
Merge pull request #4 from FIWARE/tpp-integration

fix empty list

0 of 2 new or added lines in 1 file covered. (0.0%)

281 of 28626 relevant lines covered (0.98%)

0.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/org/fiware/iam/tmforum/handlers/ProductOrderEventHandler.java
1
package org.fiware.iam.tmforum.handlers;
2

3
import com.fasterxml.jackson.databind.ObjectMapper;
4
import io.micronaut.http.HttpResponse;
5
import io.micronaut.http.HttpResponseFactory;
6
import io.micronaut.http.HttpStatus;
7
import jakarta.inject.Singleton;
8
import lombok.RequiredArgsConstructor;
9
import lombok.extern.slf4j.Slf4j;
10
import org.fiware.iam.TMFMapper;
11
import org.fiware.iam.dsp.RainbowAdapter;
12
import org.fiware.iam.til.TrustedIssuersListAdapter;
13
import org.fiware.iam.tmforum.OrganizationResolver;
14
import org.fiware.iam.tmforum.TMForumAdapter;
15
import org.fiware.iam.tmforum.agreement.model.RelatedPartyTmfVO;
16
import org.fiware.iam.tmforum.productorder.model.*;
17
import org.fiware.rainbow.model.AgreementVO;
18
import reactor.core.publisher.Mono;
19

20
import java.util.*;
21
import java.util.function.Function;
22
import java.util.stream.Stream;
23

24

25
/**
26
 * Handle all incoming events in connection to ProductOrder
27
 */
28
@RequiredArgsConstructor
29
@Singleton
30
@Slf4j
×
31
public class ProductOrderEventHandler implements EventHandler {
32

33
        private static final String CREATE_EVENT = "ProductOrderCreateEvent";
34
        private static final String DELETE_EVENT = "ProductOrderDeleteEvent";
35
        private static final String STATE_CHANGE_EVENT = "ProductOrderStateChangeEvent";
36

37
        private static final List<String> SUPPORTED_EVENT_TYPES = List.of(CREATE_EVENT, DELETE_EVENT, STATE_CHANGE_EVENT);
×
38

39
        private final ObjectMapper objectMapper;
40
        private final OrganizationResolver organizationResolver;
41
        private final TrustedIssuersListAdapter trustedIssuersListAdapter;
42
        private final RainbowAdapter rainbowAdapter;
43
        private final TMForumAdapter tmForumAdapter;
44

45
        private final TMFMapper tmfMapper;
46

47
        @Override
48
        public boolean isEventTypeSupported(String eventType) {
49
                return SUPPORTED_EVENT_TYPES.contains(eventType);
×
50
        }
51

52
        @Override
53
        public Mono<HttpResponse<?>> handleEvent(String eventType, Map<String, Object> event) {
54

55
                String orgId = Stream
×
56
                                .ofNullable(event)
×
57
                                .map(rawEvent -> objectMapper.convertValue(rawEvent, ProductOrderCreateEventVO.class))
×
58
                                .map(ProductOrderCreateEventVO::getEvent)
×
59
                                .map(ProductOrderCreateEventPayloadVO::getProductOrder)
×
60
                                .map(ProductOrderVO::getRelatedParty)
×
NEW
61
                                .filter(Objects::nonNull)
×
62
                                .map(rpl -> {
×
NEW
63
                                        if (rpl.size() != 1) {
×
64
                                                throw new IllegalArgumentException("Expected exactly one ordering organization.");
×
65
                                        }
66
                                        return rpl.get(0);
×
67
                                })
68
                                .map(RelatedPartyVO::getId)
×
69
                                .findAny()
×
70
                                .orElseThrow(() -> new IllegalArgumentException("The ProductOrder-Event does not include a valid organization id."));
×
71

72
                return switch (eventType) {
×
73
                        case CREATE_EVENT -> handelCreateEvent(orgId, event);
×
74
                        case STATE_CHANGE_EVENT -> handelStateChangeEvent(orgId, event);
×
75
                        case DELETE_EVENT -> handelDeleteEvent(orgId, event);
×
76
                        default -> throw new IllegalArgumentException("Invalid event type received.");
×
77
                };
78

79
        }
80

81
        private Mono<HttpResponse<?>> handelCreateEvent(String organizationId, Map<String, Object> event) {
82
                ProductOrderCreateEventVO productOrderCreateEventVO = objectMapper.convertValue(event, ProductOrderCreateEventVO.class);
×
83

84
                ProductOrderVO productOrderVO = Optional.ofNullable(productOrderCreateEventVO.getEvent())
×
85
                                .map(ProductOrderCreateEventPayloadVO::getProductOrder)
×
86
                                .orElseThrow(() -> new IllegalArgumentException("The event does not contain a product order."));
×
87

88
                boolean isCompleted = isCompleted(productOrderVO);
×
89
                if (!isCompleted) {
×
90
                        log.debug("The received event is not in state completed.");
×
91
                        return Mono.just(HttpResponse.noContent());
×
92
                }
93

94
                return Mono.zipDelayError(createAgreement(productOrderVO, organizationId), allowIssuer(organizationId))
×
95
                                .map(tuple -> HttpResponse.noContent());
×
96
        }
97

98
        private static boolean isCompleted(ProductOrderVO productOrderVO) {
99
                return Optional.ofNullable(productOrderVO.getState())
×
100
                                .filter(ProductOrderStateTypeVO.COMPLETED::equals)
×
101
                                .isPresent();
×
102
        }
103

104
        private Mono<HttpResponse<?>> handelStateChangeEvent(String organizationId, Map<String, Object> event) {
105
                ProductOrderStateChangeEventVO productOrderStateChangeEventVO = objectMapper.convertValue(event, ProductOrderStateChangeEventVO.class);
×
106
                ProductOrderVO productOrderVO = Optional.ofNullable(productOrderStateChangeEventVO.getEvent())
×
107
                                .map(ProductOrderStateChangeEventPayloadVO::getProductOrder)
×
108
                                .orElseThrow(() -> new IllegalArgumentException("The event does not contain a product order."));
×
109

110
                if (isCompleted(productOrderVO)) {
×
111
                        return Mono.zipDelayError(
×
112
                                                        createAgreement(productOrderVO, organizationId),
×
113
                                                        allowIssuer(organizationId))
×
114
                                        .map(tuple -> HttpResponse.noContent());
×
115
                } else {
116
                        return handleStopEvent(organizationId, event);
×
117
                }
118
        }
119

120
        private Mono<HttpResponse<?>> handleStopEvent(String organizationId, Map<String, Object> event) {
121
                ProductOrderStateChangeEventVO productOrderStateChangeEventVO = objectMapper.convertValue(event, ProductOrderStateChangeEventVO.class);
×
122
                ProductOrderVO productOrderVO = Optional.ofNullable(productOrderStateChangeEventVO.getEvent())
×
123
                                .map(ProductOrderStateChangeEventPayloadVO::getProductOrder)
×
124
                                .orElseThrow(() -> new IllegalArgumentException("The event does not contain a product order."));
×
125

126
                Mono<HttpResponse<?>> agreementsDeletion = deleteAgreement(productOrderVO);
×
127
                Mono<HttpResponse<?>> issuerDenial = denyIssuer(organizationId);
×
128

129
                return Mono.zipDelayError(List.of(agreementsDeletion, issuerDenial), responses -> Arrays.stream(responses)
×
130
                                .filter(HttpResponse.class::isInstance)
×
131
                                .map(HttpResponse.class::cast)
×
132
                                .filter(response -> response.status().getCode() > 299)
×
133
                                .findAny()
×
134
                                .orElse(HttpResponse.ok()));
×
135
        }
136

137
        private Mono<HttpResponse<?>> handelDeleteEvent(String organizationId, Map<String, Object> event) {
138
                ProductOrderDeleteEventVO productOrderDeleteEventVO = objectMapper.convertValue(event, ProductOrderDeleteEventVO.class);
×
139
                ProductOrderVO productOrderVO = Optional.ofNullable(productOrderDeleteEventVO.getEvent())
×
140
                                .map(ProductOrderDeleteEventPayloadVO::getProductOrder)
×
141
                                .orElseThrow(() -> new IllegalArgumentException("The event does not contain a product order."));
×
142

143
                Mono<HttpResponse<?>> agreementsDeletion = deleteAgreement(productOrderVO);
×
144
                Mono<HttpResponse<?>> issuerDenial = denyIssuer(organizationId);
×
145

146
                return Mono.zipDelayError(List.of(agreementsDeletion, issuerDenial), responses -> Arrays.stream(responses)
×
147
                                .filter(HttpResponse.class::isInstance)
×
148
                                .map(HttpResponse.class::cast)
×
149
                                .filter(response -> response.status().getCode() > 299)
×
150
                                .findAny()
×
151
                                .orElse(HttpResponse.ok()));
×
152
        }
153

154

155
        private Mono<?> createAgreement(ProductOrderVO productOrderVO, String organizationId) {
156

157
                List<RelatedPartyTmfVO> relatedPartyTmfVOS = productOrderVO
×
158
                                .getRelatedParty()
×
159
                                .stream()
×
160
                                .map(tmfMapper::map)
×
161
                                .toList();
×
162

163
                return Mono.zipDelayError(
×
164
                                                productOrderVO
165
                                                                .getProductOrderItem()
×
166
                                                                .stream()
×
167
                                                                .map(ProductOrderItemVO::getProductOffering)
×
168
                                                                .filter(Objects::nonNull)
×
169
                                                                .map(offering -> rainbowAdapter.createAgreement(organizationId, offering.getId()))
×
170
                                                                .toList(),
×
171
                                                res -> {
172
                                                        List<AgreementVO> agreementVOS = Arrays.stream(res).filter(Objects::nonNull).filter(AgreementVO.class::isInstance).map(AgreementVO.class::cast).toList();
×
173
                                                        return updateProductOrder(productOrderVO, agreementVOS, relatedPartyTmfVOS);
×
174
                                                })
175
                                .flatMap(Function.identity());
×
176
        }
177

178
        private Mono<ProductOrderVO> updateProductOrder(ProductOrderVO productOrderVO, List<AgreementVO> agreementVOS, List<RelatedPartyTmfVO> relatedPartyTmfVOS) {
179
                return Mono.zipDelayError(
×
180
                                agreementVOS.stream()
×
181
                                                .map(agreementVO ->
×
182
                                                                tmForumAdapter.createAgreement(productOrderVO.getId(), agreementVO.getDataServiceId(), agreementVO.getAgreementId(), relatedPartyTmfVOS))
×
183
                                                .toList(),
×
184
                                agreements -> {
185
                                        List<String> agreementIds = Arrays.stream(agreements)
×
186
                                                        .filter(String.class::isInstance)
×
187
                                                        .map(String.class::cast)
×
188
                                                        .toList();
×
189
                                        return tmForumAdapter.addAgreementToOrder(productOrderVO.getId(), agreementIds);
×
190
                                }).flatMap(Function.identity());
×
191

192
        }
193

194
        private Mono<HttpResponse<?>> allowIssuer(String organizationId) {
195
                return organizationResolver.getDID(organizationId)
×
196
                                .flatMap(trustedIssuersListAdapter::allowIssuer)
×
197
                                .map(issuer -> HttpResponseFactory.INSTANCE.status(HttpStatus.CREATED));
×
198
        }
199

200
        private Mono<HttpResponse<?>> deleteAgreement(ProductOrderVO productOrderVO) {
201
                List<Mono<Boolean>> deletionMonos = productOrderVO.getAgreement()
×
202
                                .stream()
×
203
                                .map(AgreementRefVO::getId)
×
204
                                .map(rainbowAdapter::deleteAgreement)
×
205
                                .toList();
×
206
                return Mono.zipDelayError(deletionMonos, deletions -> {
×
207
                        if (Set.of(deletions).contains(false)) {
×
208
                                log.warn("Was not able to delete the agreement for order {}.", productOrderVO);
×
209
                                HttpResponse.status(HttpStatus.BAD_GATEWAY);
×
210
                        }
211
                        return HttpResponse.status(HttpStatus.ACCEPTED);
×
212
                });
213
        }
214

215
        private Mono<HttpResponse<?>> denyIssuer(String organizationId) {
216
                return organizationResolver.getDID(organizationId)
×
217
                                .flatMap(trustedIssuersListAdapter::denyIssuer);
×
218
        }
219
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc