1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.restapi.v1.utils;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.lang.annotation.Annotation;
24 import java.lang.reflect.Type;
25 import java.nio.charset.StandardCharsets;
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.stream.Collectors;
29
30 import org.apache.logging.log4j.LogManager;
31 import org.apache.logging.log4j.Logger;
32
33 import com.google.common.reflect.TypeToken;
34 import com.google.gson.GsonBuilder;
35 import com.google.gson.JsonElement;
36 import com.google.gson.JsonObject;
37 import com.google.gson.JsonSerializationContext;
38 import com.google.gson.JsonSerializer;
39
40 import jakarta.ws.rs.Produces;
41 import jakarta.ws.rs.WebApplicationException;
42 import jakarta.ws.rs.core.HttpHeaders;
43 import jakarta.ws.rs.core.MediaType;
44 import jakarta.ws.rs.core.MultivaluedMap;
45 import jakarta.ws.rs.ext.MessageBodyWriter;
46 import jakarta.ws.rs.ext.Provider;
47
48 @Produces(MediaType.APPLICATION_JSON)
49 @Provider
50 public class MCRPropertiesToJSONTransformer implements MessageBodyWriter<Properties> {
51
52 @Override
53 public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
54 return Properties.class.isAssignableFrom(type) && mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE);
55 }
56
57 @Override
58 public long getSize(Properties t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
59 return -1;
60 }
61
62 @Override
63 public void writeTo(Properties t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
64 MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
65 throws IOException, WebApplicationException {
66 httpHeaders.putSingle(HttpHeaders.CONTENT_TYPE,
67 MediaType.APPLICATION_JSON_TYPE.withCharset(StandardCharsets.UTF_8.name()));
68 final Type mapType = new TypeToken<Map<String, String>>() {
69 private static final long serialVersionUID = 1L;
70 }.getType();
71 Map<String, String> writeMap = t.entrySet()
72 .stream()
73 .collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue().toString()));
74 String json = new GsonBuilder().registerTypeAdapter(mapType, new BundleMapSerializer())
75 .create()
76 .toJson(writeMap, mapType);
77 entityStream.write(json.getBytes(StandardCharsets.UTF_8));
78 }
79
80 public static class BundleMapSerializer implements JsonSerializer<Map<String, String>> {
81
82 private static final Logger LOGGER = LogManager.getLogger();
83
84 @Override
85 public JsonElement serialize(final Map<String, String> bundleMap, final Type typeOfSrc,
86 final JsonSerializationContext context) {
87 final JsonObject resultJson = new JsonObject();
88
89 for (final String key : bundleMap.keySet()) {
90 try {
91 createFromBundleKey(resultJson, key, bundleMap.get(key));
92 } catch (final IOException e) {
93 LOGGER.error("Bundle map serialization exception: ", e);
94 }
95 }
96
97 return resultJson;
98 }
99
100 public static JsonObject createFromBundleKey(final JsonObject resultJson, final String key, final String value)
101 throws IOException {
102 if (!key.contains(".")) {
103 resultJson.addProperty(key, value);
104
105 return resultJson;
106 }
107
108 final String currentKey = firstKey(key);
109 if (currentKey != null) {
110 final String subRightKey = key.substring(currentKey.length() + 1);
111 final JsonObject childJson = getJsonIfExists(resultJson, currentKey);
112
113 resultJson.add(currentKey, createFromBundleKey(childJson, subRightKey, value));
114 }
115
116 return resultJson;
117 }
118
119 private static String firstKey(final String fullKey) {
120 final String[] splittedKey = fullKey.split("\\.");
121
122 return (splittedKey.length != 0) ? splittedKey[0] : fullKey;
123 }
124
125 private static JsonObject getJsonIfExists(final JsonObject parent, final String key) {
126 if (parent == null) {
127 LOGGER.warn("Parent json parameter is null!");
128 return null;
129 }
130
131 if (parent.get(key) != null && !(parent.get(key) instanceof JsonObject)) {
132 throw new IllegalArgumentException("Invalid key \'" + key + "\' for parent: " + parent
133 + "\nKey can not be JSON object and property or array in one time");
134 }
135
136 if (parent.getAsJsonObject(key) != null) {
137 return parent.getAsJsonObject(key);
138 } else {
139 return new JsonObject();
140 }
141 }
142 }
143 }