Merge pull request #32 from OnixByte/release/1.5.0

Release/1.5.0
This commit is contained in:
Zihlu Wang
2024-06-30 12:22:51 +08:00
committed by GitHub
73 changed files with 426 additions and 1324 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,204 +19,98 @@ package com.onixbyte.devkit.utils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
/** /**
* {@code MapUtil} is a utility class that provides methods for converting * {@code MapUtil} is a utility class that provides methods for converting objects to maps and maps
* objects to maps and maps to objects. * to objects.
* <p> * <p>
* It also provides methods for getting and setting field values using * Note: Since version 1.4.2, this util class removed reflection API and transferred to a safer API.
* reflection. * Please see <a href="">documentation</a> for more information.
* *
* @author Zihlu Wang * @author Zihlu Wang
* @version 1.1.0 * @version 1.4.2
* @see com.onixbyte.devkit.utils.unsafe.ReflectMapUtil
* @since 1.0.0 * @since 1.0.0
*/ */
@Slf4j @Slf4j
public final class MapUtil { public final class MapUtil {
/** /**
* Converts an object to a map by mapping the field names to their * Converts an object to a map by mapping the field names to their corresponding values.
* corresponding values.
* *
* @param obj the object to be converted to a map * @param entity the object to be converted to a map
* @return a map representing the fields and their values of the object * @return a map representing the fields and their values of the object
* @throws IllegalAccessException if an error occurs while accessing the
* fields of the object
*/ */
public static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException { public static <T> Map<String, Object> objectToMap(T entity,
if (obj == null) { Map<String, ObjectMapAdapter<T, ?>> adapters) {
return null; var resultMap = new HashMap<String, Object>();
} adapters.forEach((fieldName, adapter) -> resultMap.put(fieldName, adapter.fetch(entity)));
return resultMap;
var map = new HashMap<String, Object>();
var declaredFields = obj.getClass().getDeclaredFields();
for (var field : declaredFields) {
field.setAccessible(true);
Object result = field.get(obj);
if (result != null) {
map.put(field.getName(), result);
}
}
return map;
} }
/** /**
* Converts a map to an object of the specified type by setting the field * Converts a map to an object of the specified type by setting the field values using the
* values using the map entries. * map entries.
* *
* @param map the map representing the fields and their values * @param objectMap the map representing the fields and their values
* @param requiredType the class of the object to be created * @param entity an empty entity of the target class
* @param adapters the adapters to execute the setter for the entity
* @param <T> the type of the object to be created * @param <T> the type of the object to be created
* @return an object of the specified type with the field values set from * @return an object of the specified type with the field values set from the map
* the map
* @throws NoSuchMethodException if the constructor of the required
* type is not found
* @throws InvocationTargetException if an error occurs while invoking the
* constructor
* @throws InstantiationException if the required type is abstract or an
* interface
* @throws IllegalAccessException if an error occurs while accessing the
* fields of the object
*/ */
public static <T> T mapToObject(Map<String, Object> map, Class<T> requiredType) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { public static <T> T mapToObject(Map<String, Object> objectMap,
var bean = requiredType.getConstructor().newInstance(); T entity,
if (map != null) { Map<String, ObjectMapAdapter<T, ?>> adapters) {
for (var entry : map.entrySet()) { adapters.forEach((fieldName, adapter) -> Optional.ofNullable(objectMap)
try { .map((data) -> data.get(fieldName))
var entryValue = entry.getValue().toString(); .ifPresent((fieldValue) -> adapter.setValue(entity, fieldValue)));
// get the field by field name return entity;
var field = requiredType.getDeclaredField(entry.getKey());
var fieldType = field.getGenericType();
// convert field value by class
if (fieldType instanceof Class<?> fieldClass) {
if (fieldClass == Short.class || fieldClass == short.class) {
entry.setValue(Short.parseShort(entryValue));
} else if (fieldClass == Integer.class || fieldClass == int.class) {
entry.setValue(Integer.parseInt(entryValue));
} else if (fieldClass == Long.class || fieldClass == long.class) {
entry.setValue(Long.parseLong(entryValue));
} else if (fieldClass == Float.class || fieldClass == float.class) {
entry.setValue(Float.parseFloat(entryValue));
} else if (fieldClass == Double.class || fieldClass == double.class) {
entry.setValue(Double.parseDouble(entryValue));
} else if (fieldClass == Character.class || fieldClass == char.class) {
entry.setValue(entryValue.charAt(0));
} else if (fieldClass == Byte.class || fieldClass == byte.class) {
entry.setValue(Byte.parseByte(entryValue));
} else if (fieldClass == Boolean.class || fieldClass == boolean.class) {
entry.setValue(Boolean.parseBoolean(entryValue));
} else if (fieldClass == String.class) {
entry.setValue(entryValue);
} else {
log.error("Unable to determine the type of property {}.", field.getName());
continue;
}
}
setFieldValue(bean, entry.getKey(), entry.getValue());
} catch (Exception e) {
log.error("Map to Object failed.");
}
}
}
return bean;
} }
/** /**
* Retrieves the value of a field from an object using reflection. * Retrieves the value of a field from an object using reflection.
* *
* @param obj the object from which to retrieve the field value
* @param fieldName the name of the field
* @param fieldType the class representing the type of the field value
* @param <T> the type of the field value * @param <T> the type of the field value
* @return the value of the field in the object, or null if the field does * @param entity the object from which to retrieve the field value
* not exist or cannot be accessed * @param adapter the adapter to execute the getter
* @throws IllegalAccessException if an error occurs while accessing the * @return the value of the field in the object, or null if the field does not exist or cannot
* field * be accessed
* @throws InvocationTargetException if an error occurs while invoking the
* field getter method
* @throws NoSuchMethodException if the specified getter is not present
*/ */
public static <T> T getFieldValue(Object obj, String fieldName, Class<T> fieldType) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { public static <E, T> T getFieldValue(E entity, ObjectMapAdapter<E, T> adapter) {
var methodName = getMethodName("get", fieldName); return adapter.fetch(entity);
var objectClass = obj.getClass();
var method = objectClass.getDeclaredMethod(methodName);
method.setAccessible(true);
return cast(method.invoke(obj), fieldType);
} }
/** /**
* Sets the value of a field in an object using reflection. * Sets the value of a field in an object using reflection.
* *
* @param obj the object in which to set the field value * @param entity the object in which to set the field value
* @param fieldName the name of the field * @param adapter the adapter to execute the setter
* @param fieldValue the value to be set * @param fieldValue the value to be set
* @throws InvocationTargetException if an error occurs while invoking the
* field setter method
* @throws IllegalAccessException if an error occurs while accessing the
* field
* @throws NoSuchMethodException if the specific setter is not present
*/ */
public static void setFieldValue(Object obj, String fieldName, Object fieldValue) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { public static <E, T> void setFieldValue(E entity,
var objectClass = obj.getClass(); ObjectMapAdapter<E, T> adapter,
var methodName = getMethodName("set", fieldName); Object fieldValue) {
var method = objectClass.getDeclaredMethod(methodName, fieldValue.getClass()); adapter.setValue(entity, fieldValue);
method.setAccessible(true);
method.invoke(obj, fieldValue);
} }
/** /**
* Casts the specified value to the required type. * Casts the specified value to the required type with Optional.
* *
* @param value the value to be cast * @param value the value to be cast
* @param requiredType the type to which the value should be cast * @param requiredType the type to which the value should be cast
* @param <T> the type to which the value should be cast * @param <T> the type to which the value should be cast
* @return the cast value, or null if the value cannot be cast to the * @return the cast value, or {@code null} if the value is not an instance of the requiredType
* required type
*/ */
public static <T> T cast(Object value, Class<T> requiredType) { public static <T> T cast(Object value, Class<T> requiredType) {
if (requiredType.isInstance(value)) { return Optional.ofNullable(requiredType)
return requiredType.cast(value); .filter((clazz) -> clazz.isInstance(value))
} .map((clazz) -> clazz.cast(value))
return null; .orElse(null);
} }
/**
* Constructs a method name based on the given prefix and field name.
*
* @param prefix the prefix to be added to the field name
* @param fieldName the name of the field
* @return the constructed method name
*/
private static String getMethodName(String prefix, String fieldName) {
return prefix + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
}
/**
* Returns the default string representation of the specified object.
*
* @param obj the object for which to return the default string
* representation
* @return the default string representation of the object
*/
private static String defaultObject(Object obj) {
if (obj == null) {
return "";
} else {
return String.valueOf(obj);
}
}
/**
* Private constructor will protect this class from being instantiated.
*/
private MapUtil() { private MapUtil() {
} }
} }
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2024-2024 OnixByte.
*
* 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 com.onixbyte.devkit.utils;
import java.util.function.BiConsumer;
import java.util.function.Function;
/**
* Adapts an Object to a Map, making conversion between Map and Object much more safe.
*
* @param <E> entity type
* @param <T> field type
* @author zihluwang
* @version 1.4.2
* @since 1.4.2
*/
public class ObjectMapAdapter<E, T> {
private final Function<E, T> getter;
private final BiConsumer<E, Object> setter;
/**
* Create an adapter.
*
* @param getter the getter of the field
* @param setter the setter of the field
*/
public ObjectMapAdapter(Function<E, T> getter, BiConsumer<E, Object> setter) {
this.getter = getter;
this.setter = setter;
}
/**
* Get data from the entity.
*
* @param entity the source of the data
* @return the data
*/
public T fetch(E entity) {
return getter.apply(entity);
}
/**
* Set value to the entity.
*
* @param entity the target of the data
* @param value the value
*/
public void setValue(E entity, Object value) {
setter.accept(entity, value);
}
}
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -0,0 +1,222 @@
/*
* Copyright (C) 2024 OnixByte.
*
* 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 com.onixbyte.devkit.utils.unsafe;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
/**
* {@code MapUtil} is a utility class that provides methods for converting
* objects to maps and maps to objects.
* <p>
* It also provides methods for getting and setting field values using
* reflection.
*
* @author zihluwang
* @version 1.4.2
* @since 1.4.2
*/
@Slf4j
public final class ReflectMapUtil {
/**
* Converts an object to a map by mapping the field names to their
* corresponding values.
*
* @param obj the object to be converted to a map
* @return a map representing the fields and their values of the object
* @throws IllegalAccessException if an error occurs while accessing the
* fields of the object
*/
public static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {
if (obj == null) {
return null;
}
var map = new HashMap<String, Object>();
var declaredFields = obj.getClass().getDeclaredFields();
for (var field : declaredFields) {
field.setAccessible(true);
Object result = field.get(obj);
if (result != null) {
map.put(field.getName(), result);
}
}
return map;
}
/**
* Converts a map to an object of the specified type by setting the field
* values using the map entries.
*
* @param map the map representing the fields and their values
* @param requiredType the class of the object to be created
* @param <T> the type of the object to be created
* @return an object of the specified type with the field values set from
* the map
* @throws NoSuchMethodException if the constructor of the required
* type is not found
* @throws InvocationTargetException if an error occurs while invoking the
* constructor
* @throws InstantiationException if the required type is abstract or an
* interface
* @throws IllegalAccessException if an error occurs while accessing the
* fields of the object
*/
public static <T> T mapToObject(Map<String, Object> map, Class<T> requiredType) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
var bean = requiredType.getConstructor().newInstance();
if (map != null) {
for (var entry : map.entrySet()) {
try {
var entryValue = entry.getValue().toString();
// get the field by field name
var field = requiredType.getDeclaredField(entry.getKey());
var fieldType = field.getGenericType();
// convert field value by class
if (fieldType instanceof Class<?> fieldClass) {
if (fieldClass == Short.class || fieldClass == short.class) {
entry.setValue(Short.parseShort(entryValue));
} else if (fieldClass == Integer.class || fieldClass == int.class) {
entry.setValue(Integer.parseInt(entryValue));
} else if (fieldClass == Long.class || fieldClass == long.class) {
entry.setValue(Long.parseLong(entryValue));
} else if (fieldClass == Float.class || fieldClass == float.class) {
entry.setValue(Float.parseFloat(entryValue));
} else if (fieldClass == Double.class || fieldClass == double.class) {
entry.setValue(Double.parseDouble(entryValue));
} else if (fieldClass == Character.class || fieldClass == char.class) {
entry.setValue(entryValue.charAt(0));
} else if (fieldClass == Byte.class || fieldClass == byte.class) {
entry.setValue(Byte.parseByte(entryValue));
} else if (fieldClass == Boolean.class || fieldClass == boolean.class) {
entry.setValue(Boolean.parseBoolean(entryValue));
} else if (fieldClass == String.class) {
entry.setValue(entryValue);
} else {
log.error("Unable to determine the type of property {}.", field.getName());
continue;
}
}
setFieldValue(bean, entry.getKey(), entry.getValue());
} catch (Exception e) {
log.error("Map to Object failed.");
}
}
}
return bean;
}
/**
* Retrieves the value of a field from an object using reflection.
*
* @param obj the object from which to retrieve the field value
* @param fieldName the name of the field
* @param fieldType the class representing the type of the field value
* @param <T> the type of the field value
* @return the value of the field in the object, or null if the field does
* not exist or cannot be accessed
* @throws IllegalAccessException if an error occurs while accessing the
* field
* @throws InvocationTargetException if an error occurs while invoking the
* field getter method
* @throws NoSuchMethodException if the specified getter is not present
*/
public static <T> T getFieldValue(Object obj, String fieldName, Class<T> fieldType) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
var methodName = getMethodName("get", fieldName);
var objectClass = obj.getClass();
var method = objectClass.getDeclaredMethod(methodName);
method.setAccessible(true);
return cast(method.invoke(obj), fieldType);
}
/**
* Sets the value of a field in an object using reflection.
*
* @param obj the object in which to set the field value
* @param fieldName the name of the field
* @param fieldValue the value to be set
* @throws InvocationTargetException if an error occurs while invoking the
* field setter method
* @throws IllegalAccessException if an error occurs while accessing the
* field
* @throws NoSuchMethodException if the specific setter is not present
*/
public static void setFieldValue(Object obj, String fieldName, Object fieldValue) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
var objectClass = obj.getClass();
var methodName = getMethodName("set", fieldName);
var method = objectClass.getDeclaredMethod(methodName, fieldValue.getClass());
method.setAccessible(true);
method.invoke(obj, fieldValue);
}
/**
* Casts the specified value to the required type.
*
* @param value the value to be cast
* @param requiredType the type to which the value should be cast
* @param <T> the type to which the value should be cast
* @return the cast value, or null if the value cannot be cast to the
* required type
*/
public static <T> T cast(Object value, Class<T> requiredType) {
if (requiredType.isInstance(value)) {
return requiredType.cast(value);
}
return null;
}
/**
* Constructs a method name based on the given prefix and field name.
*
* @param prefix the prefix to be added to the field name
* @param fieldName the name of the field
* @return the constructed method name
*/
private static String getMethodName(String prefix, String fieldName) {
return prefix + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
}
/**
* Returns the default string representation of the specified object.
*
* @param obj the object for which to return the default string
* representation
* @return the default string representation of the object
*/
private static String defaultObject(Object obj) {
if (obj == null) {
return "";
} else {
return String.valueOf(obj);
}
}
/**
* Private constructor will protect this class from being instantiated.
*/
private ReflectMapUtil() {
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ springVersion=6.1.3
springBootVersion=3.2.3 springBootVersion=3.2.3
buildGroupId=com.onixbyte buildGroupId=com.onixbyte
buildVersion=1.4.1 buildVersion=1.5.0
projectUrl=https://onixbyte.com/JDevKit projectUrl=https://onixbyte.com/JDevKit
projectGithubUrl=https://github.com/OnixByte/JDevKit projectGithubUrl=https://github.com/OnixByte/JDevKit
licenseName=The Apache License, Version 2.0 licenseName=The Apache License, Version 2.0
+2 -3
View File
@@ -1,5 +1,5 @@
# #
# Copyright (C) 2023 CodeCraftersCN. # Copyright (C) 2024-2024 OnixByte.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -15,10 +15,9 @@
# limitations under the License. # limitations under the License.
# #
# Wed 31 Jan 00:00:00 HKT 2024
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
Vendored
+10 -10
View File
@@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. echo location of your Java installation. 1>&2
goto fail goto fail
@@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto execute
echo. echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. echo location of your Java installation. 1>&2
goto fail goto fail
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
+2 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -28,3 +28,4 @@ include(
"simple-jwt-spring-boot-starter", "simple-jwt-spring-boot-starter",
"property-guard-spring-boot-starter" "property-guard-spring-boot-starter"
) )
include("map-util-unsafe")
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,3 +1,20 @@
/*
* Copyright (C) 2024-2024 OnixByte.
*
* 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 com.onixbyte.simplejwt.autoconfiguration.conditions; package com.onixbyte.simplejwt.autoconfiguration.conditions;
import com.onixbyte.guid.GuidCreator; import com.onixbyte.guid.GuidCreator;
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 CodeCraftersCN. * Copyright (C) 2024-2024 OnixByte.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
-93
View File
@@ -1,93 +0,0 @@
# Module `webcal`
## Introduction
The module `webcal` is a Java library that facilitates the generation and resolution of iCalendar content for web-based calendar applications. It provides a flexible and easy-to-use API for creating web calendars with customisable settings and events.
### Key features
- Create and manage web calendars with events, including event details such as summary, description, location, and more.
- Define event classifications and categories for better organisation and filtering of calendar data.
- Set event start and end times, durations, and time zones to handle various scheduling scenarios.
- Configure event priorities and completion percentages for visual representation in the calendar.
- Generate iCalendar format output suitable for web calendar applications.
With the `webcal` module, developers can easily integrate calendar functionality into web applications, enabling users to view, add, and manage events in a structured and standardized format. It is designed to simplify calendar-related tasks and enhance the overall user experience when dealing with calendar data on the web.
Please note that the `webcal` module adheres to the iCalendar standard specified in RFC 5545, ensuring compatibility with other calendar applications that support this format.
## Prerequisites
- This whole `JDevKit` is developed by **JDK 17**, which means you have to use JDK 17 for better experience.
## Installation
### If you are using `Maven`
It is quite simple to install this module by `Maven`. The only thing you need to do is find your `pom.xml` file in the project, then find the `<dependencies>` node in the `<project>` node, and add the following codes to `<dependencies>` node:
```xml
<dependency>
<groupId>${implementation-builder-group-id}</groupId>
<artifactId>simple-jwt-${any-implementation}</artifactId>
<version>${simple-jwt-${any-implementation}.version}</version>
</dependency>
<dependency>
<groupId>cn.org.codecrafters</groupId>
<artifactId>simple-jwt-spring-boot-starter</artifactId>
<version>${simple-jwt-spring-boot-starter.version}</version>
</dependency>
```
And run `mvn dependency:get` in your project root folder(i.e., if your `pom.xml` is located at `/path/to/your/project/pom.xml`, then your current work folder should be `/path/to/your/project`), then `Maven` will automatically download the `jar` archive from `Maven Central Repository`. This could be **MUCH EASIER** if you are using IDE(i.e., IntelliJ IDEA), the only thing you need to do is click the refresh button of `Maven`.
If you are restricted using the Internet, and have to make `Maven` offline, you could follow the following steps.
1. Download the `jar` file from any place you can get and transfer the `jar` files to your work computer.
2. Move the `jar` files to your local `Maven` Repository as the path of `/path/to/maven_local_repo/cn/org/codecrafters/simple-jwt-spring-boot-starter/` and `/path/to/maven_local_repo/${implementation-builder-group-seperated-by-system-seperator}/${implementation_artifact_id}`.
### If you are using `Gradle`
Add this module to your project with `Gradle` is much easier than doing so with `Maven`.
Find `build.gradle` in the needed project, and add the following code to the `dependencies` closure in the build script:
```groovy
implementation '${implementation-builder-group-id}:simple-jwt-${any-implementation}:${simple-jwt-${any-implementation}.version}'
implementation 'cn.org.codecrafters:simple-jwt-spring-boot-starter:${simple-jwt-spring-boot-starter.version}'
```
### If you are not using `Maven` or `Gradle`
1. Download the `jar` file from the Internet.
2. Create a folder in your project and name it as a name you like(i.e., for me, I prefer `vendor`).
3. Put the `jar` file to the folder you just created in Step 2.
4. Add this folder to your project `classpath`.
## Create a web calendar
```java
var calendar = new WebCalendar()
// set the properties for web calendar here.
;
```
## Add a calendar node to this calendar
```java
calendar.addNode(new WebCalendarNode()
// set properties for this node here.
);
```
## Resolve this calendar.
```java
var calendarString = calendar.resolve();
```
## Contact
If you have any suggestions, ideas, don't hesitate contacting us via [GitHub Issues](https://github.com/CodeCraftersCN/jdevkit/issues/new) or [Discord Community](https://discord.gg/NQK9tjcBB8).
If you face any bugs while using our library and you are able to fix any bugs in our library, we would be happy to accept pull requests from you on [GitHub](https://github.com/CodeCraftersCN/jdevkit/compare).
-90
View File
@@ -1,90 +0,0 @@
import java.net.URI
val buildGroupId: String by project
val buildVersion: String by project
val projectUrl: String by project
val projectGithubUrl: String by project
val licenseName: String by project
val licenseUrl: String by project
group = buildGroupId
version = buildVersion
dependencies {
implementation(project(":devkit-core"))
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
withSourcesJar()
withJavadocJar()
}
tasks.test {
useJUnitPlatform()
}
publishing {
publications {
create<MavenPublication>("webcal") {
groupId = buildGroupId
artifactId = "webcal"
version = buildVersion
pom {
name = "DevKit :: WebCal"
description = "The web calendar module of JDevKit."
url = projectUrl
licenses {
license {
name = licenseName
url = licenseUrl
}
}
scm {
connection = "scm:git:git://github.com:OnixByte/JDevKit.git"
developerConnection = "scm:git:git://github.com:OnixByte/JDevKit.git"
url = projectGithubUrl
}
developers {
developer {
id = "zihluwang"
name = "Zihlu Wang"
email = "really@zihlu.wang"
timezone = "Asia/Hong_Kong"
}
}
}
from(components["java"])
signing {
sign(publishing.publications["webcal"])
}
}
repositories {
maven {
name = "sonatypeNexus"
url = URI(providers.gradleProperty("repo.maven-central.host").get())
credentials {
username = providers.gradleProperty("repo.maven-central.username").get()
password = providers.gradleProperty("repo.maven-central.password").get()
}
}
maven {
name = "githubPackages"
url = URI(providers.gradleProperty("repo.github.host").get())
credentials {
username = providers.gradleProperty("repo.github.username").get()
password = providers.gradleProperty("repo.github.password").get()
}
}
}
}
}
@@ -1,215 +0,0 @@
/*
* 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 com.onixbyte.webcal;
import com.onixbyte.webcal.impl.WebCalendarEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* {@code WebCalendar} class represents a web calendar in iCalendar format.
* <p>
* It allows users to create and customise calendar components and events and
* generate an <b>iCalendar</b> string containing all the calendar information.
* <p>
* Usage Example:
* <pre>
* WebCalendar calendar = new WebCalendar()
* .setName("My Web Calendar")
* .setCompanyName("CodeCrafters Inc.")
* .setProductName("WebCal")
* .setDomainName("codecrafters.org.cn")
* .setMethod("PUBLISH")
* .addEvent(event1)
* .addEvent(event2);
* String iCalendarString = calendar.resolve();
* </pre>
* <p>
* The {@code WebCalendar} class is designed to generate an iCalendar string
* conforming to the iCalendar specification, which can be used to share
* calendar data with other calendar applications or services.
*
* @author Zihlu Wang
* @version 1.1.0
* @since 1.0.0
*/
public final class WebCalendar {
/**
* Constructor for WebCalendar class, initializes the list of calendar
* components and events.
*/
public WebCalendar() {
this.nodes = new ArrayList<>();
}
/**
* Set the name of the web calendar.
*
* @param name the name of the web calendar
* @return the WebCalendar object
*/
public WebCalendar setName(String name) {
this.name = name;
return this;
}
/**
* Set the company name associated with the web calendar.
*
* @param companyName the company name
* @return the WebCalendar object
*/
public WebCalendar setCompanyName(String companyName) {
this.companyName = companyName;
return this;
}
/**
* Set the domain name associated with the web calendar.
*
* @param domainName the domain name
* @return the WebCalendar object
*/
public WebCalendar setDomainName(String domainName) {
this.domainName = domainName;
return this;
}
/**
* Set the product name of the web calendar.
*
* @param productName the product name
* @return the WebCalendar object
*/
public WebCalendar setProductName(String productName) {
this.productName = productName;
return this;
}
/**
* Set the method for publishing the web calendar.
*
* @param method the publishing method
* @return the WebCalendar object
*/
public WebCalendar setMethod(String method) {
this.method = method;
return this;
}
/**
* Add an node to the web calendar.
*
* @param node the calendar component or event to be added
* @return the WebCalendar object
*/
public WebCalendar addNode(WebCalendarNode node) {
this.nodes.add(node);
return this;
}
/**
* Add an event to the web calendar.
*
* @param event the calendar component or event to be added
* @return the WebCalendar object
*/
public WebCalendar addEvent(WebCalendarEvent event) {
this.nodes.add(event);
return this;
}
/**
* Generate and resolve the iCalendar string for the web calendar.
*
* @return the resolved iCalendar string
*/
public String resolve() {
var eventBuilder = new StringBuilder();
if (!nodes.isEmpty()) {
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" +
eventBuilder + "\n" +
"END:" + TAG;
}
/**
* The {@code VCALENDAR} tag for iCalendar format
*/
private final static String TAG = "VCALENDAR";
/**
* The name of this calendar.
*/
private String name;
/**
* The company who produces this calendar.
* <p>
* This property will be used in {@code PRODID}.
*/
private String companyName;
/**
* The product name.
* <p>
* This property will be used in {@code PRODID}
*/
private String productName;
/**
* The producer's domain name.
*/
private String domainName;
/**
* Scale of this calendar.
*/
private final String scale = "GREGORIAN";
/**
* The method of this calendar.
*/
private String method;
/**
* The version of this calendar.
*/
private final String version = "2.0";
/**
* List of calendar components and events
*/
private final List<WebCalendarNode> nodes;
}
@@ -1,124 +0,0 @@
/*
* 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 com.onixbyte.webcal;
import com.onixbyte.webcal.config.Classification;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* The abstract sealed class {@code WebCalendarNode} represents a node in the
* web calendar, such as an event, a to-do item, or an alarm. It provides
* common properties and methods for all calendar components and events.
* <p>
* Subclasses of {@code WebCalendarNode} should implement the {@link
* #resolve()} method to generate the corresponding iCalendar content for the
* specific calendar component or event.
*
* @author Zihlu Wang
* @version 1.1.0
* @since 1.0.0
*/
public abstract class WebCalendarNode {
// Common properties for all calendar components and events
protected List<String> categories;
protected Classification classification;
protected String comment;
protected String description;
protected String location;
protected Integer percentComplete;
protected Integer priority;
protected String summary;
protected LocalDateTime end;
protected LocalDateTime start;
protected Duration duration;
protected String url;
protected String uid;
protected String domainName;
protected String timezone;
/**
* Constructor for WebCalendarNode class, initializes the list of
* categories associated with the calendar component or event.
*/
protected WebCalendarNode() {
this.categories = new ArrayList<>();
}
/**
* Set the domain name associated with the calendar component or event.
*
* @param domainName the domain name
* @return the WebCalendarNode object
*/
public WebCalendarNode setDomainName(String domainName) {
this.domainName = domainName;
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.
*
* @return the comma-separated string of categories
*/
protected String resolveCategories() {
var builder = new StringBuilder();
if (categories != null && !categories.isEmpty()) {
categories.forEach(item -> builder.append(item).append(","));
return builder.substring(0, builder.length() - 1);
}
return builder.toString();
}
/**
* Generate and resolve the iCalendar content for the calendar component or
* event.
*
* @return the resolved iCalendar content
*/
public abstract String resolve();
}
@@ -1,74 +0,0 @@
/*
* 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 com.onixbyte.webcal.config;
import lombok.Getter;
/**
* The {@code Classification} enum represents the classification levels of
* calendar content based on <b>RFC-5545</b>.
* <p>
* Calendar events or components can be classified as one of the following
* levels:
* <ul>
* <li>
* {@link #PUBLIC}: Indicates that the calendar content is public and
* can be freely distributed.
* </li>
* <li>
* {@link #PRIVATE}: Indicates that the calendar content is private and
* should not be shared with others.
* </li>
* <li>
* {@link #CONFIDENTIAL}: Indicates that the calendar content is
* confidential and should be kept strictly private.
* </li>
* </ul>
*
* @author Zihlu Wang
* @version 1.1.0
* @since 1.0.0
*/
public enum Classification {
/**
* Public classification level.
* <p>
* Indicates that the calendar content is public and can be freely
* distributed.
*/
PUBLIC,
/**
* Private classification level.
* <p>
* Indicates that the calendar content is private and should not be shared
* with others.
*/
PRIVATE,
/**
* Confidential classification level.
* <p>
* Indicates that the calendar content is confidential and should be kept
* strictly private.
*/
CONFIDENTIAL,
;
}
@@ -1,48 +0,0 @@
/*
* 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 com.onixbyte.webcal.config;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
/**
* A formatter to format {@link java.time.LocalDateTime}.
*
* @author Zihlu Wang
*/
public final class DateAndTimeFormatter {
/**
* Get the {@link java.time.format.DateTimeFormatter datetime formatter}
* with UTC pattern and timezone.
*
* @return the {@link java.time.format.DateTimeFormatter datetime formatter}
* with UTC pattern and timezone
*/
public static DateTimeFormatter getUtcDatetimeFormatter() {
if (Objects.isNull(utcDateTimeFormatter)) {
utcDateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'").withZone(ZoneOffset.UTC);
}
return utcDateTimeFormatter;
}
private static DateTimeFormatter utcDateTimeFormatter;
}
@@ -1,33 +0,0 @@
/*
* 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.
*/
/**
* The package {@code cn.org.codecrafters.webcal.config} contains classes
* related to the configuration and settings of the web calendar module. It
* provides various configurations and constants used in the generation and
* resolution of iCalendar content.
* <p>The classes in this package include:</p>
* <ul>
* <li>
* {@link com.onixbyte.webcal.config.Classification}: An enum
* representing the classification of events in the web calendar.
* </li>
* </ul>
*
* @since 1.0.0
*/
package com.onixbyte.webcal.config;
@@ -1,293 +0,0 @@
/*
* 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 com.onixbyte.webcal.impl;
import com.onixbyte.webcal.WebCalendarNode;
import com.onixbyte.webcal.config.Classification;
import com.onixbyte.webcal.config.DateAndTimeFormatter;
import java.text.MessageFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import java.util.UUID;
/**
* The {@code WebCalendarEvent} class represents an event in the web calendar.
* It extends the abstract class WebCalendarNode and provides additional
* methods to set properties specific to events.
* <p>
* Users can use the methods in this class to add categories, set the
* classification, add comments, descriptions, locations, set percent
* complete, set priority, set summary, set start time, set end time, set
* duration, set URL, set UID, and set timezone for the event. After setting
* the properties, users can call the {@link #resolve()} method to generate the
* corresponding iCalendar content for the event.
*
* @author Zihlu Wang
* @version 1.1.0
* @since 1.0.0
*/
public final class WebCalendarEvent extends WebCalendarNode {
/**
* Add categories to the event.
*
* @param categories the categories to add
* @return the WebCalendarEvent object
*/
public WebCalendarEvent addCategories(String... categories) {
this.categories.addAll(Arrays.asList(categories));
return this;
}
/**
* Add a collection of categories to the event.
*
* @param categories the collection of categories to add
* @return the WebCalendarEvent object
*/
public WebCalendarEvent addCategories(Collection<String> categories) {
this.categories.addAll(categories);
return this;
}
/**
* Add a single category to the event.
*
* @param category the category to add
* @return the WebCalendarEvent object
*/
public WebCalendarEvent addCategory(String category) {
this.categories.add(category);
return this;
}
/**
* Set the classification of the event.
*
* @param classification the classification to set
* @return the WebCalendarEvent object
*/
public WebCalendarEvent setClassification(Classification classification) {
this.classification = classification;
return this;
}
/**
* Set the comment for the event.
*
* @param comment the comment to set
* @return the WebCalendarEvent object
*/
public WebCalendarEvent setComment(String comment) {
this.comment = comment;
return this;
}
/**
* Set the description for the event.
*
* @param description the description to set
* @return the WebCalendarEvent object
*/
public WebCalendarEvent setDescription(String description) {
this.description = description;
return this;
}
/**
* Set the location for the event.
*
* @param location the location to set
* @return the WebCalendarEvent object
*/
public WebCalendarEvent setLocation(String location) {
this.location = location;
return this;
}
/**
* Set the percent complete for the event.
*
* @param percentComplete the percent complete to set
* @return the WebCalendarEvent object
* @throws IllegalArgumentException if the percent complete is out of range (0 ~ 100)
*/
public WebCalendarEvent setPercentComplete(Integer percentComplete) {
if (percentComplete < 0 || percentComplete > 100) {
throw new IllegalArgumentException("Percent out of range (0 ~ 100)");
}
this.percentComplete = percentComplete;
return this;
}
/**
* Set the priority for the event.
*
* @param priority the priority to set
* @return the WebCalendarEvent object
* @throws IllegalArgumentException if the priority is out of range (0 ~ 9)
*/
public WebCalendarEvent setPriority(Integer priority) {
if (priority < 0 || priority > 9) {
throw new IllegalArgumentException("The priority you provide is out of range (0 ~ 9).");
}
this.priority = priority;
return this;
}
/**
* Set the summary for the event.
*
* @param summary the summary to set
* @return the WebCalendarEvent object
*/
public WebCalendarEvent setSummary(String summary) {
this.summary = summary;
return this;
}
/**
* Set the end time for the event.
*
* @param end the end time to set
* @return the WebCalendarEvent object
* @throws IllegalStateException if the field DURATION has been set before
*/
public WebCalendarEvent setEnd(LocalDateTime end) {
if (this.duration != null) {
throw new IllegalStateException("You have set the field DURATION before, please remove it or remove setEnd.");
}
this.end = end;
return this;
}
/**
* Set the start time for the event.
*
* @param start the start time to set
* @return the WebCalendarEvent object
*/
public WebCalendarEvent setStart(LocalDateTime start) {
this.start = start;
return this;
}
/**
* Set the duration for the event.
*
* @param duration the duration to set
* @return the WebCalendarEvent object
* @throws IllegalStateException if the field END has been set before
*/
public WebCalendarEvent setDuration(Duration duration) {
if (this.end != null) {
throw new IllegalStateException("You have set the field END before, please remove it or remove setDuration.");
}
this.duration = duration;
return this;
}
/**
* Set the URL for the event.
*
* @param url the URL to set
* @return the WebCalendarEvent object
*/
public WebCalendarEvent setUrl(String url) {
this.url = url;
return this;
}
/**
* Set the UID for the event.
*
* @param uid the UID to set
* @return the WebCalendarEvent object
*/
public WebCalendarEvent setUid(String uid) {
this.uid = uid;
return this;
}
/**
* Set the domain name for the event.
*
* @param domainName the domain name to set
* @return the WebCalendarEvent object
*/
public WebCalendarEvent setDomainName(String domainName) {
this.domainName = domainName;
return this;
}
/**
* Set the timezone for the event.
*
* @param timezone the timezone to set
* @return the WebCalendarEvent object
*/
public WebCalendarEvent setTimezone(String timezone) {
this.timezone = timezone;
return this;
}
/**
* Generate and resolve the iCalendar content for the event.
*
* @return the resolved iCalendar content for the event
*/
@Override
public String resolve() {
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}""",
/* 0 - tag */TAG,
/* 1 - uid */ Optional.ofNullable(uid).orElse(UUID.randomUUID().toString()) + "@" + domainName,
/* 2 - dtstamp */ now.format(DateAndTimeFormatter.getUtcDatetimeFormatter()),
/* 3 - start time */ start.atZone(ZoneId.systemDefault()).format(DateAndTimeFormatter.getUtcDatetimeFormatter()),
/* 4 - summary */ Optional.ofNullable(summary).map((item) -> "\nSUMMARY:" + item).orElse(""),
/* 5 - categories */ Optional.ofNullable(categories)
.map((item) -> !item.isEmpty() ? "\nCATEGORIES:" + resolveCategories() : null).orElse(""),
/* 6 - duration */ Optional.ofNullable(duration)
.map((_duration) -> String.valueOf(_duration.getSeconds()))
.orElse(Optional.ofNullable(end)
.map((_end) -> String.valueOf(Duration.between(_end, start).getSeconds()))
.orElse("0")),
/* 7 - classification */ Optional.ofNullable(classification).map((_classification) -> "\nCLASS:" + _classification + "\n").orElse(""),
/* 8 - comment */ Optional.ofNullable(comment).map((_comment) -> "\nCOMMENT:" + _comment + "\n").orElse(""),
/* 9 - location */ Optional.ofNullable(location).map((_location) -> "\nLOCATION:" + _location).orElse(""),
/* 10 = percentComplete */ Optional.ofNullable(percentComplete).map((_percentComplete) -> "\nPERCENT-COMPLETE:" + _percentComplete).orElse(""),
/* 11 - description */ Optional.ofNullable(description).map((_description) -> "\nDESCRIPTION:" + _description).orElse(""),
/* 12 - priority */ Optional.ofNullable(priority).map((_priority) -> "\nPRIORITY:" + _priority).orElse("")
);
}
private final static String TAG = "VEVENT";
}
@@ -1,43 +0,0 @@
/*
* 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.
*/
/**
* The package {@code cn.org.codecrafters.webcal} contains classes and modules
* related to web calendar generation and resolution. It provides functionality
* to create and manage iCalendar content for web-based calendar applications.
* <p>
* The main classes and modules in this package include:
* <ul>
* <li>
* {@link com.onixbyte.webcal.WebCalendar}: A class for
* generating web calendars with customisable settings and events.
* </li>
* <li>
* {@link com.onixbyte.webcal.impl.WebCalendarEvent}: A class
* representing a single event in a web calendar with various
* attributes and options.
* </li>
* <li>
* {@link com.onixbyte.webcal.WebCalendarNode}: An abstract
* class serving as the base class for web calendar nodes, providing
* common attributes and functionality for events.
* </li>
* </ul>
*
* @since 1.0.0
*/
package com.onixbyte.webcal;
-31
View File
@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<configuration>
<property name="COLOURFUL_OUTPUT" value="%black(%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK}) %highlight(%-5level) %black(---) %black([%10.10t]) %cyan(%-20.20logger{20}) %black(:) %msg%n"/>
<property name="STANDARD_OUTPUT" value="%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK} %-5level %black(---) [%10.10t] %-20.20logger{20} : %msg%n"/>
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${COLOURFUL_OUTPUT}</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
@@ -1,56 +0,0 @@
/*
* 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 com.onixbyte.webcal.test;
import com.onixbyte.webcal.WebCalendar;
import com.onixbyte.webcal.impl.WebCalendarEvent;
import com.onixbyte.webcal.config.Classification;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.util.UUID;
/**
* TestWebCalendar
*
* @author Zihlu Wang
*/
@Slf4j
public class TestWebCalendar {
@Test
void testWebCalendar() {
var calendar = new WebCalendar();
calendar.setCompanyName("Code Crafters")
.setDomainName("codecrafters.org.cn")
.setName("Code Crafters SPECIAL EVENT")
.setProductName("Code Crafters SPECIAL EVENT");
calendar.addEvent(new WebCalendarEvent()
.setClassification(Classification.PUBLIC)
.setStart(LocalDateTime.of(2023, 8, 6, 0, 0, 0))
.setEnd(LocalDateTime.of(2023, 8, 6, 8, 0, 0))
.setLocation("Hong Kong University, Pokfulam, Central West, Hong Kong S.A.R")
.setUid(UUID.randomUUID().toString())
.setTimezone("Asia/Hong_Kong"));
System.out.println(calendar.resolve());
}
}