This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch v4
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/v4 by this push:
new 0677eae3d1a CAUSEWAY-3897: bit of housekeeping (RO)
0677eae3d1a is described below
commit 0677eae3d1ac59afdba16de737a92b6b99bc52f1
Author: Andi Huber <[email protected]>
AuthorDate: Tue Jul 8 07:29:00 2025 +0200
CAUSEWAY-3897: bit of housekeeping (RO)
---
.../org/apache/causeway/commons/io/UrlUtils.java | 4 +-
.../restfulobjects/applib/JsonRepresentation.java | 249 +++++-----------
.../restfulobjects/applib/LinkRepresentation.java | 12 +-
.../restfulobjects/applib/RestfulMediaType.java | 6 +-
.../restfulobjects/applib/RestfulResponse.java | 331 +--------------------
.../restfulobjects/applib/util/JsonMapper.java | 109 +++----
.../restfulobjects/applib/util/JsonNodeUtils.java | 86 ------
.../viewer/restfulobjects/applib/util/Links.java | 36 ---
.../restfulobjects/applib/util/MediaTypes.java | 74 -----
.../viewer/restfulobjects/applib/util/Parser.java | 7 +-
.../viewer/restfulobjects/applib/util/Parsers.java | 94 ++++--
.../restfulobjects/applib/util/PathNode.java | 33 +-
.../applib/util/UrlEncodingUtils.java | 63 ----
.../applib/util/PathNodeTest_parse.java | 16 +-
.../client/src/main/java/module-info.java | 5 +-
.../exhandling/ExceptionResponseFactory.java | 4 +-
.../JsonValueEncoderServiceDefault.java | 2 -
.../context/ResourceContext_getArg_Test.java | 6 +-
.../context/ResourceContext_stripQuotes_Test.java | 2 -
.../resources/DomainObjectResourceServerside.java | 9 +-
.../resources/DomainTypeResourceServerside.java | 4 +-
.../resources/MenuBarsResourceServerside.java | 3 +-
.../viewer/resources/ResourceAbstract.java | 9 +
.../restfulobjects/viewer/header/ParserTest.java | 8 +-
24 files changed, 251 insertions(+), 921 deletions(-)
diff --git a/commons/src/main/java/org/apache/causeway/commons/io/UrlUtils.java
b/commons/src/main/java/org/apache/causeway/commons/io/UrlUtils.java
index 94ff598c5ef..5aeb24ae606 100644
--- a/commons/src/main/java/org/apache/causeway/commons/io/UrlUtils.java
+++ b/commons/src/main/java/org/apache/causeway/commons/io/UrlUtils.java
@@ -42,7 +42,7 @@ public class UrlUtils {
* @see URLDecoder
*/
@SneakyThrows
- public static String urlDecodeUtf8(final @Nullable String input) {
+ public @Nullable String urlDecodeUtf8(final @Nullable String input) {
return input!=null
? URLDecoder.decode(input, StandardCharsets.UTF_8)
: input;
@@ -54,7 +54,7 @@ public static String urlDecodeUtf8(final @Nullable String
input) {
* @see URLEncoder
*/
@SneakyThrows
- public static String urlEncodeUtf8(final @Nullable String input) {
+ public @Nullable String urlEncodeUtf8(final @Nullable String input) {
return input!=null
? URLEncoder.encode(input, StandardCharsets.UTF_8)
: input;
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/JsonRepresentation.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/JsonRepresentation.java
index 06a6d9b8e4c..9c83ed679bb 100644
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/JsonRepresentation.java
+++
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/JsonRepresentation.java
@@ -18,11 +18,13 @@
*/
package org.apache.causeway.viewer.restfulobjects.applib;
+import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -48,11 +50,9 @@
import org.apache.causeway.commons.internal.base._Casts;
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 org.apache.causeway.commons.io.JsonUtils;
-import org.apache.causeway.viewer.restfulobjects.applib.util.JsonNodeUtils;
+import org.apache.causeway.commons.io.UrlUtils;
import org.apache.causeway.viewer.restfulobjects.applib.util.PathNode;
-import org.apache.causeway.viewer.restfulobjects.applib.util.UrlEncodingUtils;
/**
* A wrapper around {@link JsonNode} that provides some additional helper
@@ -81,16 +81,14 @@ public interface HasExtensions {
public JsonRepresentation getExtensions();
}
- private static Map<Class<?>, Function<JsonNode, ?>>
REPRESENTATION_INSTANTIATORS = _Maps.newHashMap();
- static {
- REPRESENTATION_INSTANTIATORS.put(String.class, input -> {
+ private final static Map<Class<?>, Function<JsonNode, ?>>
REPRESENTATION_INSTANTIATORS = Map.of(
+ String.class, input -> {
if (!input.isTextual()) {
throw new IllegalStateException("found node that is not a
string " + input.toString());
}
return input.textValue();
- });
- REPRESENTATION_INSTANTIATORS.put(JsonNode.class, input -> input);
- }
+ },
+ JsonNode.class, input -> input);
private static <T> Function<JsonNode, ?>
representationInstantiatorFor(final Class<T> representationType) {
Function<JsonNode, ?> transformer =
REPRESENTATION_INSTANTIATORS.get(representationType);
@@ -176,9 +174,7 @@ public boolean isValue() {
return jsonNode.isValueNode();
}
- // ///////////////////////////////////////////////////////////////////////
- // getRepresentation
- // ///////////////////////////////////////////////////////////////////////
+ // -- REPRESENTATION
public JsonRepresentation getRepresentation(final String pathTemplate,
final Object... args) {
final String pathStr = String.format(pathTemplate, args);
@@ -192,9 +188,7 @@ public JsonRepresentation getRepresentation(final String
pathTemplate, final Obj
return new JsonRepresentation(node);
}
- // ///////////////////////////////////////////////////////////////////////
- // isArray, getArray, asArray
- // ///////////////////////////////////////////////////////////////////////
+ // -- ARRAY
public boolean isArray(final String path) {
return isArray(getNode(path));
@@ -238,9 +232,7 @@ private JsonRepresentation getArrayEnsured(final String
path, final JsonNode nod
return new JsonRepresentation(node).ensureArray();
}
- // ///////////////////////////////////////////////////////////////////////
- // isMap, getMap, asMap
- // ///////////////////////////////////////////////////////////////////////
+ // -- MAP
public boolean isMap(final String path) {
return isMap(getNode(path));
@@ -272,9 +264,7 @@ private JsonRepresentation getMap(final String path, final
JsonNode node) {
return new JsonRepresentation(node);
}
- // ///////////////////////////////////////////////////////////////////////
- // isNumber
- // ///////////////////////////////////////////////////////////////////////
+ // -- NUMBER
public boolean isNumber(final String path) {
return isNumber(getNode(path));
@@ -303,9 +293,7 @@ private Number getNumber(final String path, final JsonNode
node) {
return node.numberValue();
}
- // ///////////////////////////////////////////////////////////////////////
- // isIntegralNumber, getIntegralNumber, asIntegralNumber
- // ///////////////////////////////////////////////////////////////////////
+ // -- INTEGRALNUMBER
/**
* Is a long, an int or a {@link BigInteger}.
@@ -325,81 +313,7 @@ private boolean isIntegralNumber(final JsonNode node) {
return !representsNull(node) && node.isValueNode() &&
node.isIntegralNumber();
}
- // ///////////////////////////////////////////////////////////////////////
- // getDate, asDate
- // ///////////////////////////////////////////////////////////////////////
-
-//TODO[causeway-viewer-restfulobjects-applib-CAUSEWAY-3892] we have proper
temporal types since Java 8
-// public java.util.Date getDate(final String path) {
-// return getDate(path, getNode(path));
-// }
-//
-// public java.util.Date asDate() {
-// return getDate(null, asJsonNode());
-// }
-//
-// private java.util.Date getDate(final String path, final JsonNode node) {
-// if (representsNull(node)) {
-// return null;
-// }
-// checkValue(path, node, "a date");
-// if (!node.isTextual()) {
-// throw new IllegalArgumentException(formatExMsg(path, "is not a
date"));
-// }
-// return JsonTemporalLegacy.fromJsonAsDateOnly(node);
-// }
-
- // ///////////////////////////////////////////////////////////////////////
- // getDateTime, asDateTime
- // ///////////////////////////////////////////////////////////////////////
-
-//TODO[causeway-viewer-restfulobjects-applib-CAUSEWAY-3892] we have proper
temporal types since Java 8
-// public java.util.Date getDateTime(final String path) {
-// return getDateTime(path, getNode(path));
-// }
-//
-// public java.util.Date asDateTime() {
-// return getDateTime(null, asJsonNode());
-// }
-//
-// private java.util.Date getDateTime(final String path, final JsonNode
node) {
-// if (representsNull(node)) {
-// return null;
-// }
-// checkValue(path, node, "a date-time");
-// if (!node.isTextual()) {
-// throw new IllegalArgumentException(formatExMsg(path, "is not a
date-time"));
-// }
-// return JsonTemporalLegacy.fromJsonAsDateTime(node);
-// }
-
- // ///////////////////////////////////////////////////////////////////////
- // getTime, asTime
- // ///////////////////////////////////////////////////////////////////////
-
-//TODO[causeway-viewer-restfulobjects-applib-CAUSEWAY-3892] we have proper
temporal types since Java 8
-// public java.util.Date getTime(final String path) {
-// return getTime(path, getNode(path));
-// }
-//
-// public java.util.Date asTime() {
-// return getTime(null, asJsonNode());
-// }
-//
-// private java.util.Date getTime(final String path, final JsonNode node) {
-// if (representsNull(node)) {
-// return null;
-// }
-// checkValue(path, node, "a time");
-// if (!node.isTextual()) {
-// throw new IllegalArgumentException(formatExMsg(path, "is not a
time"));
-// }
-// return JsonTemporalLegacy.fromJsonAsTimeOnly(node);
-// }
-
- // ///////////////////////////////////////////////////////////////////////
- // isBoolean, getBoolean, asBoolean
- // ///////////////////////////////////////////////////////////////////////
+ // -- BOOLEAN
public boolean isBoolean(final String path) {
return isBoolean(getNode(path));
@@ -438,9 +352,7 @@ private Boolean getBoolean(final String path, final
JsonNode node) {
return node.booleanValue();
}
- // ///////////////////////////////////////////////////////////////////////
- // isByte, getByte, asByte
- // ///////////////////////////////////////////////////////////////////////
+ // -- BYTE
/**
* Use {@link #isIntegralNumber(String)} to test if number (it is not
possible to check if a byte, however).
@@ -469,9 +381,7 @@ private Byte getByte(final String path, final JsonNode
node) {
return node.numberValue().byteValue();
}
- // ///////////////////////////////////////////////////////////////////////
- // getShort, asShort
- // ///////////////////////////////////////////////////////////////////////
+ // -- SHORT
/**
* Use {@link #isIntegralNumber(String)} to check if number (it is not
possible to check if a short, however).
@@ -500,9 +410,7 @@ private Short getShort(final String path, final JsonNode
node) {
return node.shortValue();
}
- // ///////////////////////////////////////////////////////////////////////
- // getChar, asChar
- // ///////////////////////////////////////////////////////////////////////
+ // -- CHAR
/**
* Use {@link #isString(String)} to check if string (it is not possible to
check if a character, however).
@@ -534,9 +442,7 @@ private Character getChar(final String path, final JsonNode
node) {
return textValue.charAt(0);
}
- // ///////////////////////////////////////////////////////////////////////
- // isInt, getInt, asInt
- // ///////////////////////////////////////////////////////////////////////
+ // -- INT
public boolean isInt(final String path) {
return isInt(getNode(path));
@@ -576,9 +482,7 @@ private Integer getInt(final String path, final JsonNode
node) {
return node.intValue();
}
- // ///////////////////////////////////////////////////////////////////////
- // isLong, getLong, asLong
- // ///////////////////////////////////////////////////////////////////////
+ // -- LONG
public boolean isLong(final String path) {
return isLong(getNode(path));
@@ -621,9 +525,7 @@ private Long getLong(final String path, final JsonNode
node) {
throw new IllegalArgumentException(formatExMsg(path, "is not a long"));
}
- // ///////////////////////////////////////////////////////////////////////
- // getFloat, asFloat
- // ///////////////////////////////////////////////////////////////////////
+ // -- FLOAT
/**
* Use {@link #isDecimal(String)} to test if a decimal value
@@ -651,9 +553,7 @@ private Float getFloat(final String path, final JsonNode
node) {
return node.floatValue();
}
- // ///////////////////////////////////////////////////////////////////////
- // isDecimal, isDouble, getDouble, asDouble
- // ///////////////////////////////////////////////////////////////////////
+ // -- DECIMAL
public boolean isDecimal(final String path) {
return isDecimal(getNode(path));
@@ -693,9 +593,7 @@ private Double getDouble(final String path, final JsonNode
node) {
return node.doubleValue();
}
- // ///////////////////////////////////////////////////////////////////////
- // isBigInteger, getBigInteger, asBigInteger
- // ///////////////////////////////////////////////////////////////////////
+ // -- BIGINTEGER
public boolean isBigInteger(final String path) {
return isBigInteger(getNode(path));
@@ -792,9 +690,7 @@ private BigInteger getBigInteger(final String path, final
JsonNode node) {
throw new IllegalArgumentException(formatExMsg(path, "is not a
biginteger, is not any other integral number, is not text parseable as a
biginteger"));
}
- // ///////////////////////////////////////////////////////////////////////
- // isBigDecimal, getBigDecimal, asBigDecimal
- // ///////////////////////////////////////////////////////////////////////
+ // -- BIGDECIMAL
public boolean isBigDecimal(final String path) {
return isBigDecimal(getNode(path));
@@ -903,9 +799,7 @@ private BigDecimal getBigDecimal(final String path, final
JsonNode node) {
throw new IllegalArgumentException(formatExMsg(path, "is not a
bigdecimal, is not any other numeric, is not text parseable as a bigdecimal"));
}
- // ///////////////////////////////////////////////////////////////////////
- // getString, isString, asString
- // ///////////////////////////////////////////////////////////////////////
+ // -- STRING
public boolean isString(final String path) {
return isString(getNode(path));
@@ -1073,10 +967,6 @@ private JsonRepresentation getNull(final String path,
final JsonNode node) {
return new JsonRepresentation(node);
}
- // ///////////////////////////////////////////////////////////////////////
- // mapValueAsLink
- // ///////////////////////////////////////////////////////////////////////
-
/**
* Convert a representation that contains a single node representing a link
* into a {@link LinkRepresentation}.
@@ -1089,18 +979,13 @@ public LinkRepresentation mapValueAsLink() {
return getLink(linkPropertyName);
}
- // ///////////////////////////////////////////////////////////////////////
- // asInputStream
- // ///////////////////////////////////////////////////////////////////////
-
+ /**
+ * Returns the underlying JSON (UTF-8 String) as {@link
ByteArrayInputStream}.
+ */
public InputStream asInputStream() {
- return JsonNodeUtils.asInputStream(jsonNode);
+ return new
ByteArrayInputStream(jsonNode.toString().getBytes(StandardCharsets.UTF_8));
}
- // ///////////////////////////////////////////////////////////////////////
- // asArrayNode, asObjectNode
- // ///////////////////////////////////////////////////////////////////////
-
/**
* Convert underlying representation into an array.
*/
@@ -1121,10 +1006,6 @@ protected ObjectNode asObjectNode() {
return (ObjectNode) asJsonNode();
}
- // ///////////////////////////////////////////////////////////////////////
- // asT
- // ///////////////////////////////////////////////////////////////////////
-
/**
* Convenience to simply "downcast".
*
@@ -1141,17 +1022,11 @@ public <T extends JsonRepresentation> T as(final
Class<T> cls) {
}
}
- // ///////////////////////////////////////////////////////////////////////
- // asUrlEncoded
- // ///////////////////////////////////////////////////////////////////////
-
public String asUrlEncoded() {
- return UrlEncodingUtils.urlEncode(asJsonNode());
+ return UrlUtils.urlEncodeUtf8(asJsonNode().toString());
}
- // ///////////////////////////////////////////////////////////////////////
- // mutable (array)
- // ///////////////////////////////////////////////////////////////////////
+ // -- MUTABLE (ARRAY)
public JsonRepresentation arrayAdd(final Object value) {
if (!isArray()) {
@@ -1350,7 +1225,7 @@ public JsonRepresentation mapPut(final String key, final
Object value) {
throw new IllegalStateException("does not represent map");
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
node.set(path.getTail(), value != null ? new POJONode(value) :
NullNode.getInstance());
return this;
}
@@ -1363,7 +1238,7 @@ public JsonRepresentation mapPutJsonRepresentation(final
String key, final JsonR
return this;
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
node.set(path.getTail(), value.asJsonNode());
return this;
}
@@ -1376,7 +1251,7 @@ public JsonRepresentation mapPutString(final String key,
final String value) {
return this;
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
node.put(path.getTail(), value);
return this;
}
@@ -1389,7 +1264,7 @@ public JsonRepresentation mapPutJsonNode(final String
key, final JsonNode value)
return this;
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
node.set(path.getTail(), value);
return this;
}
@@ -1415,7 +1290,7 @@ public JsonRepresentation mapPutInt(final String key,
final int value) {
throw new IllegalStateException("does not represent map");
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
node.put(path.getTail(), value);
return this;
}
@@ -1429,7 +1304,7 @@ public JsonRepresentation mapPutLong(final String key,
final long value) {
throw new IllegalStateException("does not represent map");
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
node.put(path.getTail(), value);
return this;
}
@@ -1443,7 +1318,7 @@ public JsonRepresentation mapPutFloat(final String key,
final float value) {
throw new IllegalStateException("does not represent map");
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
node.put(path.getTail(), value);
return this;
}
@@ -1457,7 +1332,7 @@ public JsonRepresentation mapPutDouble(final String key,
final double value) {
throw new IllegalStateException("does not represent map");
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
node.put(path.getTail(), value);
return this;
}
@@ -1471,7 +1346,7 @@ public JsonRepresentation mapPutBoolean(final String key,
final boolean value) {
throw new IllegalStateException("does not represent map");
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
node.put(path.getTail(), value);
return this;
}
@@ -1493,7 +1368,7 @@ public JsonRepresentation mapPutBigInteger(final String
key, final BigInteger va
throw new IllegalStateException("does not represent map");
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
if (value != null) {
node.put(path.getTail(), value.toString());
} else {
@@ -1519,7 +1394,7 @@ public JsonRepresentation mapPutBigDecimal(final String
key, final BigDecimal va
throw new IllegalStateException("does not represent map");
}
final Path path = Path.parse(key);
- final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(),
path.getHead());
+ final ObjectNode node = walkNodeUpTo(asObjectNode(), path.getHead());
if (value != null) {
node.put(path.getTail(), value.toString());
} else {
@@ -1604,9 +1479,7 @@ public JsonRepresentation setValue(final
JsonRepresentation value) {
}
};
- // ///////////////////////////////////////////////////////////////////////
- // helpers
- // ///////////////////////////////////////////////////////////////////////
+ // -- HELPERS
/**
* A reciprocal of the behaviour of the automatic dereferencing of arrays
@@ -1645,10 +1518,10 @@ private NodeAndFormat getNodeAndFormat(final String
path) {
String format = null;
for (final String key : keys) {
final PathNode pathNode = PathNode.parse(key);
- if (!pathNode.getKey().isEmpty()) {
+ if (!pathNode.key().isEmpty()) {
// grab format (if present) before moving down the path
format = getFormatValueIfAnyFrom(jsonNode);
- jsonNode = jsonNode.path(pathNode.getKey());
+ jsonNode = jsonNode.path(pathNode.key());
} else {
// pathNode is criteria only; don't change jsonNode
}
@@ -1752,4 +1625,40 @@ public String toString() {
return jsonNode.toString();
}
+ // -- UTIL
+
+ /**
+ * Walks the path, ensuring keys exist and are maps, or creating required
+ * maps as it goes.
+ *
+ * <p>For example, if given a list ("a", "b", "c") and starting with an
empty
+ * map, then will create:
+ *
+ * <pre>
+ * {
+ * "a": {
+ * "b: {
+ * "c": {
+ * }
+ * }
+ * }
+ * }
+ * </pre>
+ */
+ private static ObjectNode walkNodeUpTo(ObjectNode node, final List<String>
keys) {
+ for (final String key : keys) {
+ JsonNode jsonNode = node.get(key);
+ if (jsonNode == null) {
+ jsonNode = new ObjectNode(JsonNodeFactory.instance);
+ node.set(key, jsonNode);
+ } else {
+ if (!jsonNode.isObject()) {
+ throw new IllegalArgumentException(String.format("walking
path: '%s', existing key '%s' is not a map", keys, key));
+ }
+ }
+ node = (ObjectNode) jsonNode;
+ }
+ return node;
+ }
+
}
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/LinkRepresentation.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/LinkRepresentation.java
index d10106b2cbb..291807a296f 100644
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/LinkRepresentation.java
+++
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/LinkRepresentation.java
@@ -117,15 +117,9 @@ public int hashCode() {
@Override
public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
final LinkRepresentation other = (LinkRepresentation) obj;
if (getHref() == null) {
if (other.getHref() != null) {
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/RestfulMediaType.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/RestfulMediaType.java
index 397cf69749b..649b5fbaffa 100644
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/RestfulMediaType.java
+++
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/RestfulMediaType.java
@@ -18,12 +18,12 @@
*/
package org.apache.causeway.viewer.restfulobjects.applib;
+import org.springframework.web.bind.annotation.RequestMapping;
+
/**
* Media types including the <tt>profile</tt> parameter.
*
- * <p>
- * Because these values are used in the <tt>@Produces</tt> annotation on the
jax-rs
- * resources, they must be constants and must be strings.
+ * <p> Because these values are used with {@link RequestMapping} annotations,
they must be constant strings.
*
* @see <a
href="http://buzzword.org.uk/2009/draft-inkster-profile-parameter-00.html">buzzword.org.uk</a>
*
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/RestfulResponse.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/RestfulResponse.java
index 8a90069d85d..d1ed806719f 100644
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/RestfulResponse.java
+++
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/RestfulResponse.java
@@ -18,27 +18,11 @@
*/
package org.apache.causeway.viewer.restfulobjects.applib;
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.util.Date;
-import java.util.Map;
-
-//import jakarta.ws.rs.core.MultivaluedMap;
-//import jakarta.ws.rs.core.Response;
-//import jakarta.ws.rs.core.Response.Status;
-//import jakarta.ws.rs.core.Response.Status.Family;
-//import jakarta.ws.rs.core.Response.StatusType;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
-import org.apache.causeway.commons.internal.collections._Maps;
-import org.apache.causeway.viewer.restfulobjects.applib.util.JsonMapper;
import org.apache.causeway.viewer.restfulobjects.applib.util.Parser;
/**
@@ -46,329 +30,26 @@
*/
public class RestfulResponse<T> {
-// public static final class HttpStatusCode {
-//
-// private static final Map<Status, HttpStatusCode> statii =
_Maps.newHashMap();
-// private static final Map<Integer, HttpStatusCode> statusCodes =
_Maps.newHashMap();
-//
-// private static class StatusTypeImpl implements StatusType {
-//
-// private final int statusCode;
-// private final Family family;
-// private final String reasonPhrase;
-//
-// private StatusTypeImpl(final int statusCode, final Family
family, final String reasonPhrase) {
-// this.statusCode = statusCode;
-// this.family = family;
-// this.reasonPhrase = reasonPhrase;
-// }
-//
-// @Override
-// public int getStatusCode() {
-// return statusCode;
-// }
-//
-// @Override
-// public Family getFamily() {
-// return family;
-// }
-//
-// @Override
-// public String getReasonPhrase() {
-// return reasonPhrase;
-// }
-// }
-//
-// public static HttpStatusCode lookup(final int status) {
-// return statusCodes.get(status);
-// }
-//
-// public static Family lookupFamily(final int statusCode) {
-// switch (statusCode / 100) {
-// case 1:
-// return Family.INFORMATIONAL;
-// case 2:
-// return Family.SUCCESSFUL;
-// case 3:
-// return Family.REDIRECTION;
-// case 4:
-// return Family.CLIENT_ERROR;
-// case 5:
-// return Family.SERVER_ERROR;
-// default:
-// return Family.OTHER;
-// }
-// }
-//
-// // public static final int SC_CONTINUE = 100;
-// // public static final int SC_SWITCHING_PROTOCOLS = 101;
-// // public static final int SC_PROCESSING = 102;
-//
-// public static final HttpStatusCode OK = new HttpStatusCode(200,
Status.OK);
-// public static final HttpStatusCode CREATED = new HttpStatusCode(201,
Status.CREATED);
-//
-// // public static final int SC_ACCEPTED = 202;
-// // public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;
-//
-// public static final HttpStatusCode NO_CONTENT = new
HttpStatusCode(204, Status.NO_CONTENT);
-//
-// // public static final int SC_RESET_CONTENT = 205;
-// // public static final int SC_PARTIAL_CONTENT = 206;
-// // public static final int SC_MULTI_STATUS = 207;
-// // public static final int SC_MULTIPLE_CHOICES = 300;
-// // public static final int SC_MOVED_PERMANENTLY = 301;
-// // public static final int SC_MOVED_TEMPORARILY = 302;
-// // public static final int SC_SEE_OTHER = 303;
-// public static final HttpStatusCode NOT_MODIFIED = new
HttpStatusCode(304, Status.BAD_REQUEST);
-//
-// // public static final int SC_NOT_MODIFIED = 304;
-// // public static final int SC_USE_PROXY = 305;
-// // public static final int SC_TEMPORARY_REDIRECT = 307;
-//
-// public static final HttpStatusCode BAD_REQUEST = new
HttpStatusCode(400, Status.BAD_REQUEST);
-// public static final HttpStatusCode UNAUTHORIZED = new
HttpStatusCode(401, Status.UNAUTHORIZED);
-//
-// // public static final int SC_PAYMENT_REQUIRED = 402;
-// public static final HttpStatusCode FORBIDDEN = new
HttpStatusCode(403, Status.FORBIDDEN);
-//
-// public static final HttpStatusCode NOT_FOUND = new
HttpStatusCode(404, Status.NOT_FOUND);
-// public static final HttpStatusCode METHOD_NOT_ALLOWED = new
HttpStatusCode(405, new StatusTypeImpl(405, Family.CLIENT_ERROR, "Method not
allowed"));
-// public static final HttpStatusCode NOT_ACCEPTABLE = new
HttpStatusCode(406, Status.NOT_ACCEPTABLE);
-//
-// // public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
-// // public static final int SC_REQUEST_TIMEOUT = 408;
-//
-// public static final HttpStatusCode CONFLICT = new
HttpStatusCode(409, Status.CONFLICT);
-//
-// // public static final int SC_GONE = 410;
-// // public static final int SC_LENGTH_REQUIRED = 411;
-// // public static final int SC_PRECONDITION_FAILED = 412;
-// // public static final int SC_REQUEST_TOO_LONG = 413;
-// // public static final int SC_REQUEST_URI_TOO_LONG = 414;
-// // public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
-//
-// public static final HttpStatusCode UNSUPPORTED_MEDIA_TYPE = new
HttpStatusCode(415, Status.UNSUPPORTED_MEDIA_TYPE);
-//
-// // public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
-// // public static final int SC_EXPECTATION_FAILED = 417;
-// // public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419;
-//
-// public static final HttpStatusCode METHOD_FAILURE = new
HttpStatusCode(420, new StatusTypeImpl(420, Family.CLIENT_ERROR, "Method
failure"));
-//
-// // public static final int SC_UNPROCESSABLE_ENTITY = 422;
-// public static final HttpStatusCode VALIDATION_FAILED = new
HttpStatusCode(422, new StatusTypeImpl(422, Family.CLIENT_ERROR, "Validation
failed"));
-//
-// // public static final int SC_LOCKED = 423;
-// // public static final int SC_FAILED_DEPENDENCY = 424;
-//
-// public static final HttpStatusCode PRECONDITION_HEADER_MISSING = new
HttpStatusCode(428, new StatusTypeImpl(428, Family.CLIENT_ERROR, "Precondition
header missing"));
-//
-// public static final HttpStatusCode INTERNAL_SERVER_ERROR = new
HttpStatusCode(500, Status.INTERNAL_SERVER_ERROR);
-// public static final HttpStatusCode NOT_IMPLEMENTED = new
HttpStatusCode(501, new StatusTypeImpl(501, Family.SERVER_ERROR, "Not
implemented"));
-//
-// // public static final int SC_BAD_GATEWAY = 502;
-// // public static final int SC_SERVICE_UNAVAILABLE = 503;
-// // public static final int SC_GATEWAY_TIMEOUT = 504;
-// // public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
-// // public static final int SC_INSUFFICIENT_STORAGE = 507;
-//
-// public static final HttpStatusCode statusFor(final int statusCode) {
-// final HttpStatusCode httpStatusCode =
statusCodes.get(statusCode);
-// if (httpStatusCode != null) {
-// return httpStatusCode;
-// }
-// return statusForSynchronized(statusCode);
-// }
-//
-// public static final HttpStatusCode statusFor(final Status status) {
-// return statii.get(status);
-// }
-//
-// private static final synchronized HttpStatusCode
statusForSynchronized(final int statusCode) {
-// HttpStatusCode httpStatusCode = statusCodes.get(statusCode);
-// if (httpStatusCode != null) {
-// return httpStatusCode;
-// }
-// httpStatusCode = new HttpStatusCode(statusCode, null);
-// statusCodes.put(statusCode, httpStatusCode);
-// return httpStatusCode;
-// }
-//
-// private final int statusCode;
-// private final Family family;
-// private final StatusType jaxrsStatusType;
-//
-// private HttpStatusCode(final int statusCode, final StatusType
status) {
-// this.statusCode = statusCode;
-// this.jaxrsStatusType = status;
-// family = lookupFamily(statusCode);
-// statusCodes.put(statusCode, this);
-// }
-//
-// public int getStatusCode() {
-// return statusCode;
-// }
-//
-// public StatusType getJaxrsStatusType() {
-// return jaxrsStatusType;
-// }
-//
-// public Family getFamily() {
-// return family;
-// }
-//
-// @Override
-// public int hashCode() {
-// return statusCode;
-// }
-//
-// @Override
-// public boolean equals(final Object obj) {
-// if (this == obj) {
-// return true;
-// }
-// if (obj == null) {
-// return false;
-// }
-// if (getClass() != obj.getClass()) {
-// return false;
-// }
-// final HttpStatusCode other = (HttpStatusCode) obj;
-// if (statusCode != other.statusCode) {
-// return false;
-// }
-// return true;
-// }
-//
-// @Override
-// public String toString() {
-// return "HttpStatusCode " + statusCode + ", " + family;
-// }
-//
-// }
-
- public static class Header<X> {
+ public record Header<X>(
+ String name,
+ Parser<X> parser) {
- public static final Header<String> WARNING = new
Header<String>("Warning", warningParser());
+ public static final Header<String> WARNING = new
Header<String>("Warning", Parser.forWarning());
public static final Header<Date> LAST_MODIFIED = new
Header<Date>("Last-Modified", Parser.forDate());
public static final Header<CacheControl> CACHE_CONTROL = new
Header<CacheControl>("Cache-Control", Parser.forCacheControl());
public static final Header<MediaType> CONTENT_TYPE = new
Header<MediaType>("Content-Type", Parser.forMediaType());
public static final Header<Integer> CONTENT_LENGTH = new
Header<Integer>("Content-Length", Parser.forInteger());
- public static final Header<String> ETAG = new Header<String>("ETag",
Parser.forETag());
-
- private final String name;
- private final Parser<X> parser;
-
- private Header(final String name, final Parser<X> parser) {
- this.name = name;
- this.parser = parser;
- }
-
- public String getName() {
- return name;
- }
+ //public static final Header<String> ETAG = new Header<String>("ETag",
Parser.forETag());
public X parse(final String value) {
- return value != null? parser.valueOf(value): null;
+ return value != null ? parser.valueOf(value): null;
}
public String render(X message) {
return parser.asString(message);
}
- private static Parser<String> warningParser() {
- return new Parser<String>(){
- private static final String PREFIX = "199 RestfulObjects ";
-
- @Override
- public String valueOf(String str) {
- return stripPrefix(str, PREFIX);
- }
-
- @Override
- public String asString(String str) {
- return PREFIX + str;
- }
- private String stripPrefix(String str, String prefix) {
- return str.startsWith(prefix) ?
str.substring(prefix.length()) : str;
- }
- };
- }
-
- }
-
-// private final Response response;
-// private final HttpStatusCode httpStatusCode;
- //private final Class<T> returnType;
- private T entity;
-
-// @SuppressWarnings({ "rawtypes", "unchecked" })
-// public static RestfulResponse<JsonRepresentation> of(final Response
response) {
-// final MediaType jaxRsMediaType = getHeader(response,
Header.CONTENT_TYPE);
-// final RepresentationType representationType =
RepresentationType.lookup(jaxRsMediaType);
-// final Class<? extends JsonRepresentation> returnType =
representationType.getRepresentationClass();
-// return new RestfulResponse(response, returnType);
-// }
-//
-// @SuppressWarnings("unchecked")
-// public static <T extends JsonRepresentation> RestfulResponse<T>
ofT(final Response response) {
-// return (RestfulResponse<T>) of(response);
-// }
-//
-// private RestfulResponse(final Response response, final Class<T>
returnType) {
-// this.response = response;
-// this.httpStatusCode = HttpStatusCode.statusFor(response.getStatus());
-// this.returnType = returnType;
-// }
-//
-// public HttpStatusCode getStatus() {
-// return httpStatusCode;
-// }
-
-// public T getEntity() throws JsonParseException, JsonMappingException,
IOException {
-// if(entity == null) {
-// // previously this was good enough, but no longer it seems
-// //entity = JsonMapper.instance().read(response, returnType);
-//
-// // instead, we do it manually
-// final JsonNode jsonNode = JsonMapper.instance().read(response,
JsonNode.class);
-// try {
-// final Constructor<T> constructor =
returnType.getConstructor(JsonNode.class);
-// entity = constructor.newInstance(jsonNode);
-// } catch (NoSuchMethodException | InvocationTargetException |
IllegalAccessException | InstantiationException e) {
-// throw new RuntimeException(e);
-// }
-// }
-// return entity;
-// }
-
-// public <V> V getHeader(final Header<V> header) {
-// return getHeader(response, header);
-// }
-//
-// private static <V> V getHeader(final Response response, final Header<V>
header) {
-// final MultivaluedMap<String, Object> metadata =
response.getMetadata();
-// // always returns a String
-// final String value = (String) metadata.getFirst(header.getName());
-// return header.parse(value);
-// }
-
- /**
- * Convenience that recasts this response as wrapping some other
- * representation.
- *
- * <p>
- * This would typically be as the results of a content type being an
- * error rather than a representation returned on success.
- */
- @SuppressWarnings("unchecked")
- public <Q extends JsonRepresentation> RestfulResponse<Q> wraps(Class<Q>
cls) {
- return (RestfulResponse<Q>) this;
}
-// @Override
-// public String toString() {
-// return "RestfulResponse [httpStatusCode=" + httpStatusCode + "]";
-// }
}
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/JsonMapper.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/JsonMapper.java
index 80245e8c95e..dc32ec04907 100644
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/JsonMapper.java
+++
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/JsonMapper.java
@@ -32,7 +32,6 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@@ -44,46 +43,57 @@
/**
* @since 1.x {@index}
*/
-public final class JsonMapper {
-
-// public static String getEntityAsStringFrom(final Response response) {
-//
-// final Object result = response.getEntity();
-//
-// if(result == null)
-// return null;
-//
-// if(result instanceof String) {
-// return (String) result;
-// }
-//
-// // TODO [andi-huber] just a wild guess
-// return response.readEntity(String.class);
-//
-// // legacy code ...
-// // final ClientResponse<?> clientResponse = (ClientResponse<?>)
response;
-// // return clientResponse.getEntity(String.class);
-// }
+public record JsonMapper(
+ ObjectMapper objectMapper,
+ PrettyPrinting prettyPrinting) {
public enum PrettyPrinting {
ENABLE,
DISABLE
}
+ /**
+ * Returns a {@link
org.apache.causeway.viewer.restfulobjects.applib.util.JsonMapper.PrettyPrinting#ENABLE
pretty-printing enabled} JSON mapper.
+ */
+ public static final JsonMapper instance() {
+ return instance(PrettyPrinting.ENABLE);
+ }
+
+ public static final JsonMapper instance(final PrettyPrinting
prettyPrinting) {
+ return instanceByConfig.computeIfAbsent(prettyPrinting,
JsonMapper::new);
+ }
+
+ public JsonRepresentation read(final String json) throws
JsonParseException, JsonMappingException, IOException {
+ return read(json, JsonRepresentation.class);
+ }
+
+ public <T> T read(final String json, final Class<T> requiredType) throws
JsonParseException, JsonMappingException, IOException {
+ return objectMapper.readValue(json, requiredType);
+ }
+
+ public String write(final Object object) throws JsonGenerationException,
JsonMappingException, IOException {
+ return objectMapper.writeValueAsString(object);
+ }
+
+ // -- HELPER
+
+ // non canonical constructor
+ private JsonMapper(final PrettyPrinting prettyPrinting) {
+ this(createObjectMapper(prettyPrinting), prettyPrinting);
+ }
+
private static final class JsonRepresentationDeserializer extends
JsonDeserializer<JsonRepresentation> {
@Override
public JsonRepresentation deserialize(final JsonParser jp, final
DeserializationContext ctxt) throws IOException {
- JsonNode node = jp.getCodec().readTree(jp);
- return new JsonRepresentation(node);
+ return new JsonRepresentation(jp.getCodec().readTree(jp));
}
}
private static final class JsonRepresentationSerializer extends
JsonSerializer<Object> {
@Override
- public void serialize(final Object value, final JsonGenerator jgen,
final SerializerProvider provider) throws IOException, JsonProcessingException {
- final JsonRepresentation jsonRepresentation = (JsonRepresentation)
value;
- final JsonNode jsonNode = jsonRepresentation.asJsonNode();
- jgen.writeTree(jsonNode);
+ public void serialize(final Object value, final JsonGenerator jgen,
final SerializerProvider provider)
+ throws IOException, JsonProcessingException {
+ jgen.writeTree(((JsonRepresentation) value).asJsonNode());
}
}
@@ -103,49 +113,4 @@ private static ObjectMapper createObjectMapper(final
PrettyPrinting prettyPrinti
private static Map<PrettyPrinting, JsonMapper> instanceByConfig = new
ConcurrentHashMap<>();
- /**
- * Returns a {@link
org.apache.causeway.viewer.restfulobjects.applib.util.JsonMapper.PrettyPrinting#ENABLE
pretty-printing enabled} JSON mapper.
- */
- public static final JsonMapper instance() {
- return instance(PrettyPrinting.ENABLE);
- }
-
- public static final JsonMapper instance(final PrettyPrinting
prettyPrinting) {
- final JsonMapper jsonMapper = instanceByConfig.get(prettyPrinting);
- if (jsonMapper != null) {
- return jsonMapper;
- }
- // there could be a race-condition here, but it doesn't matter; last
one wins.
- final JsonMapper mapper = new JsonMapper(prettyPrinting);
- instanceByConfig.put(prettyPrinting, mapper);
-
- return mapper;
- }
-
- private final ObjectMapper objectMapper;
-
- private JsonMapper(final PrettyPrinting prettyPrinting) {
- objectMapper = createObjectMapper(prettyPrinting);
- }
-
- public JsonRepresentation read(final String json) throws
JsonParseException, JsonMappingException, IOException {
- return read(json, JsonRepresentation.class);
- }
-
- public <T> T read(final String json, final Class<T> requiredType) throws
JsonParseException, JsonMappingException, IOException {
- return objectMapper.readValue(json, requiredType);
- }
-
-// public <T> T read(final Response response, final Class<T> requiredType)
throws JsonParseException, JsonMappingException, IOException {
-// final String entity = getEntityAsStringFrom(response);
-// if (entity == null) {
-// return null;
-// }
-// return read(entity, requiredType);
-// }
-
- public String write(final Object object) throws JsonGenerationException,
JsonMappingException, IOException {
- return objectMapper.writeValueAsString(object);
- }
-
}
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/JsonNodeUtils.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/JsonNodeUtils.java
deleted file mode 100644
index ef908183f68..00000000000
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/JsonNodeUtils.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.applib.util;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import org.apache.causeway.viewer.restfulobjects.applib.JsonRepresentation;
-
-/**
- * @since 1.x {@index}
- */
-public class JsonNodeUtils {
-
- private JsonNodeUtils() {
- }
-
- public static InputStream asInputStream(final JsonNode jsonNode) {
- final String jsonStr = jsonNode.toString();
- final byte[] bytes = jsonStr.getBytes(StandardCharsets.UTF_8);
- return new ByteArrayInputStream(bytes);
- }
-
- public static InputStream asInputStream(final JsonRepresentation
jsonRepresentation) {
- final String jsonStr = jsonRepresentation.toString();
- final byte[] bytes = jsonStr.getBytes(StandardCharsets.UTF_8);
- return new ByteArrayInputStream(bytes);
- }
-
- /**
- * Walks the path, ensuring keys exist and are maps, or creating required
- * maps as it goes.
- *
- * <p>
- * For example, if given a list ("a", "b", "c") and starting with an empty
- * map, then will create:
- *
- * <pre>
- * {
- * "a": {
- * "b: {
- * "c": {
- * }
- * }
- * }
- * }
- */
- public static ObjectNode walkNodeUpTo(ObjectNode node, final List<String>
keys) {
- for (final String key : keys) {
- JsonNode jsonNode = node.get(key);
- if (jsonNode == null) {
- jsonNode = new ObjectNode(JsonNodeFactory.instance);
- node.set(key, jsonNode);
- } else {
- if (!jsonNode.isObject()) {
- throw new IllegalArgumentException(String.format("walking
path: '%s', existing key '%s' is not a map", keys, key));
- }
- }
- node = (ObjectNode) jsonNode;
- }
- return node;
- }
-
-}
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Links.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Links.java
deleted file mode 100644
index 0059e92e9d2..00000000000
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Links.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.applib.util;
-
-import org.apache.causeway.applib.layout.links.Link;
-import org.apache.causeway.viewer.restfulobjects.applib.Rel;
-
-import lombok.experimental.UtilityClass;
-
-@UtilityClass
-public class Links {
-
- public Link get(
- final Rel rel,
- final String href,
- final String type) {
- return new Link(rel.getName(), "GET", href, type);
- }
-
-}
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/MediaTypes.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/MediaTypes.java
deleted file mode 100644
index 9395150b876..00000000000
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/MediaTypes.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.applib.util;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.springframework.http.MediaType;
-
-import org.apache.causeway.commons.internal.base._Strings;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * @since 1.x {@index}
- */
-@UtilityClass
-public class MediaTypes {
-
- /**
- * Same as {@code MediaType.valueOf(type)}, but with fallback in case
{@code MediaType.valueOf(type)}
- * throws an IllegalArgumentException.
- * <p>
- * The fallback is to retry with some special characters replaces in
String {@code type}.
- *
- * @param type
- */
- public MediaType parse(String type) {
-
- if(type==null)
- return MediaType.valueOf(null);
-
- try {
-
- return MediaType.valueOf(type);
-
- } catch (IllegalArgumentException e) {
-
- List<String> chunks = _Strings.splitThenStream(type, ";")
- .collect(Collectors.toList());
-
- final StringBuilder sb = new StringBuilder();
- sb.append(chunks.get(0));
-
- if(chunks.size()>1) {
- chunks.stream()
- .skip(1)
- .map(chunk->chunk.replace(":", "..").replace("/", "."))
- .forEach(chunk->sb.append(';').append(chunk));
- }
-
- return MediaType.valueOf(sb.toString());
-
- }
-
- }
-
-}
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Parser.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Parser.java
index 38b7246ddf1..e7555d634df 100644
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Parser.java
+++
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Parser.java
@@ -49,18 +49,15 @@ default T valueOf(final JsonRepresentation
jsonRepresentation) {
return valueOf(jsonRepresentation.asString());
}
- default JsonRepresentation asJsonRepresentation(final T t) {
- return JsonRepresentation.newMap("dummy",
asString(t)).getRepresentation("dummy");
- }
-
// -- FACTORIES
static Parser<Boolean> forBoolean() { return new Parsers.BooleanParser(); }
static Parser<Date> forDate() { return new Parsers.DateParser(); }
static Parser<Integer> forInteger() { return new Parsers.IntegerParser(); }
static Parser<String> forString() { return new Parsers.StringParser(); }
+ static Parser<String> forWarning() { return new Parsers.WarningParser(); }
static Parser<MediaType> forMediaType() { return new
Parsers.MediaTypeParser(); }
- static Parser<String> forETag() { return new Parsers.ETagParser(); }
+ //static Parser<String> forETag() { return new Parsers.ETagParser(); }
static Parser<CacheControl> forCacheControl() { return new
Parsers.CacheControlParser(); }
static Parser<List<String>> forListOfStrings() { return new
Parsers.ListOfStringsParser(); }
static Parser<List<List<String>>> forListOfListOfStrings() { return new
Parsers.ListOfListOfStringsParser(); }
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Parsers.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Parsers.java
index 4ada8408fe4..b06a0226885 100644
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Parsers.java
+++
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/Parsers.java
@@ -40,9 +40,9 @@
import lombok.experimental.UtilityClass;
@UtilityClass
-public class Parsers {
+class Parsers {
- public record BooleanParser() implements Parser<Boolean> {
+ record BooleanParser() implements Parser<Boolean> {
@Override public Boolean valueOf(final String str) {
if (str == null) return null;
return "yes".equalsIgnoreCase(str) || "true".equalsIgnoreCase(str)
@@ -54,7 +54,7 @@ public record BooleanParser() implements Parser<Boolean> {
}
}
- public record IntegerParser() implements Parser<Integer> {
+ record IntegerParser() implements Parser<Integer> {
@Override public Integer valueOf(final String str) {
if (str == null) return null;
return Integer.valueOf(str);
@@ -64,12 +64,12 @@ public record IntegerParser() implements Parser<Integer> {
}
}
- public record StringParser() implements Parser<String> {
+ record StringParser() implements Parser<String> {
@Override public String valueOf(final String str) { return str; }
@Override public String asString(final String t) { return t; }
}
- public record DateParser() implements Parser<Date> {
+ record DateParser() implements Parser<Date> {
final static SimpleDateFormat RFC1123_DATE_FORMAT = new
SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z");
@Override public Date valueOf(final String str) {
if (!StringUtils.hasLength(str)) return null;
@@ -86,7 +86,7 @@ public record DateParser() implements Parser<Date> {
}
}
- public record MediaTypeParser() implements Parser<MediaType> {
+ record MediaTypeParser() implements Parser<MediaType> {
@Override public MediaType valueOf(final String str) {
if (!StringUtils.hasLength(str)) return null;
return MediaType.valueOf(str);
@@ -96,9 +96,48 @@ public record MediaTypeParser() implements Parser<MediaType>
{
? t.toString()
: null;
}
+//legacy utility code - perhaps not needed any more
+// /**
+// * Same as {@code MediaType.valueOf(type)}, but with fallback in
case {@code MediaType.valueOf(type)}
+// * throws an IllegalArgumentException.
+// * <p>
+// * The fallback is to retry with some special characters replaces in
String {@code type}.
+// *
+// * @param type
+// */
+// private MediaType parse(String type) {
+//
+// if(type==null) return null;
+//
+// try {
+//
+// return MediaType.valueOf(type);
+//
+// } catch (IllegalArgumentException e) {
+//
+// List<String> chunks = _Strings.splitThenStream(type, ";")
+// .collect(Collectors.toList());
+//
+// final StringBuilder sb = new StringBuilder();
+// sb.append(chunks.get(0));
+//
+// if(chunks.size()>1) {
+// chunks.stream()
+// .skip(1)
+// .map(chunk->chunk.replace(":", "..").replace("/", "."))
+// .forEach(chunk->sb.append(';').append(chunk));
+// }
+//
+// return MediaType.valueOf(sb.toString());
+//
+// }
+//
+// }
}
- public record CacheControlParser() implements Parser<CacheControl> {
+
+
+ record CacheControlParser() implements Parser<CacheControl> {
@Override public CacheControl valueOf(String str) {
//Cache-Control: no-cache, no-store, max-age=3600
var directives =
_Strings.splitThenStream(str.toLowerCase(Locale.US), ",")
@@ -115,7 +154,7 @@ public record CacheControlParser() implements
Parser<CacheControl> {
builder =
CacheControl.maxAge(Integer.parseInt(directive.substring("max-age=".length())),
TimeUnit.SECONDS);
}
}
- };
+ }
}
// modifications
for(String directive : directives) {
@@ -133,7 +172,7 @@ public record CacheControlParser() implements
Parser<CacheControl> {
case "proxy-revalidate" -> builder =
builder.proxyRevalidate();
case "immutable" -> builder = builder.immutable();
default -> {}
- };
+ }
}
return builder;
}
@@ -142,16 +181,16 @@ public record CacheControlParser() implements
Parser<CacheControl> {
}
}
- public record ETagParser() implements Parser<String> {
- @Override public String valueOf(String str) {
- return null;
- }
- @Override public String asString(String t) {
- return null;
- }
- }
+// record ETagParser() implements Parser<String> {
+// @Override public String valueOf(String str) {
+// return null;
+// }
+// @Override public String asString(String t) {
+// return null;
+// }
+// }
- public record ListOfStringsParser() implements Parser<List<String>> {
+ record ListOfStringsParser() implements Parser<List<String>> {
@Override public List<String> valueOf(final List<String> strings) {
if (strings == null) return Collections.emptyList();
if (strings.size() == 1) {
@@ -181,7 +220,7 @@ public record ListOfStringsParser() implements
Parser<List<String>> {
}
}
- public record ListOfListOfStringsParser() implements
Parser<List<List<String>>> {
+ record ListOfListOfStringsParser() implements Parser<List<List<String>>> {
@Override public List<List<String>> valueOf(final List<String> str) {
if (str == null || str.size() == 0) return null;
final List<List<String>> listOfLists = _Lists.newArrayList();
@@ -207,7 +246,7 @@ public record ListOfListOfStringsParser() implements
Parser<List<List<String>>>
}
}
- public record ArrayOfStringsParser() implements Parser<String[]> {
+ record ArrayOfStringsParser() implements Parser<String[]> {
@Override public String[] valueOf(final List<String> strings) {
if (strings == null) return _Constants.emptyStringArray;
if (strings.size() == 1) {
@@ -236,7 +275,7 @@ public record ArrayOfStringsParser() implements
Parser<String[]> {
}
}
- public record ListOfMediaTypesParser() implements Parser<List<MediaType>> {
+ record ListOfMediaTypesParser() implements Parser<List<MediaType>> {
@Override public List<MediaType> valueOf(final String str) {
if (str == null) return Collections.emptyList();
return _Strings.splitThenStream(str, ",")
@@ -250,4 +289,17 @@ public record ListOfMediaTypesParser() implements
Parser<List<MediaType>> {
}
}
+ record WarningParser() implements Parser<String> {
+ private static final String PREFIX = "199 RestfulObjects ";
+ @Override public String valueOf(String str) {
+ return stripPrefix(str, PREFIX);
+ }
+ @Override public String asString(String str) {
+ return PREFIX + str;
+ }
+ private String stripPrefix(String str, String prefix) {
+ return str.startsWith(prefix) ? str.substring(prefix.length()) :
str;
+ }
+ }
+
}
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/PathNode.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/PathNode.java
index d493bf71130..305373c8fcf 100644
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/PathNode.java
+++
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/PathNode.java
@@ -34,13 +34,16 @@
/**
* @since 1.x {@index}
*/
-public class PathNode {
+public record PathNode(
+ String key,
+ Map<String, String> criteria
+ ) {
private static final Pattern NODE =
Pattern.compile("^([^\\[]*)(\\[(.+)\\])?$");
private static final Pattern WHITESPACE = Pattern.compile("\\s+");
private static final Pattern LIST_CRITERIA_SYNTAX =
Pattern.compile("^([^=]+)=(.+)$");
- public static final PathNode NULL = new PathNode("", Collections.<String,
String> emptyMap());
+ public static final PathNode NULL = new PathNode("",
Collections.emptyMap());
public static List<String> split(String path) {
List<String> parts = _Lists.newArrayList();
@@ -103,31 +106,20 @@ public static PathNode parse(final String path) {
return new PathNode(key, criteria);
}
- private final String key;
- private final Map<String, String> criteria;
-
- private PathNode(final String key, final Map<String, String> criteria) {
+ public PathNode(final String key, final Map<String, String> criteria) {
this.key = key;
this.criteria = Collections.unmodifiableMap(criteria);
}
- public String getKey() {
- return key;
- }
-
- public Map<String, String> getCriteria() {
- return criteria;
- }
-
public boolean hasCriteria() {
- return !getCriteria().isEmpty();
+ return criteria.isEmpty();
}
public boolean matches(final JsonRepresentation repr) {
if (!repr.isMap()) {
return false;
}
- for (final Map.Entry<String, String> criterium :
getCriteria().entrySet()) {
+ for (final Map.Entry<String, String> criterium : criteria.entrySet()) {
String requiredValue = criterium.getValue();
if(requiredValue != null) {
// list syntax
@@ -167,12 +159,9 @@ public int hashCode() {
@Override
public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
PathNode other = (PathNode) obj;
if (key == null) {
if (other.key != null)
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/UrlEncodingUtils.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/UrlEncodingUtils.java
deleted file mode 100644
index 595c321bacb..00000000000
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/util/UrlEncodingUtils.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.applib.util;
-
-import java.util.Arrays;
-import java.util.List;
-
-import com.fasterxml.jackson.databind.JsonNode;
-
-import org.apache.causeway.commons.internal.collections._Lists;
-import org.apache.causeway.commons.io.UrlUtils;
-import org.apache.causeway.viewer.restfulobjects.applib.JsonRepresentation;
-
-import lombok.experimental.UtilityClass;
-
-/**
- * @since 1.x {@index}
- */
-@UtilityClass
-public final class UrlEncodingUtils {
-
- public String urlDecode(final String string) {
- return UrlUtils.urlDecodeUtf8(string);
- }
-
- public List<String> urlDecode(final List<String> values) {
- return _Lists.map(values, UrlUtils::urlDecodeUtf8);
- }
-
- public String[] urlDecode(final String[] values) {
- final List<String> asList = Arrays.asList(values);
- return urlDecode(asList).toArray(new String[] {});
- }
-
- public String urlEncode(final JsonNode jsonNode) {
- return urlEncode(jsonNode.toString());
- }
-
- public String urlEncode(final JsonRepresentation jsonRepresentation ) {
- return urlEncode(jsonRepresentation.toString());
- }
-
- public String urlEncode(final String str) {
- return UrlUtils.urlEncodeUtf8(str);
- }
-
-}
diff --git
a/viewers/restfulobjects/applib/src/test/java/org/apache/causeway/viewer/restfulobjects/applib/util/PathNodeTest_parse.java
b/viewers/restfulobjects/applib/src/test/java/org/apache/causeway/viewer/restfulobjects/applib/util/PathNodeTest_parse.java
index 57afcbdfbac..41f530c6f3e 100644
---
a/viewers/restfulobjects/applib/src/test/java/org/apache/causeway/viewer/restfulobjects/applib/util/PathNodeTest_parse.java
+++
b/viewers/restfulobjects/applib/src/test/java/org/apache/causeway/viewer/restfulobjects/applib/util/PathNodeTest_parse.java
@@ -30,15 +30,15 @@ class PathNodeTest_parse {
@Test
public void simple() throws Exception {
final PathNode node = PathNode.parse("foo");
- assertThat(node.getKey(), is("foo"));
- assertThat(node.getCriteria().isEmpty(), is(true));
+ assertThat(node.key(), is("foo"));
+ assertThat(node.criteria().isEmpty(), is(true));
}
@Test
public void oneCriterium() throws Exception {
final PathNode node = PathNode.parse("foo[bar=coz]");
- assertThat(node.getKey(), is("foo"));
- final Map<String, String> criteria = node.getCriteria();
+ assertThat(node.key(), is("foo"));
+ final Map<String, String> criteria = node.criteria();
assertThat(criteria.isEmpty(), is(false));
assertThat(criteria.size(), is(1));
assertThat(criteria.get("bar"), is("coz"));
@@ -47,8 +47,8 @@ public void oneCriterium() throws Exception {
@Test
public void moreThanOneCriterium() throws Exception {
final PathNode node = PathNode.parse("foo[bar=coz dat=ein]");
- assertThat(node.getKey(), is("foo"));
- final Map<String, String> criteria = node.getCriteria();
+ assertThat(node.key(), is("foo"));
+ final Map<String, String> criteria = node.criteria();
assertThat(criteria.isEmpty(), is(false));
assertThat(criteria.size(), is(2));
assertThat(criteria.get("bar"), is("coz"));
@@ -58,8 +58,8 @@ public void moreThanOneCriterium() throws Exception {
@Test
public void whiteSpace() throws Exception {
final PathNode node = PathNode.parse("foo[bar=coz\tdat=ein]");
- assertThat(node.getKey(), is("foo"));
- final Map<String, String> criteria = node.getCriteria();
+ assertThat(node.key(), is("foo"));
+ final Map<String, String> criteria = node.criteria();
assertThat(criteria.isEmpty(), is(false));
assertThat(criteria.size(), is(2));
assertThat(criteria.get("bar"), is("coz"));
diff --git a/viewers/restfulobjects/client/src/main/java/module-info.java
b/viewers/restfulobjects/client/src/main/java/module-info.java
index f376a27cb48..b586a4ec108 100644
--- a/viewers/restfulobjects/client/src/main/java/module-info.java
+++ b/viewers/restfulobjects/client/src/main/java/module-info.java
@@ -17,19 +17,20 @@
* under the License.
*/
module org.apache.causeway.viewer.restfulobjects.client {
- exports org.apache.causeway.viewer.restfulobjects.client.log;
exports org.apache.causeway.viewer.restfulobjects.client;
exports org.apache.causeway.viewer.restfulobjects.client.auth;
exports org.apache.causeway.viewer.restfulobjects.client.auth.basic;
exports org.apache.causeway.viewer.restfulobjects.client.auth.oauth2;
exports org.apache.causeway.viewer.restfulobjects.client.auth.oauth2.azure;
+ exports org.apache.causeway.viewer.restfulobjects.client.log;
+
+ requires static lombok;
requires com.fasterxml.jackson.core;
requires com.fasterxml.jackson.databind;
requires jakarta.annotation;
requires jakarta.ws.rs;
requires jakarta.xml.bind;
- requires static lombok;
requires transitive org.apache.causeway.applib;
requires transitive org.apache.causeway.commons;
requires transitive org.apache.causeway.viewer.restfulobjects.applib;
diff --git
a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/exhandling/ExceptionResponseFactory.java
b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/exhandling/ExceptionResponseFactory.java
index bca6eee8734..e53c51598b8 100644
---
a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/exhandling/ExceptionResponseFactory.java
+++
b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/exhandling/ExceptionResponseFactory.java
@@ -72,7 +72,7 @@ private ResponseEntity<Object> buildResponse(
var builder = ResponseEntity.status(httpStatus);
if (message != null) {
- builder = builder.header(RestfulResponse.Header.WARNING.getName(),
RestfulResponse.Header.WARNING.render(message));
+ builder = builder.header(RestfulResponse.Header.WARNING.name(),
RestfulResponse.Header.WARNING.render(message));
}
// hmm; the mediaType doesn't seem to be specified in the RO spec
@@ -137,7 +137,7 @@ private ResponseEntity<Object> buildResponse(
final String message = exceptionPojo.message();
if (message != null) {
- builder = builder.header(RestfulResponse.Header.WARNING.getName(),
RestfulResponse.Header.WARNING.render(message));
+ builder = builder.header(RestfulResponse.Header.WARNING.name(),
RestfulResponse.Header.WARNING.render(message));
}
return builder
diff --git
a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/service/valuerender/JsonValueEncoderServiceDefault.java
b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/service/valuerender/JsonValueEncoderServiceDefault.java
index 3a6af73678a..74829d3aaf1 100644
---
a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/service/valuerender/JsonValueEncoderServiceDefault.java
+++
b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/service/valuerender/JsonValueEncoderServiceDefault.java
@@ -61,12 +61,10 @@
@Slf4j
public class JsonValueEncoderServiceDefault implements JsonValueEncoderService
{
- private final SpecificationLoader specificationLoader;
private final Map<Class<?>, JsonValueConverter> converterByClass;
@Inject
public JsonValueEncoderServiceDefault(final SpecificationLoader
specificationLoader) {
- this.specificationLoader = specificationLoader;
this.converterByClass = _JsonValueConverters.byClass();
}
diff --git
a/viewers/restfulobjects/rendering/src/test/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext_getArg_Test.java
b/viewers/restfulobjects/rendering/src/test/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext_getArg_Test.java
index 115a4f2232c..d4585cf1ef4 100644
---
a/viewers/restfulobjects/rendering/src/test/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext_getArg_Test.java
+++
b/viewers/restfulobjects/rendering/src/test/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext_getArg_Test.java
@@ -41,8 +41,6 @@
//import
org.apache.causeway.core.security.authentication.manager.AuthenticationManager;
import org.apache.causeway.viewer.restfulobjects.applib.JsonRepresentation;
import
org.apache.causeway.viewer.restfulobjects.applib.RestfulRequest.RequestParameter;
-import org.apache.causeway.viewer.restfulobjects.applib.util.UrlEncodingUtils;
-import
org.apache.causeway.viewer.restfulobjects.rendering.context.ResourceContext;
class ResourceContext_getArg_Test {
@@ -99,7 +97,7 @@ void setUp() throws Exception {
@Test
void whenArgExists() throws Exception {
- final String queryString =
UrlEncodingUtils.urlEncode(JsonRepresentation.newMap("x-ro-page",
"123").asJsonNode());
+ final String queryString = JsonRepresentation.newMap("x-ro-page",
"123").asUrlEncoded();
resourceContext = ResourceContext.forTesting(queryString,
mockHttpServletRequest);
final Integer arg =
ResourceContext.arg(resourceContext.queryStringAsJsonRepr(),
RequestParameter.PAGE);
assertThat(arg, equalTo(123));
@@ -107,7 +105,7 @@ void whenArgExists() throws Exception {
@Test
void whenArgDoesNotExist() throws Exception {
- final String queryString =
UrlEncodingUtils.urlEncode(JsonRepresentation.newMap("xxx",
"123").asJsonNode());
+ final String queryString = JsonRepresentation.newMap("xxx",
"123").asUrlEncoded();
resourceContext = ResourceContext.forTesting(queryString,
mockHttpServletRequest);
final Integer arg =
ResourceContext.arg(resourceContext.queryStringAsJsonRepr(),
RequestParameter.PAGE);
assertThat(arg, equalTo(RequestParameter.PAGE.getDefault()));
diff --git
a/viewers/restfulobjects/rendering/src/test/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext_stripQuotes_Test.java
b/viewers/restfulobjects/rendering/src/test/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext_stripQuotes_Test.java
index 650b57e9f27..5928e36361a 100644
---
a/viewers/restfulobjects/rendering/src/test/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext_stripQuotes_Test.java
+++
b/viewers/restfulobjects/rendering/src/test/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext_stripQuotes_Test.java
@@ -24,8 +24,6 @@
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
-import
org.apache.causeway.viewer.restfulobjects.rendering.context.ResourceContext;
-
class ResourceContext_stripQuotes_Test {
@Test
diff --git
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
index 08de00ef8b6..ee85948cf39 100644
---
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
+++
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
@@ -46,7 +46,6 @@
import org.apache.causeway.viewer.restfulobjects.applib.Rel;
import org.apache.causeway.viewer.restfulobjects.applib.RepresentationType;
import
org.apache.causeway.viewer.restfulobjects.applib.domainobjects.DomainObjectResource;
-import org.apache.causeway.viewer.restfulobjects.applib.util.Links;
import org.apache.causeway.viewer.restfulobjects.rendering.ResponseFactory;
import
org.apache.causeway.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
import
org.apache.causeway.viewer.restfulobjects.rendering.context.ResourceContext;
@@ -272,7 +271,7 @@ public static void addLinks(
grid.visit(new Grid.VisitorAdapter() {
@Override
public void visit(final DomainObjectLayoutData
domainObjectLayoutData) {
- Link link = Links.get(
+ Link link = newLink(
Rel.ELEMENT,
resourceContext.restfulUrlFor(
"objects/" + domainType + "/" + instanceId
@@ -283,7 +282,7 @@ public void visit(final DomainObjectLayoutData
domainObjectLayoutData) {
@Override
public void visit(final ActionLayoutData actionLayoutData) {
- Link link = Links.get(
+ Link link = newLink(
Rel.ACTION,
resourceContext.restfulUrlFor(
"objects/" + domainType + "/" + instanceId +
"/actions/" + actionLayoutData.getId()
@@ -294,7 +293,7 @@ public void visit(final ActionLayoutData actionLayoutData) {
@Override
public void visit(final PropertyLayoutData propertyLayoutData) {
- Link link = Links.get(
+ Link link = newLink(
Rel.PROPERTY,
resourceContext.restfulUrlFor(
"objects/" + domainType + "/" + instanceId +
"/properties/" + propertyLayoutData.getId()
@@ -305,7 +304,7 @@ public void visit(final PropertyLayoutData
propertyLayoutData) {
@Override
public void visit(final CollectionLayoutData collectionLayoutData)
{
- Link link = Links.get(
+ Link link = newLink(
Rel.COLLECTION,
resourceContext.restfulUrlFor(
"objects/" + domainType + "/" + instanceId +
"/collections/" + collectionLayoutData.getId()
diff --git
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainTypeResourceServerside.java
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainTypeResourceServerside.java
index 00986011928..018db00de2d 100644
---
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainTypeResourceServerside.java
+++
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainTypeResourceServerside.java
@@ -28,6 +28,7 @@
import org.apache.causeway.applib.annotation.Where;
import org.apache.causeway.commons.internal.base._Strings;
+import org.apache.causeway.commons.io.UrlUtils;
import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter;
import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation;
import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
@@ -36,7 +37,6 @@
import org.apache.causeway.viewer.restfulobjects.applib.Rel;
import org.apache.causeway.viewer.restfulobjects.applib.RepresentationType;
import
org.apache.causeway.viewer.restfulobjects.applib.domaintypes.DomainTypeResource;
-import org.apache.causeway.viewer.restfulobjects.applib.util.UrlEncodingUtils;
import org.apache.causeway.viewer.restfulobjects.rendering.Caching;
import org.apache.causeway.viewer.restfulobjects.rendering.LinkBuilder;
import org.apache.causeway.viewer.restfulobjects.rendering.ResponseFactory;
@@ -319,7 +319,7 @@ private static String domainTypeFor(
}
// formal style; must parse from args that has a link with an href to
the domain type
- var requestParams =
RequestParams.ofQueryString(UrlEncodingUtils.urlDecode(argsAsUrlEncodedQueryString));
+ var requestParams =
RequestParams.ofQueryString(UrlUtils.urlDecodeUtf8(argsAsUrlEncodedQueryString));
final String href = linkFromFormalArgs(requestParams, argsParamId,
onRoException);
return UrlParserUtils.domainTypeFrom(href);
}
diff --git
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/MenuBarsResourceServerside.java
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/MenuBarsResourceServerside.java
index 684728d6dc8..838cb374b99 100644
---
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/MenuBarsResourceServerside.java
+++
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/MenuBarsResourceServerside.java
@@ -32,7 +32,6 @@
import org.apache.causeway.viewer.restfulobjects.applib.Rel;
import org.apache.causeway.viewer.restfulobjects.applib.RepresentationType;
import
org.apache.causeway.viewer.restfulobjects.applib.menubars.MenuBarsResource;
-import org.apache.causeway.viewer.restfulobjects.applib.util.Links;
import
org.apache.causeway.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
import
org.apache.causeway.viewer.restfulobjects.rendering.context.ResourceContext;
import
org.apache.causeway.viewer.restfulobjects.rendering.service.RepresentationService;
@@ -81,7 +80,7 @@ public static Consumer<ServiceActionLayoutData>
linksForServiceActionsAddingVisi
final String relativeUrl = String.format(
"objects/%s/%s/actions/%s",
logicalTypeName, SERVICE_IDENTIFIER,
actionLayoutData.getId());
- Link link = Links.get(
+ Link link = newLink(
Rel.ACTION,
resourceContext.restfulUrlFor(relativeUrl),
RepresentationType.OBJECT_ACTION.getJsonMediaType().toString());
diff --git
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ResourceAbstract.java
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ResourceAbstract.java
index 9940d122cec..d50c224043a 100644
---
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ResourceAbstract.java
+++
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ResourceAbstract.java
@@ -33,6 +33,7 @@
import org.springframework.http.HttpStatus;
import org.apache.causeway.applib.annotation.Where;
+import org.apache.causeway.applib.layout.links.Link;
import org.apache.causeway.applib.services.bookmark.Bookmark;
import org.apache.causeway.commons.internal.base._Strings;
import org.apache.causeway.commons.internal.functions._Predicates;
@@ -44,6 +45,7 @@
import org.apache.causeway.core.metamodel.context.MetaModelContext;
import org.apache.causeway.core.metamodel.object.ManagedObject;
import org.apache.causeway.core.metamodel.object.ManagedObjects;
+import org.apache.causeway.viewer.restfulobjects.applib.Rel;
import org.apache.causeway.viewer.restfulobjects.applib.RepresentationType;
import org.apache.causeway.viewer.restfulobjects.rendering.ResponseFactory;
import
org.apache.causeway.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
@@ -156,6 +158,13 @@ protected ManagedObject getObjectAdapterElseThrowNotFound(
"Could not determine adapter for
bookmark: '%s'".formatted(bookmark))));
}
+ protected static Link newLink(
+ final Rel rel,
+ final String href,
+ final String type) {
+ return new Link(rel.getName(), "GET", href, type);
+ }
+
// -- HELPER
@SneakyThrows
diff --git
a/viewers/restfulobjects/viewer/src/test/java/org/apache/causeway/viewer/restfulobjects/viewer/header/ParserTest.java
b/viewers/restfulobjects/viewer/src/test/java/org/apache/causeway/viewer/restfulobjects/viewer/header/ParserTest.java
index fc976e7bdea..18e2dec8f80 100644
---
a/viewers/restfulobjects/viewer/src/test/java/org/apache/causeway/viewer/restfulobjects/viewer/header/ParserTest.java
+++
b/viewers/restfulobjects/viewer/src/test/java/org/apache/causeway/viewer/restfulobjects/viewer/header/ParserTest.java
@@ -18,6 +18,7 @@
*/
package org.apache.causeway.viewer.restfulobjects.viewer.header;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
@@ -30,7 +31,6 @@
import org.springframework.http.CacheControl;
import org.apache.causeway.viewer.restfulobjects.applib.RestfulMediaType;
-import org.apache.causeway.viewer.restfulobjects.applib.util.MediaTypes;
import org.apache.causeway.viewer.restfulobjects.applib.util.Parser;
class ParserTest {
@@ -51,12 +51,12 @@ void forCacheControl() {
void forMediaType() {
final Parser<org.springframework.http.MediaType> parser =
Parser.forMediaType();
- for (final org.springframework.http.MediaType v : new
org.springframework.http.MediaType[] {
+ for (final org.springframework.http.MediaType v : List.of(
org.springframework.http.MediaType.APPLICATION_ATOM_XML,
org.springframework.http.MediaType.APPLICATION_JSON,
org.springframework.http.MediaType.APPLICATION_XHTML_XML,
- MediaTypes.parse(RestfulMediaType.APPLICATION_JSON_OBJECT)
- }) {
+
Parser.forMediaType().valueOf(RestfulMediaType.APPLICATION_JSON_OBJECT)
+ )) {
final String asString = parser.asString(v);
final org.springframework.http.MediaType valueOf =
parser.valueOf(asString);
assertThat(v, is(equalTo(valueOf)));