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

FIWARE / contract-management / #67

27 Oct 2025 12:33PM UTC coverage: 1.686% (+0.04%) from 1.651%
#67

Pull #12

wistefan
wait for the policy
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/dsp/RainbowQuoteHandler.java
1
package org.fiware.iam.dsp;
2

3
import com.fasterxml.jackson.databind.ObjectMapper;
4
import io.micronaut.context.annotation.Requires;
5
import io.micronaut.http.HttpResponse;
6
import jakarta.inject.Singleton;
7
import lombok.RequiredArgsConstructor;
8
import lombok.extern.slf4j.Slf4j;
9
import org.fiware.iam.configuration.GeneralProperties;
10
import org.fiware.iam.handlers.QuoteHandler;
11
import org.fiware.iam.exception.RainbowException;
12
import org.fiware.iam.tmforum.TMForumAdapter;
13
import org.fiware.iam.tmforum.quote.model.QuoteItemVO;
14
import org.fiware.iam.tmforum.quote.model.QuoteStateTypeVO;
15
import org.fiware.iam.tmforum.quote.model.QuoteVO;
16
import org.fiware.rainbow.model.NegotiationRequestVO;
17
import org.fiware.rainbow.model.ObligationVO;
18
import org.fiware.rainbow.model.OfferVO;
19
import org.fiware.rainbow.model.PermissionVO;
20
import reactor.core.publisher.Mono;
21

22
import java.util.*;
23
import java.util.stream.Stream;
24

25
import static org.fiware.iam.dsp.PriceMapper.PAYMENT_ACTION;
26
import static org.fiware.iam.tmforum.TMForumAdapter.CONSUMER_ROLE;
27

