Skip to content

Commit

Permalink
Addressed incosistent handling of data type parsing calls to provide …
Browse files Browse the repository at this point in the history
…more consistent error reporting for data type related errors. Addresses GSA/fedramp-automation#823
  • Loading branch information
david-waltermire committed Nov 7, 2024
1 parent a3209a8 commit 0ca2520
Show file tree
Hide file tree
Showing 15 changed files with 159 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ public TYPE parse(XMLEventReader2 eventReader) throws IOException {
try {
while (!(nextEvent = eventReader.peek()).isEndElement()) {
if (!nextEvent.isCharacters()) {
throw new IOException(String.format("Invalid content '%s' at %s", XmlEventUtil.toString(nextEvent),
throw new IOException(String.format("Invalid content '%s' at %s",
XmlEventUtil.toString(nextEvent),
XmlEventUtil.toString(nextEvent.getLocation())));
}
Characters characters = nextEvent.asCharacters();
Expand Down Expand Up @@ -131,7 +132,9 @@ public TYPE parse(XMLEventReader2 eventReader) throws IOException {
public TYPE parse(JsonParser parser) throws IOException {
String value = parser.getValueAsString();
if (value == null) {
throw new IOException("Unable to null value as text");
throw new IOException(
String.format("Unable to get null value as text%s",
JsonUtil.generateLocationMessage(parser)));
}
// skip over value
parser.nextToken();
Expand Down Expand Up @@ -159,25 +162,34 @@ public void writeXmlValue(
StartElement parent,
XMLEventFactory2 eventFactory,
XMLEventWriter eventWriter)
throws IOException, XMLStreamException {
throws IOException {
try {
String content = asString(value);
Characters characters = eventFactory.createCharacters(content);
eventWriter.add(characters);
} catch (XMLStreamException ex) {
} catch (IllegalArgumentException | XMLStreamException ex) {
throw new IOException(ex);
}
}

@Override
public void writeXmlValue(Object value, QName parentName, XMLStreamWriter2 writer) throws XMLStreamException {
String content = asString(value);
writer.writeCharacters(content);
public void writeXmlValue(Object value, QName parentName, XMLStreamWriter2 writer) throws IOException {
String content;
try {
content = asString(value);
writer.writeCharacters(content);
} catch (IllegalArgumentException | XMLStreamException ex) {
throw new IOException(ex);
}
}

@Override
public void writeJsonValue(Object value, JsonGenerator generator) throws IOException {
generator.writeString(asString(value));
try {
generator.writeString(asString(value));
} catch (IllegalArgumentException ex) {
throw new IOException(ex);
}
}

@Override
Expand Down Expand Up @@ -214,13 +226,16 @@ public ITEM_TYPE cast(IAnyAtomicItem item) {
@NonNull
protected ITEM_TYPE castInternal(@NonNull IAnyAtomicItem item) {
// try string based casting as a fallback
String itemString = item.asString();
String itemString = null;
try {
itemString = item.asString();
TYPE value = parse(itemString);
return newItem(value);
} catch (IllegalArgumentException ex) {
} catch (IllegalArgumentException | IllegalStateException ex) {
throw new InvalidValueForCastFunctionException(
String.format("The value '%s' is not compatible with the type '%s'", itemString, getItemClass().getName()),
String.format("The value '%s' is not compatible with the type '%s'",
item.getValue(),
getItemClass().getName()),
ex);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

Expand Down Expand Up @@ -95,7 +94,7 @@ default QName getPreferredName() {
* @param value
* the data to formatted as a string
* @return a string
* @throws UnsupportedOperationException
* @throws IllegalArgumentException
* if the data type cannot be represented as a string
*/
@NonNull
Expand Down Expand Up @@ -127,6 +126,7 @@ default boolean isAtomic() {
*
* @return the java associated item type
*/
// TODO: move to IAnyAtomicItem
@NonNull
Class<? extends IAnyAtomicItem> getItemClass();

Expand All @@ -139,6 +139,7 @@ default boolean isAtomic() {
*/
// TODO: markup types are not atomic values.
// Figure out a better base type (i.e., IValuedItem)
// TODO: move to IAnyAtomicItem
@NonNull
IAnyAtomicItem newItem(@NonNull Object value);

Expand All @@ -151,6 +152,7 @@ default boolean isAtomic() {
* @throws InvalidValueForCastFunctionException
* if the provided item type cannot be cast to this item type
*/
// TODO: move to IAnyAtomicItem
@NonNull
IAnyAtomicItem cast(IAnyAtomicItem item);

Expand Down Expand Up @@ -203,6 +205,7 @@ default boolean isAtomic() {
* @throws IOException
* if a parsing error occurs
*/
// TODO: migrate code to XML parser implementation.
@NonNull
TYPE parse(@NonNull XMLEventReader2 eventReader) throws IOException;

Expand All @@ -215,6 +218,7 @@ default boolean isAtomic() {
* @throws IOException
* if a parsing error occurs
*/
// TODO: migrate code to JSON parser implementation.
@NonNull
TYPE parse(@NonNull JsonParser parser) throws IOException;

Expand Down Expand Up @@ -254,6 +258,7 @@ default Supplier<TYPE> parseAndSupply(@NonNull String value) throws IOException
* @see #parse(String)
* @see #parse(XMLEventReader2)
*/
// TODO: migrate code to XML parser implementation.
@NonNull
default Supplier<TYPE> parseAndSupply(@NonNull XMLEventReader2 eventReader) throws IOException {
TYPE retval = parse(eventReader);
Expand All @@ -274,6 +279,7 @@ default Supplier<TYPE> parseAndSupply(@NonNull XMLEventReader2 eventReader) thro
* @see #parse(String)
* @see #parse(JsonParser)
*/
// TODO: migrate code to JSON parser implementation.
@NonNull
default Supplier<TYPE> parseAndSupply(@NonNull JsonParser parser) throws IOException {
TYPE retval = parse(parser);
Expand All @@ -296,14 +302,13 @@ default Supplier<TYPE> parseAndSupply(@NonNull JsonParser parser) throws IOExcep
* the XML event factory used to generate XML writing events
* @param eventWriter
* the XML writer used to output XML as events
* @throws XMLStreamException
* if an unexpected error occurred while processing the XML output
* @throws IOException
* if an unexpected error occurred while writing to the output stream
*/
// TODO: migrate code to XML writer implementation.
void writeXmlValue(@NonNull Object instance, @NonNull StartElement parent, @NonNull XMLEventFactory2 eventFactory,
@NonNull XMLEventWriter eventWriter)
throws IOException, XMLStreamException;
throws IOException;

/**
* Writes the provided Java class instance data as XML. The parent element
Expand All @@ -319,11 +324,12 @@ void writeXmlValue(@NonNull Object instance, @NonNull StartElement parent, @NonN
* the qualified name of the XML data's parent element
* @param writer
* the XML writer used to output the XML data
* @throws XMLStreamException
* @throws IOException
* if an unexpected error occurred while processing the XML output
*/
// TODO: migrate code to XML writer implementation.
void writeXmlValue(@NonNull Object instance, @NonNull QName parentName, @NonNull XMLStreamWriter2 writer)
throws XMLStreamException;
throws IOException;

/**
* Writes the provided Java class instance as a JSON/YAML field value.
Expand All @@ -335,6 +341,7 @@ void writeXmlValue(@NonNull Object instance, @NonNull QName parentName, @NonNull
* @throws IOException
* if an unexpected error occurred while writing the JSON/YAML output
*/
// TODO: migrate code to JSON writer implementation.
void writeJsonValue(@NonNull Object instance, @NonNull JsonGenerator writer) throws IOException;

/**
Expand All @@ -343,6 +350,7 @@ void writeXmlValue(@NonNull Object instance, @NonNull QName parentName, @NonNull
*
* @return the default field name to use
*/
// TODO: migrate code to JSON implementations.
@NonNull
String getDefaultJsonValueKey();

Expand All @@ -352,6 +360,7 @@ void writeXmlValue(@NonNull Object instance, @NonNull QName parentName, @NonNull
*
* @return {@code true} if allowed, or {@code false} otherwise.
*/
// TODO: migrate code to XML implementations.
boolean isUnrappedValueAllowedInXml();

/**
Expand All @@ -360,5 +369,6 @@ void writeXmlValue(@NonNull Object instance, @NonNull QName parentName, @NonNull
* @return {@code true} if the datatype uses mixed text and element content in
* XML, or {@code false} otherwise
*/
// TODO: migrate code to XML implementations.
boolean isXmlMixed();
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ protected IBooleanItem castInternal(@NonNull IAnyAtomicItem item) {
} else if (item instanceof IStringItem) {
retval = castToBoolean((IStringItem) item);
} else {
retval = castToBoolean(item.asStringItem());
try {
retval = castToBoolean(item.asStringItem());
} catch (IllegalStateException ex) {
throw new InvalidValueForCastFunctionException(ex.getLocalizedMessage(), ex);
}
}
return retval;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDateTimeItem;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import java.time.DateTimeException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.List;
Expand Down Expand Up @@ -56,7 +57,15 @@ public ZonedDateTime parse(String value) {
@SuppressWarnings("null")
@Override
public String asString(Object value) {
return DateFormats.DATE_TIME_WITH_TZ.format((ZonedDateTime) value);
try {
return DateFormats.DATE_TIME_WITH_TZ.format((ZonedDateTime) value);
} catch (DateTimeException ex) {
throw new IllegalArgumentException(
String.format("The provided value '%s' cannot be formatted as a date/time value. %s",
value.toString(),
ex.getMessage()),
ex);
}
}

@SuppressWarnings("null")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDateItem;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import java.time.DateTimeException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.List;
Expand Down Expand Up @@ -68,7 +69,15 @@ public ZonedDateTime parse(String value) {
@SuppressWarnings("null")
@Override
public String asString(Object value) {
return DateFormats.DATE_WITH_TZ.format((ZonedDateTime) value);
try {
return DateFormats.DATE_WITH_TZ.format((ZonedDateTime) value);
} catch (DateTimeException ex) {
throw new IllegalArgumentException(
String.format("The provided value '%s' cannot be formatted as a date value. %s",
value.toString(),
ex.getMessage()),
ex);
}
}

@SuppressWarnings("null")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@ public JsonFormatTypes getJsonRawType() {
@SuppressWarnings("null")
@Override
public UUID parse(String value) {
return UUID.fromString(value);
try {
return UUID.fromString(value);
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException(
String.format("Value '%s' is not a valid UUID.", value),
ex);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,24 +54,32 @@ public void writeXmlValue(
StartElement parent,
XMLEventFactory2 eventFactory,
XMLEventWriter eventWriter)
throws XMLStreamException {
throws IOException {

IMarkupString<?> markupString = (IMarkupString<?>) value;

markupString.writeXHtml(
ObjectUtils.notNull(parent.getName().getNamespaceURI()),
eventFactory,
eventWriter);
try {
markupString.writeXHtml(
ObjectUtils.notNull(parent.getName().getNamespaceURI()),
eventFactory,
eventWriter);
} catch (XMLStreamException ex) {
throw new IOException(ex);
}
}

@Override
public void writeXmlValue(Object value, QName parentName, XMLStreamWriter2 streamWriter)
throws XMLStreamException {
throws IOException {
IMarkupString<?> markupString = (IMarkupString<?>) value;

markupString.writeXHtml(
ObjectUtils.notNull(parentName.getNamespaceURI()),
streamWriter);
try {
markupString.writeXHtml(
ObjectUtils.notNull(parentName.getNamespaceURI()),
streamWriter);
} catch (XMLStreamException ex) {
throw new IOException(ex);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ public static ISequence<IAnyAtomicItem> fnData(@NonNull ISequence<? extends IIte
* @param item
* the item to atomize
* @return the atomized result
* @throws InvalidTypeFunctionException
* if the item cannot be cast to an atomic value, most likely because
* it doesn't have a typed value
*/
@NonNull
public static IAnyAtomicItem fnDataItem(@NonNull IItem item) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
import gov.nist.secauto.metaschema.core.metapath.ISequence;
import gov.nist.secauto.metaschema.core.metapath.InvalidTypeMetapathException;
import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
Expand Down Expand Up @@ -103,7 +104,11 @@ public static IStringItem fnStringItem(@NonNull IItem item) {
if (item instanceof INodeItem) {
retval = IStringItem.valueOf(((INodeItem) item).stringValue());
} else if (item instanceof IAnyAtomicItem) {
retval = ((IAnyAtomicItem) item).asStringItem();
try {
retval = ((IAnyAtomicItem) item).asStringItem();
} catch (IllegalStateException ex) {
throw new InvalidTypeMetapathException(item, ex.getMessage(), ex);
}
} else {
throw new InvalidTypeFunctionException(InvalidTypeFunctionException.ARGUMENT_TO_STRING_IS_FUNCTION, item);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ static IDurationItem cast(@NonNull IAnyAtomicItem item) {
} else {
try {
retval = IDayTimeDurationItem.valueOf(item.asString());
} catch (IllegalArgumentException ex) {
} catch (IllegalStateException ex) {
try {
retval = IYearMonthDurationItem.valueOf(item.asString());
} catch (IllegalArgumentException ex2) {
} catch (IllegalStateException ex2) {
InvalidValueForCastFunctionException newEx = new InvalidValueForCastFunctionException(ex2);
newEx.addSuppressed(ex);
throw newEx; // NOPMD context as suppressed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ static IStringItem valueOf(@NonNull String value) {
*/
@NonNull
static IStringItem cast(@NonNull IAnyAtomicItem item) {
return item.asStringItem();
try {
return item.asStringItem();
} catch (IllegalStateException ex) {
throw new InvalidValueForCastFunctionException(ex.getLocalizedMessage(), ex);
}
}

@Override
Expand Down
Loading

0 comments on commit 0ca2520

Please sign in to comment.