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

FIWARE / contract-management / #31

04 Apr 2025 09:14AM UTC coverage: 1.9% (+0.9%) from 0.982%
#31

Pull #5

wistefan
add json schemas to extend offerings and quotes
Pull Request #5: integrate contract negotiation

29 of 247 new or added lines in 9 files covered. (11.74%)

5 existing lines in 2 files now uncovered.

644 of 33897 relevant lines covered (1.9%)

0.02 hits per line

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

36.25
/src/main/java/org/fiware/iam/tmforum/TMForumAdapter.java
1
package org.fiware.iam.tmforum;
2

3
import com.fasterxml.jackson.databind.ObjectMapper;
4
import io.micronaut.http.HttpResponse;
5
import jakarta.inject.Singleton;
6
import lombok.RequiredArgsConstructor;
7
import lombok.extern.slf4j.Slf4j;
8
import org.fiware.iam.dsp.OfferingParameters;
9
import org.fiware.iam.exception.TMForumException;
10
import org.fiware.iam.tmforum.agreement.api.AgreementApiClient;
11
import org.fiware.iam.tmforum.agreement.model.*;
12
import org.fiware.iam.tmforum.handlers.ProductOfferingEventHandler;
13
import org.fiware.iam.tmforum.productcatalog.api.ProductOfferingApiClient;
14
import org.fiware.iam.tmforum.productcatalog.api.ProductSpecificationApiClient;
15
import org.fiware.iam.tmforum.productcatalog.model.*;
16
import org.fiware.iam.tmforum.productorder.api.ProductOrderApiClient;
17
import org.fiware.iam.tmforum.productorder.model.AgreementRefVO;
18
import org.fiware.iam.tmforum.productorder.model.ProductOrderUpdateVO;
19
import org.fiware.iam.tmforum.productorder.model.ProductOrderVO;
20
import org.fiware.iam.tmforum.quote.api.QuoteApiClient;
21
import org.fiware.iam.tmforum.quote.model.QuoteItemVO;
22
import org.fiware.iam.tmforum.quote.model.QuoteUpdateVO;
23
import org.fiware.iam.tmforum.quote.model.QuoteVO;
24
import reactor.core.publisher.Mono;
25

26
import java.util.List;
27
import java.util.stream.Collectors;
28

29
/**
30
 * Adapter to handle communication with TMForum APIs.
31
 */
