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

FIWARE / contract-management / #69

30 Oct 2025 07:38AM UTC coverage: 1.686% (+0.04%) from 1.651%
#69

Pull #12

wistefan
improve organization creation and cleanup
Pull Request #12: Support for central marketplace and policy creation

117 of 1238 new or added lines in 31 files covered. (9.45%)

5 existing lines in 2 files now uncovered.

587 of 34807 relevant lines covered (1.69%)

0.02 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.context.annotation.Requires;
5
import io.micronaut.http.HttpResponse;
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.configuration.GeneralProperties;
11
import org.fiware.iam.handlers.ProductOrderHandler;
12
import org.fiware.iam.tmforum.productorder.model.*;
13
import reactor.core.publisher.Mono;
14

15
import java.util.*;
16
import java.util.stream.Stream;
17

18

19
/**
20
 * Handle all incoming events in connection to ProductOrder
21
 */
22
@Requires(condition = GeneralProperties.TmForumCondition.class)
23
@RequiredArgsConstructor
24
@Singleton
25
@Slf4j
×
26
public class ProductOrderEventHandler implements TMForumEventHandler {
27

28
    private static final String CREATE_EVENT = "ProductOrderCreateEvent";
29
    private static final String DELETE_EVENT = "ProductOrderDeleteEvent";
30
    private static final String STATE_CHANGE_EVENT = "ProductOrderStateChangeEvent";
NEW
31
    private static final List<String> SUPPORTED_EVENT_TYPES = List.of(CREATE_EVENT, DELETE_EVENT, STATE_CHANGE_EVENT);
×
32

33

34
    private static final String CUSTOMER_ROLE = "Customer";
35

36
    private final ObjectMapper objectMapper;
37

38
    private final List<ProductOrderHandler> productOrderHandlers;
39

40

41
    @Override
42
    public boolean isEventTypeSupported(String eventType) {
NEW
43
        return SUPPORTED_EVENT_TYPES.contains(eventType);
×
44
    }
45

46
    @Override
47
    public Mono<HttpResponse<?>> handleEvent(String eventType, Map<String, Object> event) {
48

NEW
49
        String orgId = Stream
×
NEW
50
                .ofNullable(event)
×
NEW
51
                .map(rawEvent -> objectMapper.convertValue(rawEvent, ProductOrderCreateEventVO.class))
×
NEW
52
                .map(ProductOrderCreateEventVO::getEvent)
×
NEW
53
                .map(ProductOrderCreateEventPayloadVO::getProductOrder)
×
NEW
54
                .map(ProductOrderVO::getRelatedParty)
×
NEW
55
                .filter(Objects::nonNull)
×
NEW
56
                .map(rpl -> getCustomer(rpl).orElseThrow(() -> new IllegalArgumentException("Exactly one ordering related party is expected.")))
×
NEW
57
                .map(RelatedPartyVO::getId)
×
NEW
58
                .findAny()
×
NEW
59
                .orElseThrow(() -> new IllegalArgumentException("The ProductOrder-Event does not include a valid organization id."));
×
60

NEW
61
        return switch (eventType) {
×
NEW
62
            case CREATE_EVENT -> handelCreateEvent(orgId, event);
×
NEW
63
            case STATE_CHANGE_EVENT -> handelStateChangeEvent(orgId, event);
×
NEW
64
            case DELETE_EVENT -> handelDeleteEvent(orgId, event);
×
NEW
65
            default -> throw new IllegalArgumentException("Invalid event type received.");
×
66
        };
67

68
    }
69

70
    private Optional<RelatedPartyVO> getCustomer(List<RelatedPartyVO> relatedPartyVOS) {
NEW
71
        if (relatedPartyVOS == null || relatedPartyVOS.isEmpty()) {
×
NEW
72
            return Optional.empty();
×
73
        }
NEW
74
        if (relatedPartyVOS.size() == 1) {
×
NEW
75
            String role = relatedPartyVOS.getFirst().getRole();
×
NEW
76
            if (role == null || role.equals(CUSTOMER_ROLE)) {
×
NEW
77
                return Optional.of(relatedPartyVOS.getFirst());
×
78
            }
79
        }
NEW
80
        return relatedPartyVOS.stream()
×
NEW
81
                .filter(relatedPartyVO -> relatedPartyVO.getRole() != null)
×
NEW
82
                .filter(relatedPartyVO -> relatedPartyVO.getRole().equals(CUSTOMER_ROLE))
×
NEW
83
                .findFirst();
×
84
    }
85

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

NEW
89
        ProductOrderVO productOrderVO = Optional.ofNullable(productOrderCreateEventVO.getEvent())
×
NEW
90
                .map(ProductOrderCreateEventPayloadVO::getProductOrder)
×
NEW
91
                .orElseThrow(() -> new IllegalArgumentException("The event does not contain a product order."));
×
92

NEW
93
        if (isNotRejected(productOrderVO) && containsQuote(productOrderVO)) {
×
NEW
94
            List<Mono<HttpResponse<?>>> responses = productOrderHandlers.stream()
×
NEW
95
                    .map(handler -> handler.handleProductOrderNegotiation(organizationId, productOrderVO))
×
NEW
96
                    .toList();
×
97

NEW
98
            return zipToResponse(responses);
×
99
        }
100

NEW
101
        boolean isCompleted = isCompleted(productOrderVO);
×
NEW
102
        if (!isCompleted) {
×
NEW
103
            log.debug("The received event is not in state completed.");
×
NEW
104
            return Mono.just(HttpResponse.noContent());
×
105
        }
106

NEW
107
        List<Mono<HttpResponse<?>>> responses = productOrderHandlers.stream()
×
NEW
108
                .map(handler -> handler.handleProductOrderComplete(organizationId, productOrderVO))
×
NEW
109
                .toList();
×
110

NEW
111
        return zipToResponse(responses);
×
112
    }
