Skip to content

Commit a93ccb1

Browse files
committed
refactor: introduce mapstruct usage in portal rest api on subscriptions mapping
1 parent fc80f61 commit a93ccb1

File tree

14 files changed

+138
-88
lines changed

14 files changed

+138
-88
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright © 2015 The Gravitee team (http://gravitee.io)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.gravitee.rest.api.portal.rest.mapper;
17+
18+
import java.time.Instant;
19+
import java.time.OffsetDateTime;
20+
import java.time.ZoneOffset;
21+
import java.util.Date;
22+
import java.util.Objects;
23+
import org.mapstruct.Mapper;
24+
import org.mapstruct.Named;
25+
import org.mapstruct.factory.Mappers;
26+
27+
@Mapper
28+
public interface DateMapper {
29+
DateMapper INSTANCE = Mappers.getMapper(DateMapper.class);
30+
31+
default OffsetDateTime map(Date value) {
32+
return Objects.isNull(value) ? null : value.toInstant().atOffset(ZoneOffset.UTC);
33+
}
34+
35+
default Date map(OffsetDateTime offsetDateTime) {
36+
return Objects.isNull(offsetDateTime) ? null : Date.from(offsetDateTime.toInstant());
37+
}
38+
39+
default OffsetDateTime map(Instant value) {
40+
return Objects.isNull(value) ? null : value.atOffset(ZoneOffset.UTC);
41+
}
42+
43+
default Instant mapToInstant(OffsetDateTime value) {
44+
return Objects.isNull(value) ? null : value.toInstant();
45+
}
46+
47+
@Named("mapTimestamp")
48+
default OffsetDateTime mapTimestamp(String timestamp) {
49+
return OffsetDateTime.parse(timestamp);
50+
}
51+
}

gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/main/java/io/gravitee/rest/api/portal/rest/mapper/SubscriptionMapper.java

+16-35
Original file line numberDiff line numberDiff line change
@@ -18,50 +18,31 @@
1818
import io.gravitee.rest.api.model.SubscriptionEntity;
1919
import io.gravitee.rest.api.model.SubscriptionStatus;
2020
import io.gravitee.rest.api.portal.rest.model.Subscription;
21-
import java.time.OffsetDateTime;
22-
import java.time.ZoneOffset;
23-
import java.util.Date;
24-
import lombok.extern.slf4j.Slf4j;
25-
import org.springframework.stereotype.Component;
21+
import org.mapstruct.Mapper;
22+
import org.mapstruct.Mapping;
23+
import org.mapstruct.factory.Mappers;
24+
import org.slf4j.Logger;
25+
import org.slf4j.LoggerFactory;
2626

2727
/**
2828
* @author Florent CHAMFROY (florent.chamfroy at graviteesource.com)
2929
* @author GraviteeSource Team
3030
*/
31+
@Mapper(uses = { DateMapper.class })
32+
public interface SubscriptionMapper {
33+
Logger log = LoggerFactory.getLogger(SubscriptionMapper.class);
34+
SubscriptionMapper INSTANCE = Mappers.getMapper(SubscriptionMapper.class);
3135

32-
@Slf4j
33-
@Component
34-
public class SubscriptionMapper {
36+
@Mapping(target = "keys", ignore = true)
37+
@Mapping(target = "endAt", source = "endingAt")
38+
@Mapping(target = "startAt", source = "startingAt")
39+
Subscription map(SubscriptionEntity subscriptionEntity);
3540

36-
public Subscription convert(SubscriptionEntity subscriptionEntity) {
37-
final Subscription subscriptionItem = new Subscription();
38-
subscriptionItem.setId(subscriptionEntity.getId());
39-
subscriptionItem.setApi(subscriptionEntity.getApi());
40-
subscriptionItem.setApplication(subscriptionEntity.getApplication());
41-
subscriptionItem.setCreatedAt(getDate(subscriptionEntity.getCreatedAt()));
42-
subscriptionItem.setEndAt(getDate(subscriptionEntity.getEndingAt()));
43-
subscriptionItem.setProcessedAt(getDate(subscriptionEntity.getProcessedAt()));
44-
subscriptionItem.setStartAt(getDate(subscriptionEntity.getStartingAt()));
45-
subscriptionItem.setPausedAt(getDate(subscriptionEntity.getPausedAt()));
46-
subscriptionItem.setClosedAt(getDate(subscriptionEntity.getClosedAt()));
47-
subscriptionItem.setPausedAt(getDate(subscriptionEntity.getPausedAt()));
48-
subscriptionItem.setPlan(subscriptionEntity.getPlan());
49-
subscriptionItem.setRequest(subscriptionEntity.getRequest());
50-
subscriptionItem.setReason(subscriptionEntity.getReason());
51-
subscriptionItem.setStatus(Subscription.StatusEnum.fromValue(subscriptionEntity.getStatus().name()));
52-
subscriptionItem.setSubscribedBy(subscriptionEntity.getSubscribedBy());
53-
subscriptionItem.setOrigin(convert(subscriptionEntity.getOrigin()));
54-
return subscriptionItem;
41+
default Subscription.StatusEnum map(SubscriptionStatus status) {
42+
return Subscription.StatusEnum.fromValue(status.name());
5543
}
5644

57-
private OffsetDateTime getDate(final Date date) {
58-
if (date != null) {
59-
return date.toInstant().atOffset(ZoneOffset.UTC);
60-
}
61-
return null;
62-
}
63-
64-
private static Subscription.OriginEnum convert(String origin) {
45+
default Subscription.OriginEnum convert(String origin) {
6546
try {
6647
return Subscription.OriginEnum.valueOf(origin);
6748
} catch (IllegalArgumentException | NullPointerException e) {
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package io.gravitee.rest.api.portal.rest.mapper;
16+
package io.gravitee.rest.api.portal.rest.provider;
1717

1818
import com.fasterxml.jackson.databind.ObjectMapper;
1919
import com.fasterxml.jackson.databind.SerializationFeature;

gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/main/java/io/gravitee/rest/api/portal/rest/resource/ApplicationsResource.java

+1-4
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,6 @@ public class ApplicationsResource extends AbstractResource<Application, String>
8383
@Inject
8484
private SubscriptionService subscriptionService;
8585

86-
@Inject
87-
private SubscriptionMapper subscriptionMapper;
88-
8986
@POST
9087
@Consumes(MediaType.APPLICATION_JSON)
9188
@Produces(MediaType.APPLICATION_JSON)
@@ -236,7 +233,7 @@ protected Map fillMetadata(ExecutionContext executionContext, Map metadata, List
236233
final Map<String, List<Subscription>> subscriptions = subscriptionService
237234
.search(executionContext, query)
238235
.stream()
239-
.map(subscriptionMapper::convert)
236+
.map(SubscriptionMapper.INSTANCE::map)
240237
.collect(groupingBy(Subscription::getApplication));
241238
if (!subscriptions.isEmpty()) {
242239
metadata.put(METADATA_SUBSCRIPTIONS_KEY, subscriptions);

gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/main/java/io/gravitee/rest/api/portal/rest/resource/GraviteePortalApplication.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,18 @@
1515
*/
1616
package io.gravitee.rest.api.portal.rest.resource;
1717

18-
import io.gravitee.rest.api.portal.rest.mapper.ObjectMapperResolver;
1918
import io.gravitee.rest.api.portal.rest.provider.BadRequestExceptionMapper;
2019
import io.gravitee.rest.api.portal.rest.provider.ByteArrayOutputStreamWriter;
2120
import io.gravitee.rest.api.portal.rest.provider.ConstraintValidationExceptionMapper;
2221
import io.gravitee.rest.api.portal.rest.provider.JsonMappingExceptionMapper;
2322
import io.gravitee.rest.api.portal.rest.provider.ManagementExceptionMapper;
2423
import io.gravitee.rest.api.portal.rest.provider.NotAllowedExceptionMapper;
2524
import io.gravitee.rest.api.portal.rest.provider.NotFoundExceptionMapper;
25+
import io.gravitee.rest.api.portal.rest.provider.ObjectMapperResolver;
2626
import io.gravitee.rest.api.portal.rest.provider.PayloadInputBodyReader;
2727
import io.gravitee.rest.api.portal.rest.provider.QueryParamExceptionMapper;
2828
import io.gravitee.rest.api.portal.rest.provider.ThrowableMapper;
2929
import io.gravitee.rest.api.portal.rest.provider.UnrecognizedPropertyExceptionMapper;
30-
import io.gravitee.rest.api.portal.rest.resource.auth.ConsoleAuthenticationResource;
3130
import io.gravitee.rest.api.portal.rest.resource.bootstrap.PortalUIBootstrapResource;
3231
import io.gravitee.rest.api.rest.filter.GraviteeContextResponseFilter;
3332
import io.gravitee.rest.api.rest.filter.MaintenanceFilter;

gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/main/java/io/gravitee/rest/api/portal/rest/resource/SubscriptionResource.java

+1-4
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,6 @@ public class SubscriptionResource extends AbstractResource {
8080
@Inject
8181
private KeyMapper keyMapper;
8282

83-
@Inject
84-
private SubscriptionMapper subscriptionMapper;
85-
8683
@Inject
8784
private GraviteeMapper graviteeMapper;
8885

@@ -100,7 +97,7 @@ public Response getSubscriptionBySubscriptionId(
10097
hasPermission(executionContext, RolePermission.API_SUBSCRIPTION, subscriptionEntity.getApi(), RolePermissionAction.READ) ||
10198
hasPermission(executionContext, APPLICATION_SUBSCRIPTION, subscriptionEntity.getApplication(), RolePermissionAction.READ)
10299
) {
103-
Subscription subscription = subscriptionMapper.convert(subscriptionEntity);
100+
Subscription subscription = SubscriptionMapper.INSTANCE.map(subscriptionEntity);
104101
if (include.contains(INCLUDE_KEYS)) {
105102
List<Key> keys = apiKeyService
106103
.findBySubscription(executionContext, subscriptionId)

gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/main/java/io/gravitee/rest/api/portal/rest/resource/SubscriptionsResource.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,6 @@ public class SubscriptionsResource extends AbstractResource {
8080
@Inject
8181
private SubscriptionService subscriptionService;
8282

83-
@Inject
84-
private SubscriptionMapper subscriptionMapper;
85-
8683
@Inject
8784
private ApplicationService applicationService;
8885

@@ -143,7 +140,7 @@ public Response createSubscription(@Valid @NotNull(message = "Input must not be
143140
.map(keyMapper::convert)
144141
.collect(Collectors.toList());
145142

146-
final Subscription subscription = subscriptionMapper.convert(createdSubscription);
143+
final Subscription subscription = SubscriptionMapper.INSTANCE.map(createdSubscription);
147144
subscription.setKeys(keys);
148145

149146
return Response.ok(subscription).build();
@@ -181,7 +178,10 @@ public Response getSubscriptions(
181178
return createListResponse(executionContext, subscriptions, paginationParam, null, paginationParam.hasPagination());
182179
}
183180

184-
final List<Subscription> subscriptionList = subscriptions.stream().map(subscriptionMapper::convert).collect(Collectors.toList());
181+
final List<Subscription> subscriptionList = subscriptions
182+
.stream()
183+
.map(SubscriptionMapper.INSTANCE::map)
184+
.collect(Collectors.toList());
185185

186186
SubscriptionMetadataQuery metadataQuery = new SubscriptionMetadataQuery(
187187
GraviteeContext.getCurrentOrganization(),

gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/main/java/io/gravitee/rest/api/portal/rest/spring/RestPortalConfiguration.java

+49-1
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,31 @@
1515
*/
1616
package io.gravitee.rest.api.portal.rest.spring;
1717

18+
import io.gravitee.rest.api.portal.rest.mapper.AlertMapper;
19+
import io.gravitee.rest.api.portal.rest.mapper.AnalyticsMapper;
20+
import io.gravitee.rest.api.portal.rest.mapper.ApiMapper;
21+
import io.gravitee.rest.api.portal.rest.mapper.ApplicationMapper;
22+
import io.gravitee.rest.api.portal.rest.mapper.CategoryMapper;
23+
import io.gravitee.rest.api.portal.rest.mapper.ConfigurationMapper;
24+
import io.gravitee.rest.api.portal.rest.mapper.DashboardMapper;
25+
import io.gravitee.rest.api.portal.rest.mapper.IdentityProviderMapper;
26+
import io.gravitee.rest.api.portal.rest.mapper.KeyMapper;
27+
import io.gravitee.rest.api.portal.rest.mapper.LogMapper;
28+
import io.gravitee.rest.api.portal.rest.mapper.MemberMapper;
29+
import io.gravitee.rest.api.portal.rest.mapper.PageMapper;
30+
import io.gravitee.rest.api.portal.rest.mapper.PlanMapper;
31+
import io.gravitee.rest.api.portal.rest.mapper.PortalMenuLinkMapper;
32+
import io.gravitee.rest.api.portal.rest.mapper.PortalNotificationMapper;
33+
import io.gravitee.rest.api.portal.rest.mapper.RatingMapper;
34+
import io.gravitee.rest.api.portal.rest.mapper.ReferenceMetadataMapper;
35+
import io.gravitee.rest.api.portal.rest.mapper.ThemeMapper;
36+
import io.gravitee.rest.api.portal.rest.mapper.TicketMapper;
37+
import io.gravitee.rest.api.portal.rest.mapper.UserMapper;
1838
import io.gravitee.rest.api.portal.security.SecurityPortalConfiguration;
1939
import io.gravitee.rest.api.service.spring.ServiceConfiguration;
2040
import org.springframework.context.annotation.ComponentScan;
2141
import org.springframework.context.annotation.Configuration;
42+
import org.springframework.context.annotation.FilterType;
2243
import org.springframework.context.annotation.Import;
2344
import org.springframework.scheduling.annotation.EnableAsync;
2445

@@ -27,7 +48,34 @@
2748
* @author GraviteeSource Team
2849
*/
2950
@Configuration
30-
@ComponentScan({ "io.gravitee.rest.api.portal.rest.mapper" })
51+
@ComponentScan(
52+
basePackages = "io.gravitee.rest.api.portal.rest.mapper", // please prefer using Mapstruct mappers and not declare new manual mappers here
53+
includeFilters = @ComponentScan.Filter(
54+
type = FilterType.ASSIGNABLE_TYPE,
55+
classes = {
56+
AlertMapper.class,
57+
AnalyticsMapper.class,
58+
ApiMapper.class,
59+
ApplicationMapper.class,
60+
CategoryMapper.class,
61+
ConfigurationMapper.class,
62+
DashboardMapper.class,
63+
IdentityProviderMapper.class,
64+
KeyMapper.class,
65+
LogMapper.class,
66+
MemberMapper.class,
67+
PageMapper.class,
68+
PlanMapper.class,
69+
PortalMenuLinkMapper.class,
70+
PortalNotificationMapper.class,
71+
RatingMapper.class,
72+
ReferenceMetadataMapper.class,
73+
ThemeMapper.class,
74+
TicketMapper.class,
75+
UserMapper.class,
76+
}
77+
)
78+
)
3179
@Import({ ServiceConfiguration.class, SecurityPortalConfiguration.class })
3280
@EnableAsync
3381
public class RestPortalConfiguration {}

gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/test/java/io/gravitee/rest/api/portal/rest/JerseySpringTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
package io.gravitee.rest.api.portal.rest;
1717

1818
import io.gravitee.rest.api.idp.api.authentication.UserDetails;
19-
import io.gravitee.rest.api.portal.rest.mapper.ObjectMapperResolver;
19+
import io.gravitee.rest.api.portal.rest.provider.ObjectMapperResolver;
2020
import io.gravitee.rest.api.portal.rest.resource.GraviteePortalApplication;
2121
import io.gravitee.rest.api.security.authentication.AuthenticationProviderManager;
2222
import jakarta.annotation.Priority;

gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/test/java/io/gravitee/rest/api/portal/rest/mapper/SubscriptionMapperTest.java

+5-9
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,12 @@
2626
import java.time.Instant;
2727
import java.util.Date;
2828
import org.junit.Test;
29-
import org.junit.runner.RunWith;
30-
import org.mockito.InjectMocks;
31-
import org.mockito.junit.MockitoJUnitRunner;
29+
import org.mapstruct.factory.Mappers;
3230

3331
/**
3432
* @author Florent CHAMFROY (florent.chamfroy at graviteesource.com)
3533
* @author GraviteeSource Team
3634
*/
37-
@RunWith(MockitoJUnitRunner.class)
3835
public class SubscriptionMapperTest {
3936

4037
private static final String SUBSCRIPTION_API = "my-subscription-api";
@@ -49,8 +46,7 @@ public class SubscriptionMapperTest {
4946

5047
private SubscriptionEntity subscriptionEntity;
5148

52-
@InjectMocks
53-
private SubscriptionMapper subscriptionMapper;
49+
private final SubscriptionMapper subscriptionMapper = Mappers.getMapper(SubscriptionMapper.class);
5450

5551
@Test
5652
public void testConvert() {
@@ -80,7 +76,7 @@ public void testConvert() {
8076
subscriptionEntity.setOrigin("KUBERNETES");
8177

8278
//Test
83-
Subscription subscription = subscriptionMapper.convert(subscriptionEntity);
79+
Subscription subscription = subscriptionMapper.map(subscriptionEntity);
8480
assertNotNull(subscription);
8581

8682
assertEquals(SUBSCRIPTION_API, subscription.getApi());
@@ -108,7 +104,7 @@ public void should_handle_null_origin() {
108104
subscriptionEntity.setOrigin(null);
109105

110106
//Test
111-
Subscription subscription = subscriptionMapper.convert(subscriptionEntity);
107+
Subscription subscription = subscriptionMapper.map(subscriptionEntity);
112108
assertNotNull(subscription);
113109

114110
assertEquals(SUBSCRIPTION_API, subscription.getApi());
@@ -127,7 +123,7 @@ public void should_handle_origin_not_in_enum() {
127123
subscriptionEntity.setOrigin("unicorn");
128124

129125
//Test
130-
Subscription subscription = subscriptionMapper.convert(subscriptionEntity);
126+
Subscription subscription = subscriptionMapper.map(subscriptionEntity);
131127
assertNotNull(subscription);
132128

133129
assertEquals(SUBSCRIPTION_API, subscription.getApi());

gravitee-apim-rest-api/gravitee-apim-rest-api-portal/gravitee-apim-rest-api-portal-rest/src/test/java/io/gravitee/rest/api/portal/rest/resource/AbstractResourceTest.java

-5
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,6 @@ public abstract class AbstractResourceTest extends JerseySpringTest {
255255
@Autowired
256256
protected RatingMapper ratingMapper;
257257

258-
@Autowired
259-
protected SubscriptionMapper subscriptionMapper;
260-
261258
@Autowired
262259
protected KeyMapper keyMapper;
263260

@@ -395,9 +392,7 @@ protected void resetAllMocks() {
395392
reset(pageMapper);
396393
reset(planMapper);
397394
reset(ratingMapper);
398-
reset(subscriptionMapper);
399395
reset(keyMapper);
400-
reset(subscriptionMapper);
401396
reset(applicationMapper);
402397
reset(memberMapper);
403398
reset(userMapper);

0 commit comments

Comments
 (0)