This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch spring6 in repository https://gitbox.apache.org/repos/asf/isis.git
commit 0ae277e4c04002caf33fc61c96ef6fe3d8095fbd Merge: bc1e0613d3 a7e244f5ff Author: Andi Huber <ahu...@apache.org> AuthorDate: Thu Dec 1 13:20:08 2022 +0100 ISIS-3275: merge from master .../causeway/applib/client/SuppressionType.java | 8 +- bom/pom.xml | 53 ++----- ...nthesizedMergedAnnotationInvocationHandler.java | 19 +-- .../applib/restapi/OutboxRestApi.java | 2 - extensions/core/executionoutbox/restclient/pom.xml | 143 +++---------------- .../executionoutbox/restclient/api/Jsonable.java | 27 ---- .../restclient/api/OutboxClient.java | 156 ++++++++------------- .../executionoutbox/restclient/api/_Jaxb.java | 92 ------------ .../restclient/api/delete/DeleteMessage.java | 30 +--- .../restclient/api/delete/IntValue.java | 7 +- .../restclient/api/delete/StringValue.java | 7 +- .../api/deleteMany/DeleteManyMessage.java | 27 +--- .../restclient/integtests/RestEndpointService.java | 3 +- .../secondary/fetch/CommandFetcher.java | 20 +-- .../testdomain/util/rest/RestEndpointService.java | 29 ++-- .../client/src/main/java/module-info.java | 6 +- .../restfulobjects/client/ResponseDigest.java | 66 +-------- .../restfulobjects/client/ResponseDigester.java | 127 +++++++++++++++++ .../restfulobjects/client/RestfulClient.java | 120 ++++++++-------- .../restfulobjects/client/RestfulClientConfig.java | 43 +++++- .../client/RestfulClientMediaType.java | 96 +++++++++++++ 21 files changed, 469 insertions(+), 612 deletions(-) diff --cc bom/pom.xml index 63f3e5dab4,74d46d9126..1e8d4b8b12 --- a/bom/pom.xml +++ b/bom/pom.xml @@@ -241,53 -233,31 +241,35 @@@ It is therefore a copy of org.apache:ap </dependencies> </dependencyManagement> <repositories> - <!-- breaks dependabot run: timeout due to repo not accessible - <repository> - <id>apache.snapshots</id> - <name>Apache Snapshot Repository</name> - <url>https://repository.apache.org/snapshots</url> - <releases> - <enabled>false</enabled> - </releases> - </repository> - --> + <repository> + <id>central</id> + <name>Central Repository</name> + <url>https://repo.maven.apache.org/maven2</url> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + <repository> + <!-- temporary till release of cxf 4.0.0, shiro 2.0.0 and wicket 10.0.0 --> + <id>apache.snapshots</id> - <name>Shiro Snapshot Repository</name> + <url>https://repository.apache.org/content/groups/snapshots/</url> + <snapshots><enabled>true</enabled></snapshots> + </repository> <repository> - <id>Apache Repository</id> - <url>https://repository.apache.org/</url> + <!-- used for wicket 10.0.0-M1-SNAPSHOT fork at + https://jitpack.io/#apache-causeway-committers/wicket + temporary till release of wicket 10.0.0 --> + <id>jitpack.io</id> + <url>https://jitpack.io</url> + </repository> + <repository> + <!-- temporary till release of wicket-stuff 10.0.0 --> - <id>wicketstuff-core-snapshots</id> ++ <id>sonatype-snapshots</id> + <url>https://oss.sonatype.org/content/repositories/snapshots</url> <snapshots> - <enabled>false</enabled> - </snapshots> + <enabled>true</enabled> + </snapshots> </repository> - <!-- breaks dependabot run: timeout due to repo not accessible - <repository> - <id>apache.snapshots</id> - <name>Apache Snapshot Repository</name> - <url>https://repository.apache.org/snapshots</url> - <releases> - <enabled>false</enabled> - </releases> - </repository> - --> - <repository> - <id>central</id> - <name>Central Repository</name> - <url>https://repo.maven.apache.org/maven2</url> - <snapshots> - <enabled>false</enabled> - </snapshots> - </repository> - <repository> - <id>Apache Repository</id> - <url>https://repository.apache.org/</url> - <snapshots> - <enabled>false</enabled> - </snapshots> - </repository> <repository> <!-- required for RestEasy --> <id>JBoss Public Release</id> @@@ -296,25 -266,25 +278,8 @@@ <enabled>false</enabled> </snapshots> </repository> -- <repository> -- <id>sonatype-snapshots</id> -- <url>https://oss.sonatype.org/content/repositories/snapshots</url> -- <snapshots> -- <enabled>true</enabled> -- </snapshots> -- </repository> </repositories> <pluginRepositories> -- <!-- breaks dependabot run: timeout due to repo not accessible -- <pluginRepository> -- <id>apache.snapshots</id> -- <name>Apache Snapshot Repository</name> -- <url>https://repository.apache.org/snapshots</url> -- <releases> -- <enabled>false</enabled> -- </releases> -- </pluginRepository> -- --> <pluginRepository> <id>DataNucleus_2</id> <url>https://www.datanucleus.org/downloads/maven2/</url> diff --cc commons/src/main/java/org/apache/causeway/commons/internal/reflection/_Annotations_SynthesizedMergedAnnotationInvocationHandler.java index 5c5108abd2,6b4de058b0..5f0c25b976 --- a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_Annotations_SynthesizedMergedAnnotationInvocationHandler.java +++ b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_Annotations_SynthesizedMergedAnnotationInvocationHandler.java @@@ -236,23 -236,21 +236,24 @@@ implements InvocationHandler additional.get(), null, annotationType); val classLoader = annotationType.getClassLoader(); - //TODO[ISIS-3275] - val interfaces = isVisible(classLoader, SynthesizedAnnotation.class) - ? new Class<?>[] {annotationType, SynthesizedAnnotation.class} - : new Class<?>[] {annotationType}; ++ /* removal of SynthesizedAnnotation in Spring 6 ++ * https://github.com/spring-projects/spring-framework/commit/69f23095b810615862336d35d878dda63f7b4fca */ + val interfaces = //isVisible(classLoader, SynthesizedAnnotation.class) + //? new Class<?>[] {annotationType, SynthesizedAnnotation.class} + //: + new Class<?>[] {annotationType}; val proxy = (A) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); return Optional.of(proxy); } -- private static boolean isVisible(final ClassLoader classLoader, final Class<?> interfaceClass) { -- try { -- return Class.forName(interfaceClass.getName(), false, classLoader) == interfaceClass; -- } -- catch (ClassNotFoundException ex) { -- return false; -- } -- } ++// private static boolean isVisible(final ClassLoader classLoader, final Class<?> interfaceClass) { ++// try { ++// return Class.forName(interfaceClass.getName(), false, classLoader) == interfaceClass; ++// } ++// catch (ClassNotFoundException ex) { ++// return false; ++// } ++// } /** * If annotations from a getter method are competing with annotations from its corresponding field, diff --cc extensions/core/executionoutbox/restclient/pom.xml index b98eb9e435,5a9c7e2dae..b09bfb8989 --- a/extensions/core/executionoutbox/restclient/pom.xml +++ b/extensions/core/executionoutbox/restclient/pom.xml @@@ -66,32 -54,24 +54,24 @@@ </dependency> <dependency> - <groupId>jakarta.ws.rs</groupId> - <artifactId>jakarta.ws.rs-api</artifactId> + <groupId>org.apache.causeway.core</groupId> + <artifactId>causeway-schema</artifactId> </dependency> + + <dependency> + <groupId>org.apache.causeway.viewer</groupId> + <artifactId>causeway-viewer-restfulobjects-client</artifactId> - <version>2.0.0-SNAPSHOT</version> ++ <version>3.0.0-SNAPSHOT</version> + </dependency> - <dependency> - <groupId>org.apache.cxf</groupId> - <artifactId>cxf-rt-rs-client</artifactId> - </dependency> - - <!-- TESTING --> - - <dependency> - <groupId>org.apache.causeway.testing</groupId> - <artifactId>causeway-testing-unittestsupport-applib</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.causeway.security</groupId> - <artifactId>causeway-security-bypass</artifactId> - <scope>test</scope> - </dependency> + <!-- TESTING --> + <dependency> <groupId>org.apache.causeway.core</groupId> - <artifactId>causeway-core-runtimeservices</artifactId> + <artifactId>causeway-core-internaltestsupport</artifactId> <scope>test</scope> </dependency> + <dependency> <groupId>org.apache.causeway.testing</groupId> <artifactId>causeway-testing-fixtures-applib</artifactId> diff --cc extensions/core/executionoutbox/restclient/src/main/java/org/apache/causeway/extensions/executionoutbox/restclient/api/OutboxClient.java index 5263c0a934,27bc33f225..dfec7a0438 --- a/extensions/core/executionoutbox/restclient/src/main/java/org/apache/causeway/extensions/executionoutbox/restclient/api/OutboxClient.java +++ b/extensions/core/executionoutbox/restclient/src/main/java/org/apache/causeway/extensions/executionoutbox/restclient/api/OutboxClient.java @@@ -21,16 -21,14 +21,14 @@@ package org.apache.causeway.extensions.executionoutbox.restclient.api; import java.util.Collections; - import java.util.HashMap; import java.util.List; - import java.util.concurrent.TimeUnit; - import jakarta.ws.rs.client.Client; - import jakarta.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.Entity; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.core.MediaType; - import jakarta.ws.rs.core.UriBuilder; + import org.apache.causeway.applib.util.schema.InteractionsDtoUtils; + import org.apache.causeway.commons.functional.Try; + import org.apache.causeway.commons.internal.resources._Json; import org.apache.causeway.extensions.executionoutbox.restclient.api.delete.DeleteMessage; import org.apache.causeway.extensions.executionoutbox.restclient.api.deleteMany.DeleteManyMessage; import org.apache.causeway.schema.common.v2.InteractionType; diff --cc regressiontests/stable/src/main/java/org/apache/causeway/testdomain/util/rest/RestEndpointService.java index 261ac24df0,f8d2ca8ae0..b996cc7a43 --- a/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/util/rest/RestEndpointService.java +++ b/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/util/rest/RestEndpointService.java @@@ -36,12 -41,9 +36,13 @@@ import org.apache.causeway.testdomain.l import org.apache.causeway.testdomain.util.dto.BookDto; import org.apache.causeway.viewer.restfulobjects.client.RestfulClient; import org.apache.causeway.viewer.restfulobjects.client.RestfulClientConfig; + import org.apache.causeway.viewer.restfulobjects.client.RestfulClientMediaType; import org.apache.causeway.viewer.restfulobjects.client.log.ClientConversationFilter; +import jakarta.inject.Inject; +import jakarta.ws.rs.client.Invocation; +import jakarta.ws.rs.core.GenericType; +import jakarta.xml.bind.JAXBException; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.val; diff --cc viewers/restfulobjects/client/src/main/java/module-info.java index bc1bf17cd8,18615e6f43..1fabe8b8e3 --- a/viewers/restfulobjects/client/src/main/java/module-info.java +++ b/viewers/restfulobjects/client/src/main/java/module-info.java @@@ -23,13 -23,13 +23,13 @@@ module org.apache.causeway.viewer.restf requires com.fasterxml.jackson.core; requires com.fasterxml.jackson.databind; - requires java.annotation; - requires java.ws.rs; - requires java.xml.bind; + requires jakarta.annotation; + requires jakarta.ws.rs; + requires jakarta.xml.bind; requires lombok; - requires org.apache.causeway.applib; - requires org.apache.causeway.commons; - requires org.apache.causeway.viewer.restfulobjects.applib; + requires transitive org.apache.causeway.applib; + requires transitive org.apache.causeway.commons; + requires transitive org.apache.causeway.viewer.restfulobjects.applib; requires org.apache.logging.log4j; requires spring.core; } diff --cc viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/ResponseDigest.java index dbb3ded646,5c4ef3c978..70907b2cf7 --- a/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/ResponseDigest.java +++ b/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/ResponseDigest.java @@@ -26,22 -24,15 +24,15 @@@ import java.util.List import java.util.NoSuchElementException; import java.util.Optional; -import javax.ws.rs.core.GenericType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status.Family; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.Response.Status.Family; - import com.fasterxml.jackson.core.JsonParseException; - import com.fasterxml.jackson.databind.JsonMappingException; - import com.fasterxml.jackson.databind.ObjectMapper; - import org.springframework.lang.Nullable; - import org.apache.causeway.applib.client.RepresentationTypeSimplifiedV2; import org.apache.causeway.commons.collections.Can; - import org.apache.causeway.commons.internal.base._Casts; import org.apache.causeway.commons.internal.base._Strings; import org.apache.causeway.commons.internal.exceptions._Exceptions; - import org.apache.causeway.viewer.restfulobjects.applib.dtos.ScalarValueDtoV2; import lombok.NonNull; import lombok.val; diff --cc viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/ResponseDigester.java index 0000000000,ed4c52651d..ea280366f6 mode 000000,100644..100644 --- a/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/ResponseDigester.java +++ b/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/ResponseDigester.java @@@ -1,0 -1,127 +1,127 @@@ + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package org.apache.causeway.viewer.restfulobjects.client; + + import java.io.IOException; + import java.util.ArrayList; + import java.util.List; + import java.util.Optional; + -import javax.ws.rs.core.GenericType; -import javax.ws.rs.core.Response; ++import jakarta.ws.rs.core.GenericType; ++import jakarta.ws.rs.core.Response; + + import com.fasterxml.jackson.core.JsonParseException; + import com.fasterxml.jackson.databind.JsonMappingException; + import com.fasterxml.jackson.databind.ObjectMapper; + + import org.springframework.lang.Nullable; + + import org.apache.causeway.applib.client.RepresentationTypeSimplifiedV2; + import org.apache.causeway.commons.internal.base._Casts; + import org.apache.causeway.commons.internal.base._Strings; + import org.apache.causeway.commons.internal.exceptions._Exceptions; + import org.apache.causeway.viewer.restfulobjects.applib.dtos.ScalarValueDtoV2; + + import lombok.RequiredArgsConstructor; + import lombok.SneakyThrows; + import lombok.val; + + interface ResponseDigester { + + <T> T readSingle(Class<T> entityType, Response response); + <T> List<T> readList(Class<T> entityType, GenericType<List<T>> genericType, Response response); + + // -- FACTORIES + + static Optional<ResponseDigester> forContentTypeHeaderString(final @Nullable String contentTypeHeaderString) { + if(_Strings.isEmpty(contentTypeHeaderString)) { + return Optional.empty(); + } + if(contentTypeHeaderString.startsWith("application/xml;profile=\"urn:org.restfulobjects:repr-types/action-result\"") + && contentTypeHeaderString.contains("x-ro-domain-type")) { + return Optional.of(new ResponseDigesterXmlStandard()); + } + return RepresentationTypeSimplifiedV2.parseContentTypeHeaderString(contentTypeHeaderString) + .map(ResponseDigesterJsonSimple::new); + } + + // -- IMPLEMENTATIONS + + @RequiredArgsConstructor + static class ResponseDigesterXmlStandard implements ResponseDigester { + + @Override + public <T> T readSingle(final Class<T> entityType, final Response response) { + return response.readEntity(entityType); + } + + @Override + public <T> List<T> readList(final Class<T> entityType, final GenericType<List<T>> genericType, final Response response) { + throw _Exceptions.notImplemented(); + } + } + + @RequiredArgsConstructor + static class ResponseDigesterJsonSimple implements ResponseDigester { + + private final RepresentationTypeSimplifiedV2 reprType; + + @SneakyThrows + @Override + public <T> T readSingle(final Class<T> entityType, final Response response) { + if(reprType.isValue() + || reprType.isValues()) { + val mapper = new ObjectMapper(); + val jsonInput = response.readEntity(String.class); + val scalarValueDto = mapper.readValue(jsonInput, ScalarValueDtoV2.class); + return extractValue(scalarValueDto); + } + return response.<T>readEntity(entityType); + } + + @SneakyThrows + @Override + public <T> List<T> readList(final Class<T> entityType, final GenericType<List<T>> genericType, final Response response) { + if(reprType.isValues() + || reprType.isValue()) { + val mapper = new ObjectMapper(); + val jsonInput = response.readEntity(String.class); + final List<ScalarValueDtoV2> scalarValueDtoList = + mapper.readValue( + jsonInput, + mapper.getTypeFactory().constructCollectionType(List.class, ScalarValueDtoV2.class)); + + final List<T> resultList = new ArrayList<>(scalarValueDtoList.size()); + for(val valueBody : scalarValueDtoList) { + // explicit loop, for simpler exception propagation + resultList.add(extractValue(valueBody)); + } + return resultList; + + } + return response.readEntity(genericType); + } + + private <T> T extractValue(final ScalarValueDtoV2 scalarValueDto) + throws JsonParseException, JsonMappingException, IOException { + return _Casts.uncheckedCast(scalarValueDto.getValue()); + } + } + + } diff --cc viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/RestfulClient.java index a23ad76ec2,a65ba69516..9988d8c7b0 --- a/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/RestfulClient.java +++ b/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/RestfulClient.java @@@ -18,18 -18,18 +18,18 @@@ */ package org.apache.causeway.viewer.restfulobjects.client; - import java.util.EnumSet; + import java.net.URI; import java.util.List; import java.util.Objects; - import java.util.stream.Collectors; + import java.util.function.UnaryOperator; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.Invocation.Builder; -import javax.ws.rs.core.GenericType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.Invocation.Builder; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.Response; ++import jakarta.ws.rs.core.UriBuilder; - import org.apache.causeway.applib.client.SuppressionType; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.functional.Try; import org.apache.causeway.commons.internal.base._Strings; diff --cc viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/RestfulClientConfig.java index 723c2a1d5f,3d430d8ca3..c4caa327d9 --- a/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/RestfulClientConfig.java +++ b/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/RestfulClientConfig.java @@@ -20,12 -20,15 +20,15 @@@ package org.apache.causeway.viewer.rest import java.util.ArrayList; import java.util.List; + import java.util.concurrent.TimeUnit; + import java.util.concurrent.TimeoutException; -import javax.ws.rs.ProcessingException; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; ++import jakarta.ws.rs.ProcessingException; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.XmlTransient; import org.apache.causeway.viewer.restfulobjects.client.log.ClientConversationFilter; diff --cc viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/RestfulClientMediaType.java index 0000000000,7ab02a68ba..086e26e805 mode 000000,100644..100644 --- a/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/RestfulClientMediaType.java +++ b/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/RestfulClientMediaType.java @@@ -1,0 -1,96 +1,96 @@@ + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package org.apache.causeway.viewer.restfulobjects.client; + + import java.util.EnumSet; + import java.util.Map; + import java.util.Optional; + import java.util.stream.Collectors; + -import javax.ws.rs.core.MediaType; ++import jakarta.ws.rs.core.MediaType; + + import org.springframework.lang.Nullable; + + import org.apache.causeway.applib.client.SuppressionType; + import org.apache.causeway.commons.internal.base._NullSafe; + import org.apache.causeway.commons.internal.base._Strings; + import org.apache.causeway.commons.internal.collections._Maps; + + import lombok.RequiredArgsConstructor; + import lombok.val; + + @RequiredArgsConstructor + public enum RestfulClientMediaType { + RO_XML("application", "xml", "org.restfulobjects:repr-types/action-result"), + SIMPLE_JSON("application", "json", "org.apache.causeway/v2"); + ; + + private final String type; + private final String subType; + private final String urn; + + public final MediaType mediaTypeFor() { + return mediaTypeFor(null, EnumSet.noneOf(SuppressionType.class)); + } + + public final MediaType mediaTypeFor( + final @Nullable Class<?> dtoClass) { + return mediaTypeFor(dtoClass, EnumSet.noneOf(SuppressionType.class)); + } + + public final MediaType mediaTypeFor( + final @Nullable EnumSet<SuppressionType> suppressionTypes) { + return new MediaType(type, subType, headerMap(urn, null, suppressionTypes)); + } + + public final MediaType mediaTypeFor( + final @Nullable Class<?> dtoClass, + final @Nullable EnumSet<SuppressionType> suppressionTypes) { + return new MediaType(type, subType, headerMap(urn, dtoClass, suppressionTypes)); + } + + // -- HELPER + + private static Map<String, String> headerMap( + final String urn, + final Class<?> dtoClass, + final EnumSet<SuppressionType> suppressionTypes) { + val headerMap = _Maps.<String, String>newHashMap(); + + headerMap.put("profile", "urn:" + urn); + + toSuppressionLiteral(suppressionTypes) + .ifPresent(suppress->headerMap.put("suppress", suppress)); + + Optional.ofNullable(dtoClass) + .map(Class::getName) + .ifPresent(typeLiteral->headerMap.put("x-ro-domain-type", typeLiteral)); + + return headerMap; + } + + private static Optional<String> toSuppressionLiteral(final EnumSet<SuppressionType> suppressionTypes) { + final String suppressionSetLiteral = _NullSafe.stream(suppressionTypes) + .map(SuppressionType::name) + .collect(Collectors.joining(",")); + return _Strings.nonEmpty(suppressionSetLiteral); + } + + } +