32
@Singleton
33
@RequiredArgsConstructor
34
@Slf4j
1✔
35
public class TMForumAdapter {
36

37
        public static final String DATA_SPACE_PROTOCOL_AGREEMENT_ID = "Data-Space-Protocol-Agreement-Id";
38
        public static final String CONSUMER_ROLE = "Consumer";
39

40
        private final ObjectMapper objectMapper;
41

42
        private final OrganizationResolver organizationResolver;
43
        private final ProductOrderApiClient productOrderApiClient;
44
        private final ProductOfferingApiClient productOfferingApiClient;
45
        private final ProductSpecificationApiClient productSpecificationApiClient;
46
        private final AgreementApiClient agreementApiClient;
47
        private final QuoteApiClient quoteApiClient;
48

49
        /**
50
         * Create a TMForum Agreement and connect it with product order its coming from.
51
         */
52
        public Mono<String> createAgreement(String productOrderId, String productOfferingId, String agreementId, List<RelatedPartyTmfVO> relatedParties) {
53
                AgreementItemTmfVO agreementItemTmfVO = new AgreementItemTmfVO()
1✔
54
                                .addProductItem(
1✔
55
                                                new ProductRefTmfVO()
56
                                                                .id(productOrderId))
1✔
57
                                .addProductOfferingItem(
1✔
58
                                                new ProductOfferingRefTmfVO()
59
                                                                .id(productOfferingId));
1✔
60
                CharacteristicTmfVO characteristicTmfVO = new CharacteristicTmfVO()
1✔
61
                                .name(DATA_SPACE_PROTOCOL_AGREEMENT_ID)
1✔
62
                                .value(agreementId);
1✔
63
                AgreementCreateTmfVO agreementCreateTmfVO = new AgreementCreateTmfVO()
1✔
64
                                .characteristic(List.of(characteristicTmfVO))
1✔
65
                                .engagedParty(relatedParties)
1✔
66
                                // prevent empty refs
67
                                .agreementSpecification(null)
1✔
68
                                .addAgreementItemItem(agreementItemTmfVO);
1✔
69

70
                return agreementApiClient
1✔
71
                                .createAgreement(agreementCreateTmfVO)
1✔
72
                                .map(HttpResponse::body)
1✔
73
                                .map(AgreementTmfVO::getId)
1✔
74
                                .onErrorMap(t -> {
1✔
75
                                        throw new TMForumException("Was not able to create agreement", t);
1✔
76
                                });
77
        }
78

79

80
        /**
81
         * Add the id of agreements(from rainbow) to the given product order
82
         */
83
        public Mono<ProductOrderVO> addAgreementToOrder(String productOrderId, List<String> agreementIds) {
84
                List<AgreementRefVO> agreementRefVOS = agreementIds.stream()
1✔
85
                                .map(id -> new AgreementRefVO().id(id))
1✔
86
                                .toList();
1✔
87
                ProductOrderUpdateVO productOrderUpdateVO = new ProductOrderUpdateVO().agreement(agreementRefVOS);
1✔
88
                return productOrderApiClient
1✔
89
                                .patchProductOrder(productOrderId, productOrderUpdateVO)
1✔
90
                                .map(HttpResponse::body)
1✔
91
                                .onErrorMap(t -> {
1✔
92
                                        throw new TMForumException("Was not able to update the product order");
1✔
93
                                });
94
        }
95

96
        /**
97
         * Update the externalId of a quote.
98
         */
99
        public Mono<QuoteVO> updateExternalId(QuoteVO quoteVO, String externalId) {
NEW
100
                QuoteUpdateVO quoteUpdateVO = objectMapper.convertValue(quoteVO.externalId(externalId), QuoteUpdateVO.class);
×
NEW
101
                return quoteApiClient.patchQuote(quoteVO.getId(), quoteUpdateVO)
×
NEW
102
                                .onErrorMap(t -> new TMForumException(String.format("Was not able to update the quote %s.", quoteVO.getId()), t))
×
NEW
103
                                .map(HttpResponse::body);
×
104

105

106
        }
107

108
        /**
109
         * Return the quote with the given id.
110
         */
111
        public Mono<QuoteVO> getQuoteById(String id) {
NEW
112
                return quoteApiClient.retrieveQuote(id, null)
×
NEW
113
                                .onErrorMap(t -> {
×
NEW
114
                                        throw new TMForumException(String.format("Was not able to get the quote %s.", id), t);
×
115
                                })
NEW
116
                                .map(HttpResponse::body);
×
117
        }
118

119
        public Mono<ProductSpecificationVO> getSpecFromOfferRef(String refId) {
NEW
120
                return productOfferingApiClient.retrieveProductOffering(refId, null)
×
NEW
121
                                .onErrorMap(t -> new TMForumException(String.format("Was not able to retrieve offering %s", refId), t))
×
NEW
122
                                .map(HttpResponse::body)
×
NEW
123
                                .map(ProductOfferingVO::getProductSpecification)
×
NEW
124
                                .map(ProductSpecificationRefVO::getId)
×
NEW
125
                                .flatMap(id -> productSpecificationApiClient.retrieveProductSpecification(id, null))
×
NEW
126
                                .onErrorMap(t -> new TMForumException(String.format("Was not able to retrieve specification for offering %s", refId), t))
×
NEW
127
                                .map(HttpResponse::body);
×
128
        }
129

130

131
        public Mono<String> getConsumerDid(QuoteVO quoteVO) {
NEW
132
                return organizationResolver.getDID(getConsumerIdFromQuote(quoteVO));
×
133
        }
134

135

136
        public String getConsumerIdFromQuote(QuoteVO quoteVO) {
NEW
137
                if (quoteVO.getRelatedParty() == null || quoteVO.getRelatedParty().isEmpty()) {
×
NEW
138
                        throw new TMForumException(String.format("Quote %s does not have valid consumer.", quoteVO.getId()));
×
139
                }
NEW
140
                return quoteVO.getRelatedParty()
×
NEW
141
                                .stream()
×
NEW
142
                                .filter(rp -> rp.getRole().equals(CONSUMER_ROLE))
×
NEW
143
                                .findFirst()
×
NEW
144
                                .map(org.fiware.iam.tmforum.quote.model.RelatedPartyVO::getId)
×
NEW
145
                                .orElseThrow(() -> new TMForumException(String.format("Quote %s does not have valid consumer.", quoteVO.getId())));
×
146
        }
147

148
        public Mono<OfferingParameters> getOfferingParameters(String offeringId) {
NEW
149
                return getSpecFromOfferRef(offeringId)
×
NEW
150
                                .map(spec -> fromProductSpecChars(spec.getProductSpecCharacteristic()));
×
151
        }
152

153
        private OfferingParameters fromProductSpecChars(List<ProductSpecificationCharacteristicVO> specChars) {
NEW
154
                String target = "";
×
NEW
155
                String action = "";
×
156

NEW
157
                for (ProductSpecificationCharacteristicVO specChar : specChars) {
×
NEW
158
                        if (specChar.getValueType().equals(ProductOfferingConstants.ENDPOINT_URL_TYPE)) {
×
NEW
159
                                target = specChar.getProductSpecCharacteristicValue()
×
NEW
160
                                                .stream()
×
NEW
161
                                                .filter(CharacteristicValueSpecificationVO::getIsDefault)
×
NEW
162
                                                .map(CharacteristicValueSpecificationVO::getValue)
×
NEW
163
                                                .map(String.class::cast)
×
NEW
164
                                                .findAny()
×
NEW
165
                                                .orElseThrow(() -> new TMForumException("Was not able to retrieve endpoint from spec."));
×
NEW
166
                                continue;
×
167
                        }
NEW
168
                        if (specChar.getValueType().equals(ProductOfferingConstants.ALLOWED_ACTION_TYPE)) {
×
NEW
169
                                action = specChar.getProductSpecCharacteristicValue()
×
NEW
170
                                                .stream()
×
NEW
171
                                                .filter(CharacteristicValueSpecificationVO::getIsDefault)
×
NEW
172
                                                .map(CharacteristicValueSpecificationVO::getValue)
×
NEW
173
                                                .map(String.class::cast)
×
NEW
174
                                                .findAny()
×
NEW
175
                                                .orElseThrow(() -> new TMForumException("Was not able to retrieve action from spec."));
×
176
                        }
NEW
177
                }
×
NEW
178
                if (action.isEmpty() || target.isEmpty()) {
×
NEW
179
                        throw new TMForumException(String.format("Was not able to get valid action %s and/or target %s.", action, target));
×
180
                }
NEW
181
                return new OfferingParameters(target, action);
×
182
        }
183

184

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