113

114
    private static boolean isCompleted(ProductOrderVO productOrderVO) {
NEW
115
        return Optional.ofNullable(productOrderVO.getState())
×
NEW
116
                .filter(ProductOrderStateTypeVO.COMPLETED::equals)
×
NEW
117
                .isPresent();
×
118
    }
119

120
    private static boolean isNotRejected(ProductOrderVO productOrderVO) {
NEW
121
        return Optional.ofNullable(productOrderVO.getState())
×
NEW
122
                .filter(state -> state == ProductOrderStateTypeVO.REJECTED)
×
NEW
123
                .isEmpty();
×
124
    }
125

126
    private Mono<HttpResponse<?>> handelStateChangeEvent(String organizationId, Map<String, Object> event) {
NEW
127
        ProductOrderStateChangeEventVO productOrderStateChangeEventVO = objectMapper.convertValue(event, ProductOrderStateChangeEventVO.class);
×
NEW
128
        ProductOrderVO productOrderVO = Optional.ofNullable(productOrderStateChangeEventVO.getEvent())
×
NEW
129
                .map(ProductOrderStateChangeEventPayloadVO::getProductOrder)
×
NEW
130
                .orElseThrow(() -> new IllegalArgumentException("The event does not contain a product order."));
×
131

NEW
132
        if (isCompleted(productOrderVO)) {
×
NEW
133
            log.debug("Product order is completed.");
×
134

NEW
135
            List<Mono<HttpResponse<?>>> responses = productOrderHandlers.stream()
×
NEW
136
                    .map(handler -> handler.handleProductOrderComplete(organizationId, productOrderVO)
×
NEW
137
                            .doOnNext(r -> log.debug("Handler {} responded {}", handler.getClass().getName(), r)))
×
NEW
138
                    .toList();
×
139

NEW
140
            return zipToResponse(responses);
×
141
        } else {
NEW
142
            return handleStopEvent(organizationId, event);
×
143
        }
144
    }
145

146

147
    private Mono<HttpResponse<?>> handleStopEvent(String organizationId, Map<String, Object> event) {
NEW
148
        ProductOrderStateChangeEventVO productOrderStateChangeEventVO = objectMapper.convertValue(event, ProductOrderStateChangeEventVO.class);
×
NEW
149
        ProductOrderVO productOrderVO = Optional.ofNullable(productOrderStateChangeEventVO.getEvent())
×
NEW
150
                .map(ProductOrderStateChangeEventPayloadVO::getProductOrder)
×
NEW
151
                .orElseThrow(() -> new IllegalArgumentException("The event does not contain a product order."));
×
152

153

NEW
154
        List<Mono<HttpResponse<?>>> responses = productOrderHandlers.stream()
×
NEW
155
                .map(handler -> handler.handleProductOrderStop(organizationId, productOrderVO))
×
NEW
156
                .toList();
×
157

NEW
158
        return zipToResponse(responses);
×
159
    }
160

161
    private Mono<HttpResponse<?>> handelDeleteEvent(String organizationId, Map<String, Object> event) {
NEW
162
        ProductOrderDeleteEventVO productOrderDeleteEventVO = objectMapper.convertValue(event, ProductOrderDeleteEventVO.class);
×
NEW
163
        ProductOrderVO productOrderVO = Optional.ofNullable(productOrderDeleteEventVO.getEvent())
×
NEW
164
                .map(ProductOrderDeleteEventPayloadVO::getProductOrder)
×
NEW
165
                .orElseThrow(() -> new IllegalArgumentException("The event does not contain a product order."));
×
166

NEW
167
        List<Mono<HttpResponse<?>>> responses = productOrderHandlers.stream()
×
NEW
168
                .map(handler -> handler.handleProductOrderStop(organizationId, productOrderVO))
×
NEW
169
                .toList();
×
170

NEW
171
        return zipToResponse(responses);
×
172
    }
173

174

175
    private boolean containsQuote(ProductOrderVO productOrderVO) {
NEW
176
        return productOrderVO.getQuote() != null && !productOrderVO.getQuote().isEmpty();
×
177
    }
178

179

180
}
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