Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion connectors/citrus-openapi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
</dependency>
<dependency>
<groupId>com.atlassian.oai</groupId>
<artifactId>swagger-request-validator-core</artifactId>
<artifactId>openapi-request-validator-core</artifactId>
</dependency>

<!--
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private RandomConfiguration() {
// Note that the order of generators in the list is relevant, as the list is traversed from start to end, to find the first matching generator for a schema, and some generators match for less significant schemas.
generators.add(new RandomEnumGenerator());
generators.add(randomGeneratorBuilder(TYPE_STRING, FORMAT_DATE).build((randomContext, schema) -> randomContext.getRandomModelBuilder().appendSimpleQuoted("citrus:currentDate('yyyy-MM-dd')")));
generators.add(randomGeneratorBuilder(TYPE_STRING, FORMAT_DATE_TIME).build((randomContext, schema) -> randomContext.getRandomModelBuilder().appendSimpleQuoted("citrus:currentDate('yyyy-MM-dd'T'hh:mm:ssZ')")));
generators.add(randomGeneratorBuilder(TYPE_STRING, FORMAT_DATE_TIME).build((randomContext, schema) -> randomContext.getRandomModelBuilder().appendSimpleQuoted("citrus:currentDate('yyyy-MM-dd'T'hh:mm:ssXXX')")));
generators.add(randomGeneratorBuilder(TYPE_STRING, FORMAT_UUID).build((randomContext, schema) -> randomContext.getRandomModelBuilder().appendSimpleQuoted("citrus:randomUUID()")));
generators.add(randomGeneratorBuilder(TYPE_STRING, "email").build((randomContext, schema) -> randomContext.getRandomModelBuilder().appendSimpleQuoted("citrus:randomPattern('" + EMAIL_PATTERN + "')")));
generators.add(randomGeneratorBuilder(TYPE_STRING, "uri").build((randomContext, schema) -> randomContext.getRandomModelBuilder().appendSimpleQuoted("citrus:randomPattern('" + URI_PATTERN + "')")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,21 @@

package org.citrusframework.openapi.validation;

import java.util.List;
import javax.annotation.Nullable;

import com.atlassian.oai.validator.OpenApiInteractionValidator;
import com.atlassian.oai.validator.model.ApiOperation;
import com.atlassian.oai.validator.model.Request;
import com.atlassian.oai.validator.model.Response;
import com.atlassian.oai.validator.report.MessageResolver;
import com.atlassian.oai.validator.report.ValidationReport.Message;
import com.atlassian.oai.validator.schema.SchemaValidator;
import com.atlassian.oai.validator.schema.SwaggerV20Library;
import com.atlassian.oai.validator.whitelist.ValidationErrorsWhitelist;
import com.atlassian.oai.validator.whitelist.rule.WhitelistRule;
import io.swagger.v3.oas.models.OpenAPI;
import jakarta.annotation.Nonnull;

import javax.annotation.Nullable;
import java.util.List;

/**
* Represents the context for OpenAPI validation, providing configuration and validators for request and response validation.
* This context maintains settings for both request and response validation, which can be controlled at an instance level.
Expand Down Expand Up @@ -82,7 +81,7 @@ public OpenAPI getSwaggerOpenApi() {

public synchronized @Nonnull SchemaValidator getSchemaValidator() {
if (schemaValidator == null) {
schemaValidator = new SchemaValidator(openApi, new MessageResolver(), SwaggerV20Library::schemaFactory);
schemaValidator = new SchemaValidator(openApi, new MessageResolver());
}
return schemaValidator;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,80 +16,90 @@

package org.citrusframework.functions.core;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;

import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.exceptions.InvalidFunctionUsageException;
import org.citrusframework.functions.ParameterizedFunction;
import org.citrusframework.util.StringUtils;
import org.citrusframework.yaml.SchemaProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.List;

import static org.citrusframework.util.StringUtils.hasText;

/**
* Function changes given date value by adding/subtracting day/month/year/hour/minute
* offset values. Class uses special date format to parse date string to Calendar instance.
* Function changes given date value by adding/subtracting day/month/year/hour/minute offset values.
* Class uses a date format to parse date string to an {@link OffsetDateTime}.
*
* @since 1.3.1
*/
public class ChangeDateFunction implements ParameterizedFunction<ChangeDateFunction.Parameters> {

/** Logger */
private static final Logger logger = LoggerFactory.getLogger(ChangeDateFunction.class);

private final CalendarProvider calendarProvider = new CalendarProvider();

@Override
public String execute(Parameters params, TestContext context) {
Calendar calendar = calendarProvider.getInstance();
DateTimeFormatter dateFormat = hasText(params.getDateFormat())
? DateTimeFormatter.ofPattern(params.getDateFormat())
: DateTimeFormatter.ofPattern(DateFunctionHelper.getDefaultDateFormat().toPattern());

SimpleDateFormat dateFormat;
String result;

if (StringUtils.hasText(params.getDateFormat())) {
dateFormat = new SimpleDateFormat(params.getDateFormat());
} else {
dateFormat = DateFunctionHelper.getDefaultDateFormat();
}
OffsetDateTime date;

try {
calendar.setTime(dateFormat.parse(params.getValue()));
} catch (ParseException e) {
date = parseDate(params.getValue(), dateFormat);
} catch (RuntimeException e) {
throw new CitrusRuntimeException(e);
}

if (StringUtils.hasText(params.getOffset())) {
DateFunctionHelper.applyDateOffset(calendar, params.getOffset());
if (hasText(params.getOffset())) {
date = applyDateOffset(date, params.getOffset());
}

try {
result = dateFormat.format(calendar.getTime());
return date.format(dateFormat);
} catch (RuntimeException e) {
logger.error("Error while formatting dateParameter value ", e);
throw new CitrusRuntimeException(e);
}

return result;
}

@Override
public Parameters getParameters() {
return new Parameters();
}

static class CalendarProvider {
private OffsetDateTime parseDate(String value, DateTimeFormatter formatter) {
TemporalAccessor parsed = formatter.parseBest(value, OffsetDateTime::from, LocalDateTime::from, LocalDate::from);

private CalendarProvider () {
// This class allows mocking in unit tests
if (parsed instanceof OffsetDateTime offsetDateTime) {
return offsetDateTime;
}

Calendar getInstance() {
return Calendar.getInstance();
if (parsed instanceof LocalDateTime localDateTime) {
ZoneId zone = ZoneId.systemDefault();
return localDateTime.atZone(zone).toOffsetDateTime();
}

LocalDate localDate = (LocalDate) parsed;
ZoneId zone = ZoneId.systemDefault();
return localDate.atStartOfDay(zone).toOffsetDateTime();
}

private OffsetDateTime applyDateOffset(OffsetDateTime date, String offset) {
return date
.plusYears(DateFunctionHelper.getDateValueOffset(offset, 'y'))
.plusMonths(DateFunctionHelper.getDateValueOffset(offset, 'M'))
.plusDays(DateFunctionHelper.getDateValueOffset(offset, 'd'))
.plusHours(DateFunctionHelper.getDateValueOffset(offset, 'h'))
.plusMinutes(DateFunctionHelper.getDateValueOffset(offset, 'm'))
.plusSeconds(DateFunctionHelper.getDateValueOffset(offset, 's'));
}

public static class Parameters implements FunctionParameters {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,57 +16,60 @@

package org.citrusframework.functions.core;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;

import org.citrusframework.context.TestContext;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.functions.ParameterizedFunction;
import org.citrusframework.util.StringUtils;
import org.citrusframework.yaml.SchemaProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.TimeZone;

import static org.citrusframework.functions.core.DateFunctionHelper.applyDateOffset;
import static org.citrusframework.util.StringUtils.hasText;

/**
* Function returning the actual date as formatted string value. User specifies format string
* as argument. Function also supports additional date offset in order to manipulate result date value.
*
* Function returning the actual date as formatted string value.
* User specifies format string as argument.
* Function also supports additional date offset in order to manipulate result date value.
*/
public class CurrentDateFunction implements ParameterizedFunction<CurrentDateFunction.Parameters> {

/** Logger */
private static final Logger logger = LoggerFactory.getLogger(CurrentDateFunction.class);

@Override
public String execute(Parameters params, TestContext context) {
Calendar calendar = Calendar.getInstance();

SimpleDateFormat dateFormat;
String result;
if (StringUtils.hasText(params.getDateFormat())) {
dateFormat = new SimpleDateFormat(params.getDateFormat());
} else {
dateFormat = DateFunctionHelper.getDefaultDateFormat();
}
ZoneId zone = hasText(params.getTimeZone())
? TimeZone.getTimeZone(normalizeTimeZoneId(params.getTimeZone())).toZoneId()
: ZoneId.systemDefault();

if (StringUtils.hasText(params.getOffset())) {
DateFunctionHelper.applyDateOffset(calendar, params.getOffset());
OffsetDateTime date = OffsetDateTime.now(zone);
if (hasText(params.getOffset())) {
date = applyDateOffset(date, params.getOffset());
}

if (StringUtils.hasText(params.getTimeZone())) {
dateFormat.setTimeZone(TimeZone.getTimeZone(params.getTimeZone()));
}
DateTimeFormatter formatter = hasText(params.getDateFormat())
? DateTimeFormatter.ofPattern(params.getDateFormat())
: DateTimeFormatter.ofPattern(DateFunctionHelper.getDefaultDateFormat().toPattern());

try {
result = dateFormat.format(calendar.getTime());
return date.format(formatter);
} catch (RuntimeException e) {
logger.error("Error while formatting date value ", e);
logger.error("Error while formatting date value!", e);
throw new CitrusRuntimeException(e);
}
}

private String normalizeTimeZoneId(String timeZone) {
if (timeZone.startsWith("UTC+") || timeZone.startsWith("UTC-")) {
return "GMT" + timeZone.substring(3);
}

return result;
return timeZone;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
package org.citrusframework.functions.core;

import java.text.SimpleDateFormat;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Calendar;

import static java.lang.Integer.parseInt;

/**
* Abstract date value handling function provides base date value manipulation helpers.
* @since 1.3.1
*/
public final class DateFunctionHelper {
final class DateFunctionHelper {

private DateFunctionHelper() {
//prevent instantiation of utility class.
Expand All @@ -36,13 +36,14 @@ private DateFunctionHelper() {
* Adds/removes date value offset by parsing offset string for
* year/month/day/hour/minute/second offsets.
*/
static void applyDateOffset(Calendar calendar, String offsetString) {
calendar.add(Calendar.YEAR, getDateValueOffset(offsetString, 'y'));
calendar.add(Calendar.MONTH, getDateValueOffset(offsetString, 'M'));
calendar.add(Calendar.DAY_OF_YEAR, getDateValueOffset(offsetString, 'd'));
calendar.add(Calendar.HOUR, getDateValueOffset(offsetString, 'h'));
calendar.add(Calendar.MINUTE, getDateValueOffset(offsetString, 'm'));
calendar.add(Calendar.SECOND, getDateValueOffset(offsetString, 's'));
static OffsetDateTime applyDateOffset(OffsetDateTime date, String offset) {
return date
.plusYears(DateFunctionHelper.getDateValueOffset(offset, 'y'))
.plusMonths(DateFunctionHelper.getDateValueOffset(offset, 'M'))
.plusDays(DateFunctionHelper.getDateValueOffset(offset, 'd'))
.plusHours(DateFunctionHelper.getDateValueOffset(offset, 'h'))
.plusMinutes(DateFunctionHelper.getDateValueOffset(offset, 'm'))
.plusSeconds(DateFunctionHelper.getDateValueOffset(offset, 's'));
}

/**
Expand Down
Loading
Loading