28
@Requires(condition = GeneralProperties.RainbowCondition.class)
29
@RequiredArgsConstructor
30
@Singleton
NEW
31
@Slf4j
×
32
public class RainbowQuoteHandler implements QuoteHandler {
33

34

35
    private static final String URN_UUID_TEMPLATE = "urn:uuid:%s";
36

37
    private final ObjectMapper objectMapper;
38
    private final TMForumAdapter tmForumAdapter;
39
    private final RainbowAdapter rainbowAdapter;
40
    private final PriceMapper priceMapper;
41
    private final GeneralProperties generalProperties;
42

43
    @Override
44
    public Mono<HttpResponse<?>> handleQuoteCreation(QuoteVO quoteVO) {
NEW
45
        List<PermissionVO> permissionVOS = new ArrayList<>(getPermissionsFromQuote(objectMapper, quoteVO));
×
46

NEW
47
        return tmForumAdapter.getConsumerDid(quoteVO)
×
NEW
48
                .flatMap(id -> rainbowAdapter.createParticipant(id, CONSUMER_ROLE))
×
NEW
49
                .onErrorMap(t -> new RainbowException("Was not able to create consumer.", t))
×
NEW
50
                .flatMap(r -> getObligationFromQuote(quoteVO))
×
NEW
51
                .flatMap(obligation -> {
×
NEW
52
                    String offerId = getOfferIdFromQuote(quoteVO);
×
NEW
53
                    return tmForumAdapter.getOfferingParameters(offerId)
×
NEW
54
                            .map(offeringParams -> {
×
NEW
55
                                permissionVOS.add(new PermissionVO()
×
NEW
56
                                        .odrlColonAction(offeringParams.action()));
×
NEW
57
                                OfferVO offerVO = new OfferVO()
×
NEW
58
                                        .atId(offerId)
×
NEW
59
                                        .odrlColonTarget(offeringParams.target())
×
NEW
60
                                        .odrlColonPermission(permissionVOS);
×
NEW
61
                                if (obligation.getOdrlColonConstraint() != null && !obligation.getOdrlColonConstraint().isEmpty()) {
×
NEW
62
                                    offerVO.odrlColonObligation(List.of(obligation));
×
63
                                }
NEW
64
                                return new NegotiationRequestVO()
×
NEW
65
                                        .dspaceColonCallbackAddress("")
×
NEW
66
                                        .dspaceColonConsumerPid(String.format(URN_UUID_TEMPLATE, UUID.randomUUID()))
×
NEW
67
                                        .dspaceColonOffer(offerVO);
×
68
                            });
69
                })
NEW
70
                .onErrorMap(t -> {
×
NEW
71
                    throw new RainbowException("Was not able to get the offering parameters.", t);
×
72
                })
NEW
73
                .flatMap(negotiationRequestVO ->
×
NEW
74
                        rainbowAdapter
×
NEW
75
                                .createNegotiationRequest(negotiationRequestVO)
×
NEW
76
                                .flatMap(id -> tmForumAdapter.updateExternalId(quoteVO, id))
×
NEW
77
                                .map(t -> HttpResponse.noContent()));
×
78
    }
79

80
    @Override
81
    public Mono<HttpResponse<?>> handleQuoteStateChange(QuoteVO quoteVO) {
NEW
82
        QuoteStateTypeVO quoteStateTypeVO = quoteVO.getState();
×
NEW
83
        log.debug("Quote state is {}", quoteStateTypeVO);
×
NEW
84
        return switch (quoteStateTypeVO) {
×
85
            case APPROVED ->
NEW
86
                    rainbowAdapter.updateNegotiationProcessByProviderId(quoteVO.getExternalId(), "dspace:OFFERED")
×
NEW
87
                            .map(t -> HttpResponse.noContent());
×
NEW
88
            case ACCEPTED -> tmForumAdapter.getConsumerDid(quoteVO)
×
NEW
89
                    .flatMap(consumerDid ->
×
NEW
90
                            rainbowAdapter
×
NEW
91
                                    .createAgreementAfterNegotiation(quoteVO.getExternalId(), consumerDid, generalProperties.getDid())
×
NEW
92
                                    .flatMap(r -> rainbowAdapter.updateNegotiationProcessByProviderId(quoteVO.getExternalId(), "dspace:AGREED")
×
NEW
93
                                            .map(t -> HttpResponse.noContent())));
×
94
            // a lot of requests can just be ignored
NEW
95
            default -> Mono.just(HttpResponse.noContent());
×
96
        };
97
    }
98

99
    @Override
100
    public Mono<HttpResponse<?>> handleQuoteDeletion(QuoteVO quoteVO) {
NEW
101
        if (quoteVO.getExternalId() == null && !quoteVO.getExternalId().isEmpty()) {
×
NEW
102
            return rainbowAdapter.updateNegotiationProcessByProviderId(quoteVO.getExternalId(), "dspace:TERMINATED")
×
NEW
103
                    .map(t -> HttpResponse.noContent());
×
104
        }
105

NEW
106
        return Mono.just(HttpResponse.noContent());
×
107
    }
108

109
    private String getOfferIdFromQuote(QuoteVO quoteVO) {
NEW
110
        return getRelevantQuoteItems(quoteVO)
×
NEW
111
                .map(QuoteItemVO::getProductOffering)
×
NEW
112
                .map(org.fiware.iam.tmforum.quote.model.ProductOfferingRefVO::getId)
×
NEW
113
                .findFirst()
×
NEW
114
                .orElseThrow(() -> new IllegalArgumentException("The event does not reference an offer."));
×
115
    }
116

117
    private Stream<QuoteItemVO> getRelevantQuoteItems(QuoteVO quoteVO) {
NEW
118
        return quoteVO
×
NEW
119
                .getQuoteItem()
×
NEW
120
                .stream()
×
NEW
121
                .filter(qi -> !qi.getState().equals("rejected"));
×
122
    }
123

124
    private List<Policy> getPoliciesFromQuote(ObjectMapper objectMapper, QuoteVO quoteVO) {
NEW
125
        return getRelevantQuoteItems(quoteVO)
×
NEW
126
                .map(QuoteItemVO::getUnknownProperties)
×
NEW
127
                .map(Map::entrySet)
×
NEW
128
                .flatMap(Set::stream)
×
NEW
129
                .filter(ap -> ap.getKey().equals("policy"))
×
NEW
130
                .map(Map.Entry::getValue)
×
NEW
131
                .filter(List.class::isInstance)
×
NEW
132
                .map(List.class::cast)
×
NEW
133
                .flatMap(List::stream)
×
NEW
134
                .map(v -> objectMapper.convertValue(v, Policy.class))
×
NEW
135
                .toList();
×
136
    }
137

138
    private List<PermissionVO> getPermissionsFromQuote(ObjectMapper objectMapper, QuoteVO quoteVO) {
NEW
139
        return getPoliciesFromQuote(objectMapper, quoteVO)
×
NEW
140
                .stream()
×
NEW
141
                .map(o -> objectMapper.convertValue(o, Policy.class))
×
NEW
142
                .map(Policy::getPermission)
×
NEW
143
                .flatMap(List::stream)
×
NEW
144
                .toList();
×
145
    }
146

147

148
    private Mono<ObligationVO> getObligationFromQuote(QuoteVO quoteVO) {
NEW
149
        ObligationVO obligationVO = new ObligationVO();
×
NEW
150
        obligationVO.odrlColonAction(PAYMENT_ACTION);
×
151

NEW
152
        return Mono.zip(
×
NEW
153
                getRelevantQuoteItems(quoteVO)
×
NEW
154
                        .map(QuoteItemVO::getQuoteItemPrice)
×
NEW
155
                        .flatMap(List::stream)
×
NEW
156
                        .map(priceMapper::toObligationConstraints)
×
NEW
157
                        .toList(),
×
NEW
158
                cons -> obligationVO.odrlColonConstraint(
×
NEW
159
                        Arrays.asList(cons)
×
NEW
160
                                .stream()
×
NEW
161
                                .filter(List.class::isInstance)
×
NEW
162
                                .map(List.class::cast)
×
NEW
163
                                .flatMap(List::stream)
×
NEW
164
                                .toList()));
×
165
    }
166
}
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