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

FIWARE / contract-management / #26

28 Jan 2025 10:59AM UTC coverage: 0.982% (-0.6%) from 1.629%
#26

push

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

Tpp integration

99 of 500 new or added lines in 14 files covered. (19.8%)

4 existing lines in 3 files now uncovered.

281 of 28625 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
NEW
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

NEW
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) {
NEW
49
                return SUPPORTED_EVENT_TYPES.contains(eventType);
×
50
        }
51

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

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

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

78
        }
79

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

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

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

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

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

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

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

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

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

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

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

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

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

153

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

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

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

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

191
        }
192

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

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

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

© 2026 Coveralls, Inc