diff --git a/devkit-core/pom.xml b/devkit-core/pom.xml
index 15f579a..f4bf40e 100644
--- a/devkit-core/pom.xml
+++ b/devkit-core/pom.xml
@@ -23,7 +23,7 @@
cn.org.codecrafters
jdevkit
- 1.1.0
+ 1.1.1
devkit-core
diff --git a/devkit-utils/pom.xml b/devkit-utils/pom.xml
index f99e4f7..1ddf6c5 100644
--- a/devkit-utils/pom.xml
+++ b/devkit-utils/pom.xml
@@ -6,7 +6,7 @@
cn.org.codecrafters
jdevkit
- 1.1.0
+ 1.1.1
devkit-utils
diff --git a/guid/pom.xml b/guid/pom.xml
index 26e83f1..e3742fb 100644
--- a/guid/pom.xml
+++ b/guid/pom.xml
@@ -23,7 +23,7 @@
cn.org.codecrafters
jdevkit
- 1.1.0
+ 1.1.1
guid
diff --git a/pom.xml b/pom.xml
index 77edffc..3ea9171 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
cn.org.codecrafters
jdevkit
- 1.1.0
+ 1.1.1
2023
pom
diff --git a/property-guard-spring-boot-starter/pom.xml b/property-guard-spring-boot-starter/pom.xml
index 6595ca7..8df59be 100644
--- a/property-guard-spring-boot-starter/pom.xml
+++ b/property-guard-spring-boot-starter/pom.xml
@@ -23,7 +23,7 @@
cn.org.codecrafters
jdevkit
- 1.1.0
+ 1.1.1
property-guard-spring-boot-starter
diff --git a/simple-jwt-authzero/pom.xml b/simple-jwt-authzero/pom.xml
index 65e0e00..29e96b1 100644
--- a/simple-jwt-authzero/pom.xml
+++ b/simple-jwt-authzero/pom.xml
@@ -23,7 +23,7 @@
cn.org.codecrafters
jdevkit
- 1.1.0
+ 1.1.1
simple-jwt-authzero
diff --git a/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java b/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java
index 01d3359..c2d83ce 100644
--- a/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java
+++ b/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/AuthzeroTokenResolver.java
@@ -45,11 +45,6 @@ import java.util.*;
* resolver provides functionality to create, extract, verify, and renew JWT
* tokens using various algorithms and custom payload data.
*
- * Dependencies:
- * This implementation relies on the {@code com.auth0:java-jwt} library. Please
- * ensure you have added this library as a dependency to your project before
- * using this resolver.
- *
* Usage:
* To use the {@code AuthzeroTokenResolver}, first, create an instance of this
* class:
@@ -87,7 +82,7 @@ import java.util.*;
* correctly configured in your project's dependencies.
*
* @author Zihlu Wang
- * @version 1.1.0
+ * @version 1.1.1
* @see GuidCreator
* @see Algorithm
* @see JWTVerifier
@@ -279,7 +274,7 @@ public class AuthzeroTokenResolver implements TokenResolver {
builder.withClaim(name, v);
} else {
log.warn("""
- Unable to determine the type of field {}, converting it to a string now.""", name);
+ Unable to determine the type of field {}, we will handle it as a String.""", name);
builder.withClaim(name, value.toString());
}
} else {
diff --git a/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/config/AuthzeroTokenResolverConfig.java b/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/config/AuthzeroTokenResolverConfig.java
index 2cda8ea..1f0751a 100644
--- a/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/config/AuthzeroTokenResolverConfig.java
+++ b/simple-jwt-authzero/src/main/java/cn/org/codecrafters/simplejwt/authzero/config/AuthzeroTokenResolverConfig.java
@@ -35,19 +35,20 @@ import java.util.function.Function;
* the {@link AuthzeroTokenResolver}.
*
* This configuration is used to establish the mapping between the standard
- * {@link TokenAlgorithm} defined within the {@link AuthzeroTokenResolver}
- * facade and the specific algorithms used by the {@code com.auth0:java-jwt}
- * library, which is the underlying library used by {@link
- * AuthzeroTokenResolver} to handle JSON Web Tokens (JWTs).
+ * {@link TokenAlgorithm} defined in the
+ * {@code cn.org.codecrafters:simple-jwt-facade} and the specific algorithms
+ * used by the {@code com.auth0:java-jwt} library, which is the underlying
+ * library used by {@link AuthzeroTokenResolver} to handle JSON Web Tokens
+ * (JWTs).
*
* Algorithm Mapping:
- * The {@code AuthzeroTokenResolverConfig} allows specifying the relationship
+ * The {@code AuthzeroTokenResolverConfig} allows specifying the relationships
* between the standard {@link TokenAlgorithm} instances supported by
* {@link AuthzeroTokenResolver} and the corresponding algorithms used by the
* {@code com.auth0:java-jwt} library. The mapping is achieved using a Map,
- * where the keys are the standard TokenAlgorithm instances, and the values
- * represent the algorithm functions used by Auth0 Java JWT library for each
- * corresponding key.
+ * where the keys are the standard {@link TokenAlgorithm} instances, and the
+ * values represent the algorithm functions used by {@code com.auth0:java-jwt}
+ * library for each corresponding key.
*
* Note:
* The provided algorithm mapping should be consistent with the actual
@@ -56,7 +57,7 @@ import java.util.function.Function;
* validation and processing within the {@link AuthzeroTokenResolver}.
*
* @author Zihlu Wang
- * @version 1.1.0
+ * @version 1.1.1
* @since 1.0.0
*/
public final class AuthzeroTokenResolverConfig implements TokenResolverConfig> {
diff --git a/simple-jwt-facade/pom.xml b/simple-jwt-facade/pom.xml
index bd72ec4..d16ecf6 100644
--- a/simple-jwt-facade/pom.xml
+++ b/simple-jwt-facade/pom.xml
@@ -23,7 +23,7 @@
cn.org.codecrafters
jdevkit
- 1.1.0
+ 1.1.1
simple-jwt-facade
diff --git a/simple-jwt-facade/src/main/java/cn/org/codecrafters/simplejwt/config/TokenResolverConfig.java b/simple-jwt-facade/src/main/java/cn/org/codecrafters/simplejwt/config/TokenResolverConfig.java
index 2989a03..f29e198 100644
--- a/simple-jwt-facade/src/main/java/cn/org/codecrafters/simplejwt/config/TokenResolverConfig.java
+++ b/simple-jwt-facade/src/main/java/cn/org/codecrafters/simplejwt/config/TokenResolverConfig.java
@@ -21,8 +21,8 @@ import cn.org.codecrafters.simplejwt.TokenResolver;
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
/**
- * The {@code TokenResolverConfig} provides a mechanism to configure a
- * {@link TokenResolver} with algorithm functions.
+ * The {@code TokenResolverConfig} provides a mechanism to configure an
+ * implementation of {@link TokenResolver} with algorithm functions.
*
* This generic interface is used to define the configuration details for a
* {@link TokenResolver} that utilizes algorithm functions. The interface
diff --git a/simple-jwt-jjwt/pom.xml b/simple-jwt-jjwt/pom.xml
index e5acdeb..ff49ffa 100644
--- a/simple-jwt-jjwt/pom.xml
+++ b/simple-jwt-jjwt/pom.xml
@@ -23,7 +23,7 @@
cn.org.codecrafters
jdevkit
- 1.1.0
+ 1.1.1
simple-jwt-jjwt
diff --git a/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/JjwtTokenResolver.java b/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/JjwtTokenResolver.java
index b8896ef..dbf146b 100644
--- a/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/JjwtTokenResolver.java
+++ b/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/JjwtTokenResolver.java
@@ -40,6 +40,7 @@ import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Map;
+import java.util.Objects;
import java.util.UUID;
/**
@@ -49,11 +50,6 @@ import java.util.UUID;
* This resolver provides functionality to create, extract, verify, and renew
* JWT tokens using various algorithms and custom payload data.
*
- * Dependencies:
- * This implementation relies on the {@code io.jsonwebtoken:jjwt} library. Please
- * ensure you have added this library as a dependency to your project before
- * using this resolver.
- *
* Usage:
* To use the {@code JjwtTokenResolver}, first, create an instance of this
* class:
@@ -113,7 +109,7 @@ public class JjwtTokenResolver implements TokenResolver> {
private final JjwtTokenResolverConfig config = JjwtTokenResolverConfig.getInstance();
public JjwtTokenResolver(GuidCreator> jtiCreator, TokenAlgorithm algorithm, String issuer, String secret) {
- if (secret == null || secret.isBlank()) {
+ if (Objects.isNull(secret) || secret.isBlank()) {
throw new IllegalArgumentException("A secret is required to build a JSON Web Token.");
}
@@ -209,8 +205,7 @@ public class JjwtTokenResolver implements TokenResolver> {
*/
@Override
public String createToken(Duration expireAfter, String audience, String subject) {
- var now = LocalDateTime.now();
- return buildToken(expireAfter, audience, subject, now, null);
+ return buildToken(expireAfter, audience, subject, LocalDateTime.now(), null);
}
/**
@@ -225,8 +220,7 @@ public class JjwtTokenResolver implements TokenResolver> {
*/
@Override
public String createToken(Duration expireAfter, String audience, String subject, Map payload) {
- var now = LocalDateTime.now();
- return buildToken(expireAfter, audience, subject, now, payload);
+ return buildToken(expireAfter, audience, subject, LocalDateTime.now(), payload);
}
/**
@@ -244,10 +238,9 @@ public class JjwtTokenResolver implements TokenResolver> {
*/
@Override
public String createToken(Duration expireAfter, String audience, String subject, T payload) {
- var now = LocalDateTime.now();
try {
var claims = MapUtil.objectToMap(payload);
- return buildToken(expireAfter, audience, subject, now, claims);
+ return buildToken(expireAfter, audience, subject, LocalDateTime.now(), claims);
} catch (IllegalAccessException e) {
log.error("An error occurs while accessing the fields of the object");
}
diff --git a/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/config/JjwtTokenResolverConfig.java b/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/config/JjwtTokenResolverConfig.java
index a174665..89eefba 100644
--- a/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/config/JjwtTokenResolverConfig.java
+++ b/simple-jwt-jjwt/src/main/java/cn/org/codecrafters/simplejwt/jjwt/config/JjwtTokenResolverConfig.java
@@ -28,19 +28,20 @@ import java.util.HashMap;
import java.util.Map;
/**
- * The {@code JjwtTokenResolverConfig} class provides the configuration for the
- * {@link JjwtTokenResolver}.
+ * The {@code JjwtTokenResolverConfig} class provides the configuration for
+ * the {@link JjwtTokenResolver}.
*
- * This configuration class is used to establish the mapping between the
- * standard {@link TokenAlgorithm} defined within the
- * {@code JjwtTokenResolverConfig} and the specific algorithms used by the
- * {@code io.jsonwebtoken:jjwt} library, which is the underlying library used
- * by {@code JjwtTokenResolver} to handle JSON Web Tokens (JWTs).
+ * This configuration is used to establish the mapping between the standard
+ * {@link TokenAlgorithm} defined in the
+ * {@code cn.org.codecrafters:simple-jwt-facade} and the specific algorithms
+ * used by the {@code io.jsonwebtoken:jjwt} library, which is the underlying
+ * library used by {@link JjwtTokenResolver} to handle JSON Web Tokens
+ * (JWTs).
*
* Algorithm Mapping:
- * The {@code JjwtTokenResolverConfig} allows specifying the relationship
- * between the standard {@link TokenAlgorithm} instances supported by {@link
- * JjwtTokenResolver} and the corresponding algorithms used by the
+ * The {@code JjwtTokenResolverConfig} allows specifying the relationships
+ * between the standard {@link TokenAlgorithm} instances supported by
+ * {@link JjwtTokenResolver} and the corresponding algorithms used by the
* {@code io.jsonwebtoken:jjwt} library. The mapping is achieved using a Map,
* where the keys are the standard {@link TokenAlgorithm} instances, and the
* values represent the algorithm functions used by
@@ -53,7 +54,7 @@ import java.util.Map;
* validation and processing within the {@link JjwtTokenResolver}.
*
* @author Zihlu Wang
- * @version 1.1.0
+ * @version 1.1.1
* @since 1.0.0
*/
public final class JjwtTokenResolverConfig implements TokenResolverConfig {
diff --git a/simple-jwt-spring-boot-starter/pom.xml b/simple-jwt-spring-boot-starter/pom.xml
index 9e6a49c..50a9890 100644
--- a/simple-jwt-spring-boot-starter/pom.xml
+++ b/simple-jwt-spring-boot-starter/pom.xml
@@ -23,7 +23,7 @@
cn.org.codecrafters
jdevkit
- 1.1.0
+ 1.1.1
simple-jwt-spring-boot-starter
diff --git a/webcal/pom.xml b/webcal/pom.xml
index 4419d64..eb49cb2 100644
--- a/webcal/pom.xml
+++ b/webcal/pom.xml
@@ -23,7 +23,7 @@
cn.org.codecrafters
jdevkit
- 1.1.0
+ 1.1.1
webcal
diff --git a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendar.java b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendar.java
index e16b581..9a99469 100644
--- a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendar.java
+++ b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendar.java
@@ -19,6 +19,7 @@ package cn.org.codecrafters.webcal;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* {@code WebCalendar} class represents a web calendar in iCalendar format.
@@ -189,18 +190,22 @@ public final class WebCalendar {
* @return the resolved iCalendar string
*/
public String resolve() {
- var events = new StringBuilder();
+ var eventBuilder = new StringBuilder();
if (!nodes.isEmpty()) {
- nodes.forEach(item ->
- events.append(item.setDomainName(domainName)
- .resolve()));
+ for (var node : nodes) {
+ if (Objects.isNull(node.getDomainName()) || node.getDomainName().isBlank()) {
+ node.setDomainName(this.domainName);
+ }
+
+ eventBuilder.append(node.resolve());
+ }
}
return "BEGIN:" + TAG + "\n" +
"PRODID:-//" + companyName + "//" + productName + "//EN\n" +
"VERSION:" + version + "\n" +
"X-WR-CALNAME:" + name + "\n" +
- events + "\n" +
+ eventBuilder + "\n" +
"END:" + TAG;
}
diff --git a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarEvent.java b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarEvent.java
index c073d19..2870246 100644
--- a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarEvent.java
+++ b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarEvent.java
@@ -18,10 +18,12 @@
package cn.org.codecrafters.webcal;
import cn.org.codecrafters.webcal.config.Classification;
+import cn.org.codecrafters.webcal.config.Formatter;
+import java.text.MessageFormat;
import java.time.Duration;
import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
+import java.time.ZoneId;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
@@ -257,30 +259,34 @@ public final class WebCalendarEvent extends WebCalendarNode {
*/
@Override
public String resolve() {
- return "\nBEGIN:" + TAG + "\n" +
- "UID:" + Optional.ofNullable(uid).orElse(UUID.randomUUID().toString()) + "@" + domainName + "\n" +
- Optional.ofNullable(summary).map((item) -> "SUMMARY:" + item + "\n").orElse("") +
- "DTSTART" + Optional.ofNullable(timezone).map(item -> ";TZID=" + item).orElse("") + ":" + start.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + "\n" +
+ var now = LocalDateTime.now().atZone(ZoneId.systemDefault());
+ return MessageFormat.format("""
+ BEGIN:{0}
+ UID:{1}
+ DTSTAMP:{2}
+ DTSTART:{3}
+ DURATION:PT{6}S
+ {4}{5}{7}{8}{9}{10}{11}{12}
+ END:{0}""",
+ TAG, // 0 - tag
+ Optional.ofNullable(uid).orElse(UUID.randomUUID().toString()) + "@" + domainName, // 1 - uid
+ now.format(Formatter.getUtcDatetimeFormatter()), // 2 - dtstamp
+ start.atZone(ZoneId.systemDefault()).format(Formatter.getUtcDatetimeFormatter()), // 3 - start time
+ Optional.ofNullable(summary).map((item) -> "\nSUMMARY:" + item).orElse(""), // 4 - summary
Optional.ofNullable(categories)
- .map((item) -> {
- if (!item.isEmpty()) {
- return "CATEGORIES:" + resolveCategories() + "\n";
- }
- return null;
- }).orElse("") +
+ .map((item) -> !item.isEmpty() ? "\nCATEGORIES:" + resolveCategories() : null).orElse(""), // 5 - categories
Optional.ofNullable(duration)
- .map((item) -> "DURATION:PT" + item.getSeconds() + "S\n").orElse("") +
- Optional.ofNullable(end)
- .map((item) -> "DTEND" + Optional.ofNullable(timezone).map(tz -> ";TZID=" + tz).orElse("") + ":" +
- end.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + "\n").orElse("") +
- Optional.ofNullable(classification)
- .map((item) -> "CLASS:" + item.name() + "\n").orElse("") +
- Optional.ofNullable(comment).map((item) -> "COMMENT:" + item + "\n").orElse("") +
- Optional.ofNullable(description).map((item) -> "DESCRIPTION:" + item + "\n").orElse("") +
- Optional.ofNullable(location).map((item) -> "LOCATION:" + item + "\n").orElse("") +
- Optional.ofNullable(percentComplete).map((item) -> "PERCENT-COMPLETE:" + item + "\n").orElse("") +
- Optional.ofNullable(priority).map((item) -> "PRIORITY:" + item + "\n").orElse("") +
- "END:" + TAG + "\n";
+ .map((_duration) -> String.valueOf(_duration.getSeconds()))
+ .orElse(Optional.ofNullable(end)
+ .map((_end) -> String.valueOf(Duration.between(_end, start).getSeconds()))
+ .orElse("0")), // 6 - duration
+ Optional.ofNullable(classification).map((_classification) -> "\nCLASS:" + _classification + "\n").orElse(""), /* 7 - classification */
+ Optional.ofNullable(comment).map((_comment) -> "\nCOMMENT:" + _comment + "\n").orElse(""), /* 8 - comment */
+ Optional.ofNullable(location).map((_location) -> "\nLOCATION:" + _location).orElse("") /* 9 - location */,
+ Optional.ofNullable(percentComplete).map((_percentComplete) -> "\nPERCENT-COMPLETE:" + _percentComplete).orElse("") /* 10 = percentComplete */,
+ Optional.ofNullable(description).map((_description) -> "\nDESCRIPTION:" + _description).orElse("") /* 11 - description */,
+ Optional.ofNullable(priority).map((_priority) -> "\nPRIORITY:" + _priority).orElse("") /* 12 - priority */
+ );
}
}
diff --git a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarNode.java b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarNode.java
index 5f56b11..75b0e43 100644
--- a/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarNode.java
+++ b/webcal/src/main/java/cn/org/codecrafters/webcal/WebCalendarNode.java
@@ -90,6 +90,15 @@ public abstract sealed class WebCalendarNode
return this;
}
+ /**
+ * Get the domain name.
+ *
+ * @return the domain name of this event
+ */
+ public String getDomainName() {
+ return this.domainName;
+ }
+
/**
* Resolve the list of categories into a comma-separated string.
*
diff --git a/webcal/src/main/java/cn/org/codecrafters/webcal/config/Formatter.java b/webcal/src/main/java/cn/org/codecrafters/webcal/config/Formatter.java
new file mode 100644
index 0000000..4760d79
--- /dev/null
+++ b/webcal/src/main/java/cn/org/codecrafters/webcal/config/Formatter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 CodeCraftersCN.
+ *
+ * Licensed 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 cn.org.codecrafters.webcal.config;
+
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.util.Objects;
+
+/**
+ * DatetimeFormatters
+ *
+ * @author Zihlu Wang
+ * @since 21 Sept, 2023
+ */
+public final class Formatter {
+
+ public static DateTimeFormatter getUtcDatetimeFormatter() {
+ if (Objects.isNull(utcDateTimeFormatter)) {
+ utcDateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'").withZone(ZoneOffset.UTC);
+ }
+
+ return utcDateTimeFormatter;
+ }
+
+ // public static DateTimeFormatter getLocalDatetimeFormatter() {
+ // if (Objects.isNull(localDatetimeFormatter)) {
+ // localDatetimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss");
+ // }
+ //
+ // return localDatetimeFormatter;
+ // }
+
+ private static DateTimeFormatter utcDateTimeFormatter;
+
+ // private static DateTimeFormatter localDatetimeFormatter;
+
+}