Skip to content

Commit

Permalink
Refactored data type and atomic item implementations to move casting …
Browse files Browse the repository at this point in the history
…operations to the atomic item implementations. This creates a cleaner isolation between the type adapters and Metapath items.
  • Loading branch information
david-waltermire committed Nov 12, 2024
1 parent fc1413e commit d73da15
Show file tree
Hide file tree
Showing 99 changed files with 1,516 additions and 479 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public String getName() {

@Override
public String getVersion() {
return CLOSEST_TAG;
return BUILD_VERSION;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,4 @@ public TYPE copy(Object obj) {
// method.
return ((TYPE) obj).copy();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;

import gov.nist.secauto.metaschema.core.metapath.function.InvalidValueForCastFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.model.util.JsonUtil;
import gov.nist.secauto.metaschema.core.model.util.XmlEventUtil;
Expand Down Expand Up @@ -197,46 +196,47 @@ public void writeJsonValue(Object value, JsonGenerator generator) throws IOExcep

@Override
public abstract ITEM_TYPE newItem(Object value);

@SuppressWarnings("unchecked")
@Override
public ITEM_TYPE cast(IAnyAtomicItem item) {
if (item == null) {
throw new InvalidValueForCastFunctionException("item is null");
}
return getItemClass().isAssignableFrom(item.getClass())
? (ITEM_TYPE) item
: castInternal(item);
}

/**
* Attempt to cast the provided item to this adapter's item type.
* <p>
* The default implementation of this will attempt to parse the provided item as
* a string using the {@link #parse(String)} method. If this behavior is
* undesirable, then a subclass should override this method.
*
* @param item
* the item to cast
* @return the item casted to this adapter's item type
* @throws InvalidValueForCastFunctionException
* if the casting of the item is not possible because the item
* represents an invalid value for this adapter's item type
*/
@NonNull
protected ITEM_TYPE castInternal(@NonNull IAnyAtomicItem item) {
// try string based casting as a fallback
String itemString;
try {
itemString = item.asString();
TYPE value = parse(itemString);
return newItem(value);
} catch (IllegalArgumentException | IllegalStateException ex) {
throw new InvalidValueForCastFunctionException(
String.format("The value '%s' is not compatible with the type '%s'",
item.getValue(),
getItemClass().getName()),
ex);
}
}
//
// @SuppressWarnings("unchecked")
// @Override
// public ITEM_TYPE cast(IAnyAtomicItem item) {
// if (item == null) {
// throw new InvalidValueForCastFunctionException("item is null");
// }
// return getItemClass().isAssignableFrom(item.getClass())
// ? (ITEM_TYPE) item
// : castInternal(item);
// }
//
// /**
// * Attempt to cast the provided item to this adapter's item type.
// * <p>
// * The default implementation of this will attempt to parse the provided item
// as
// * a string using the {@link #parse(String)} method. If this behavior is
// * undesirable, then a subclass should override this method.
// *
// * @param item
// * the item to cast
// * @return the item casted to this adapter's item type
// * @throws InvalidValueForCastFunctionException
// * if the casting of the item is not possible because the item
// * represents an invalid value for this adapter's item type
// */
// @NonNull
// protected ITEM_TYPE castInternal(@NonNull IAnyAtomicItem item) {
// // try string based casting as a fallback
// String itemString;
// try {
// itemString = item.asString();
// TYPE value = parse(itemString);
// return newItem(value);
// } catch (IllegalArgumentException | IllegalStateException ex) {
// throw new InvalidValueForCastFunctionException(
// String.format("The value '%s' is not compatible with the type '%s'",
// item.getValue(),
// getItemClass().getName()),
// ex);
// }
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes;

import gov.nist.secauto.metaschema.core.metapath.function.InvalidValueForCastFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

Expand Down Expand Up @@ -142,19 +141,19 @@ default boolean isAtomic() {
// TODO: move to IAnyAtomicItem
@NonNull
IAnyAtomicItem newItem(@NonNull Object value);

/**
* Cast the provided item to an item of this type, if possible.
*
* @param item
* the atomic item to cast
* @return an atomic item of this type
* @throws InvalidValueForCastFunctionException
* if the provided item type cannot be cast to this item type
*/
// TODO: move to IAnyAtomicItem
@NonNull
IAnyAtomicItem cast(IAnyAtomicItem item);
//
// /**
// * Cast the provided item to an item of this type, if possible.
// *
// * @param item
// * the atomic item to cast
// * @return an atomic item of this type
// * @throws InvalidValueForCastFunctionException
// * if the provided item type cannot be cast to this item type
// */
// // TODO: move to IAnyAtomicItem
// @NonNull
// IAnyAtomicItem cast(IAnyAtomicItem item);

/**
* Determines if adapter can parse the next element. The next element's
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ public JsonFormatTypes getJsonRawType() {

@Override
public BigInteger parse(String value) {
return new BigInteger(value);
try {
return new BigInteger(value);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException(ex);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@

import edu.umd.cs.findbugs.annotations.NonNull;

/**
* Support for the Metaschema <a href=
* "https://pages.nist.gov/metaschema/specification/datatypes/#base64">base64</a>
* data type.
*/
public class Base64Adapter
extends AbstractDataTypeAdapter<ByteBuffer, IBase64BinaryItem> {
@NonNull
Expand All @@ -43,12 +48,11 @@ public JsonFormatTypes getJsonRawType() {
return JsonFormatTypes.STRING;
}

@SuppressWarnings("null")
@Override
public ByteBuffer parse(String value) {
Base64.Decoder decoder = Base64.getDecoder();
byte[] result = decoder.decode(value);
return ByteBuffer.wrap(result);
return ObjectUtils.notNull(ByteBuffer.wrap(result));
}

@Override
Expand All @@ -62,11 +66,10 @@ public ByteBuffer copy(Object obj) {
return clone;
}

@SuppressWarnings("null")
@Override
public String asString(Object value) {
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(((ByteBuffer) value).array());
return ObjectUtils.notNull(encoder.encodeToString(((ByteBuffer) value).array()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@

import gov.nist.secauto.metaschema.core.datatype.AbstractDataTypeAdapter;
import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidValueForCastFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.INumericItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import java.io.IOException;
Expand Down Expand Up @@ -92,57 +88,4 @@ public IBooleanItem newItem(Object value) {
return IBooleanItem.valueOf(item);
}

@Override
protected IBooleanItem castInternal(@NonNull IAnyAtomicItem item) {
IBooleanItem retval;
if (item instanceof INumericItem) {
retval = castToBoolean((INumericItem) item);
} else if (item instanceof IStringItem) {
retval = castToBoolean((IStringItem) item);
} else {
try {
retval = castToBoolean(item.asStringItem());
} catch (IllegalStateException ex) {
throw new InvalidValueForCastFunctionException(ex.getLocalizedMessage(), ex);
}
}
return retval;
}

/**
* Cast the provided numeric value to a boolean. Any non-zero value will be
* {@code true}, or {@code false} otherwise.
*
* @param item
* the item to cast
* @return {@code true} if the item value is non-zero, or {@code false}
* otherwise
*/
@NonNull
protected IBooleanItem castToBoolean(@NonNull INumericItem item) {
return IBooleanItem.valueOf(item.toEffectiveBoolean());
}

/**
* If the string is a numeric value, treat it as so. Otherwise parse the value
* as a boolean string.
*
* @param item
* the item to cast
* @return the effective boolean value of the string
* @throws InvalidValueForCastFunctionException
* if the provided item cannot be cast to a boolean value by any means
*/
@NonNull
protected IBooleanItem castToBoolean(@NonNull IStringItem item) {
IBooleanItem retval;
try {
INumericItem numeric = INumericItem.cast(item);
retval = castToBoolean(numeric);
} catch (InvalidValueForCastFunctionException ex) {
retval = super.castInternal(item);
}
return retval;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@
import gov.nist.secauto.metaschema.core.datatype.AbstractCustomJavaDataTypeAdapter;
import gov.nist.secauto.metaschema.core.datatype.object.Date;
import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidValueForCastFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDateItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDateTimeItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IUntypedAtomicItem;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import java.time.LocalDate;
Expand All @@ -32,18 +27,25 @@

import edu.umd.cs.findbugs.annotations.NonNull;

/**
* Support for the Metaschema <a href=
* "https://pages.nist.gov/metaschema/specification/datatypes/#date">date</a>
* data type.
*/
public class DateAdapter
extends AbstractCustomJavaDataTypeAdapter<Date, IDateItem> {
@NonNull
private static final List<QName> NAMES = ObjectUtils.notNull(
List.of(new QName(MetapathConstants.NS_METAPATH.toASCIIString(), "date")));
private static final Pattern DATE_TIMEZONE = Pattern.compile("^("
+ "^(?:(?:2000|2400|2800|(?:19|2[0-9](?:0[48]|[2468][048]|[13579][26])))-02-29)"
+ "|(?:(?:(?:19|2[0-9])[0-9]{2})-02-(?:0[1-9]|1[0-9]|2[0-8]))"
+ "|(?:(?:(?:19|2[0-9])[0-9]{2})-(?:0[13578]|10|12)-(?:0[1-9]|[12][0-9]|3[01]))"
+ "|(?:(?:(?:19|2[0-9])[0-9]{2})-(?:0[469]|11)-(?:0[1-9]|[12][0-9]|30))"
+ ")"
+ "(Z|[+-][0-9]{2}:[0-9]{2})?$");
@NonNull
private static final Pattern DATE_TIMEZONE = ObjectUtils.notNull(
Pattern.compile("^("
+ "^(?:(?:2000|2400|2800|(?:19|2[0-9](?:0[48]|[2468][048]|[13579][26])))-02-29)"
+ "|(?:(?:(?:19|2[0-9])[0-9]{2})-02-(?:0[1-9]|1[0-9]|2[0-8]))"
+ "|(?:(?:(?:19|2[0-9])[0-9]{2})-(?:0[13578]|10|12)-(?:0[1-9]|[12][0-9]|3[01]))"
+ "|(?:(?:(?:19|2[0-9])[0-9]{2})-(?:0[469]|11)-(?:0[1-9]|[12][0-9]|30))"
+ ")"
+ "(Z|[+-][0-9]{2}:[0-9]{2})?$"));

DateAdapter() {
super(Date.class);
Expand Down Expand Up @@ -87,19 +89,9 @@ public Date parse(String value) {
@Override
public String asString(Object obj) {
Date value = (Date) obj;
String retval;
if (value.hasTimeZone()) {
@SuppressWarnings("null")
@NonNull
String formatted = DateFormats.DATE_WITH_TZ.format(value.getValue());
retval = formatted;
} else {
@SuppressWarnings("null")
@NonNull
String formatted = DateFormats.DATE_WITHOUT_TZ.format(value.getValue());
retval = formatted;
}
return retval;
return ObjectUtils.notNull(value.hasTimeZone()
? DateFormats.DATE_WITH_TZ.format(value.getValue())
: DateFormats.DATE_WITHOUT_TZ.format(value.getValue()));
}

@Override
Expand All @@ -112,20 +104,4 @@ public IDateItem newItem(Object value) {
Date item = toValue(value);
return IDateItem.valueOf(item);
}

@Override
@NonNull
protected IDateItem castInternal(@NonNull IAnyAtomicItem item) {
IDateItem retval;
if (item instanceof IDateTimeItem) {
ZonedDateTime value = ((IDateTimeItem) item).asZonedDateTime();
retval = IDateItem.valueOf(value);
} else if (item instanceof IStringItem || item instanceof IUntypedAtomicItem) {
retval = super.castInternal(item);
} else {
throw new InvalidValueForCastFunctionException(
String.format("unsupported item type '%s'", item.getClass().getName()));
}
return retval;
}
}
Loading

0 comments on commit d73da15

Please sign in to comment.