com.helger.phive.result.json.PhiveJsonHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of phive-result Show documentation
Show all versions of phive-result Show documentation
phive - Philip Helger Integrative Validation Engine - Validation Result support (incl. JSON binding)
The newest version!
/*
* Copyright (C) 2014-2024 Philip Helger (www.helger.com)
* philip[at]helger[dot]com
*
* 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.helger.phive.result.json;
import java.net.MalformedURLException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.Nonempty;
import com.helger.commons.datetime.PDTWebDateHelper;
import com.helger.commons.error.IError;
import com.helger.commons.error.SingleError;
import com.helger.commons.error.level.EErrorLevel;
import com.helger.commons.error.level.IErrorLevel;
import com.helger.commons.error.list.ErrorList;
import com.helger.commons.error.text.ConstantHasErrorText;
import com.helger.commons.io.resource.ClassPathResource;
import com.helger.commons.io.resource.FileSystemResource;
import com.helger.commons.io.resource.IReadableResource;
import com.helger.commons.io.resource.URLResource;
import com.helger.commons.io.resource.inmemory.IMemoryReadableResource;
import com.helger.commons.io.resource.wrapped.IWrappedReadableResource;
import com.helger.commons.lang.StackTraceHelper;
import com.helger.commons.location.ILocation;
import com.helger.commons.location.SimpleLocation;
import com.helger.commons.mutable.MutableInt;
import com.helger.commons.state.ETriState;
import com.helger.commons.string.StringHelper;
import com.helger.diver.api.coord.DVRCoordinate;
import com.helger.json.IJson;
import com.helger.json.IJsonArray;
import com.helger.json.IJsonObject;
import com.helger.json.IJsonValue;
import com.helger.json.JsonArray;
import com.helger.json.JsonObject;
import com.helger.phive.api.EValidationType;
import com.helger.phive.api.IValidationType;
import com.helger.phive.api.artefact.ValidationArtefact;
import com.helger.phive.api.executorset.IValidationExecutorSet;
import com.helger.phive.api.executorset.ValidationExecutorSetRegistry;
import com.helger.phive.api.executorset.status.IValidationExecutorSetStatus;
import com.helger.phive.api.result.ValidationResult;
import com.helger.phive.api.result.ValidationResultList;
import com.helger.phive.api.source.IValidationSource;
import com.helger.phive.api.validity.EExtendedValidity;
import com.helger.phive.result.exception.PhiveRestoredException;
import com.helger.schematron.svrl.SVRLResourceError;
/**
* A utility class to create a common JSON representation of a PHIVE result. Use
* {@link #applyGlobalError(IJsonObject, String, long)} or
* {@link #applyValidationResultList(IJsonObject, IValidationExecutorSet, List, Locale, long, MutableInt, MutableInt)}
* to add the result to an arbitrary {@link IJsonObject}.
*
* @author Philip Helger
* @since 5.2.5
*/
@Immutable
public final class PhiveJsonHelper
{
public static final String JSON_ERRORLEVEL_SUCCESS = "SUCCESS";
public static final String JSON_ERRORLEVEL_WARN = "WARN";
public static final String JSON_ERRORLEVEL_ERROR = "ERROR";
public static final String JSON_TRISTATE_TRUE = "TRUE";
public static final String JSON_TRISTATE_FALSE = "FALSE";
public static final String JSON_TRISTATE_UNDEFINED = "UNDEFINED";
public static final String JSON_RESOURCE_ID = "resource";
public static final String JSON_LINE_NUM = "line";
public static final String JSON_COLUMN_NUM = "col";
public static final String JSON_ERROR_DATETIME = "errorDateTime";
public static final String JSON_ERROR_LEVEL = "errorLevel";
public static final String JSON_ERROR_ID = "errorID";
public static final String JSON_ERROR_FIELD_NAME = "errorFieldName";
public static final String JSON_ERROR_LOCATION_OBJ = "errorLocationObj";
public static final String JSON_ERROR_LOCATION_STR = "errorLocation";
public static final String JSON_ERROR_TEXT = "errorText";
public static final String JSON_EXCEPTION = "exception";
public static final String JSON_TEST = "test";
public static final String JSON_VESID = "vesid";
public static final String JSON_NAME = "name";
public static final String JSON_DEPRECATED = "deprecated";
public static final String JSON_STATUS = "status";
public static final String JSON_STATUS_LAST_MODIFICATION = "lastModification";
public static final String JSON_STATUS_TYPE = "type";
public static final String JSON_STATUS_VALID_FROM = "validFrom";
public static final String JSON_STATUS_VALID_TO = "validTo";
public static final String JSON_STATUS_DEPRECATION_REASON = "deprecationReason";
public static final String JSON_STATUS_REPLACEMENT_VESID = "replacementVesid";
public static final String JSON_SUCCESS = "success";
public static final String JSON_ARTIFACT_TYPE = "artifactType";
public static final String JSON_ARTIFACT_PATH_TYPE = "artifactPathType";
public static final String JSON_ARTIFACT_PATH = "artifactPath";
public static final String JSON_ITEMS = "items";
public static final String JSON_INTERRUPTED = "interrupted";
public static final String JSON_MOST_SEVERE_ERROR_LEVEL = "mostSevereErrorLevel";
public static final String JSON_RESULTS = "results";
public static final String JSON_DURATION_MS = "durationMS";
public static final String JSON_VES = "ves";
public static final String ARTIFACT_TYPE_INPUT_PARAMETER = "input-parameter";
public static final String ARTIFACT_PATH_NONE = "none";
private static final Logger LOGGER = LoggerFactory.getLogger (PhiveJsonHelper.class);
private PhiveJsonHelper ()
{}
public static boolean isConsideredError (@Nonnull final IErrorLevel aErrorLevel)
{
return aErrorLevel.isGE (EErrorLevel.ERROR);
}
public static boolean isConsideredWarning (@Nonnull final IErrorLevel aErrorLevel)
{
return aErrorLevel.isGE (EErrorLevel.WARN);
}
/**
* Get the JSON string of the error level. One of "ERROR"
,
* "WARN"
or "SUCCESS"
.
* See {@link #JSON_ERRORLEVEL_SUCCESS}, {@link #JSON_ERRORLEVEL_WARN},
* {@link #JSON_ERRORLEVEL_ERROR}
*
* @param aErrorLevel
* The error level to convert. May not be null
.
* @return A non-null
JSON value string.
*/
@Nonnull
@Nonempty
public static String getJsonErrorLevel (@Nonnull final IErrorLevel aErrorLevel)
{
ValueEnforcer.notNull (aErrorLevel, "ErrorLevel");
if (isConsideredError (aErrorLevel))
return JSON_ERRORLEVEL_ERROR;
if (isConsideredWarning (aErrorLevel))
return JSON_ERRORLEVEL_WARN;
return JSON_ERRORLEVEL_SUCCESS;
}
@Nullable
public static IErrorLevel getAsErrorLevel (@Nullable final String sErrorLevel)
{
if (JSON_ERRORLEVEL_ERROR.equals (sErrorLevel))
return EErrorLevel.ERROR;
if (JSON_ERRORLEVEL_WARN.equals (sErrorLevel))
return EErrorLevel.WARN;
if (JSON_ERRORLEVEL_SUCCESS.equals (sErrorLevel))
return EErrorLevel.SUCCESS;
return null;
}
/**
* Get the tri-state representation of the provided value. Either
* {@link #JSON_TRISTATE_TRUE} or {@link #JSON_TRISTATE_FALSE}.
*
* @param b
* boolean value to get converted.
* @return A non-null
JSON value string.
* @see #getJsonTriState(ETriState)
*/
@Nonnull
@Nonempty
public static String getJsonTriState (final boolean b)
{
return b ? JSON_TRISTATE_TRUE : JSON_TRISTATE_FALSE;
}
/**
* Get the tri-state representation of the provided value. Either
* {@link #JSON_TRISTATE_TRUE}, {@link #JSON_TRISTATE_FALSE} or
* {@link #JSON_TRISTATE_UNDEFINED}.
*
* @param eTriState
* Tri-state value to get converted. May not be null
.
* @return A non-null
JSON value string.
* @see #getJsonTriState(boolean)
*/
@Nonnull
public static String getJsonTriState (@Nonnull final ETriState eTriState)
{
ValueEnforcer.notNull (eTriState, "TriState");
if (eTriState.isUndefined ())
return JSON_TRISTATE_UNDEFINED;
return getJsonTriState (eTriState.isTrue ());
}
/**
* Convert the provided value into a tri-state value. Must be one of
* {@link #JSON_TRISTATE_TRUE}, {@link #JSON_TRISTATE_FALSE} or
* {@link #JSON_TRISTATE_UNDEFINED}.
*
* @param sTriState
* Source value. May be null
.
* @return null
if the provided value is unknown.
*/
@Nullable
public static ETriState getAsTriState (@Nullable final String sTriState)
{
if (JSON_TRISTATE_TRUE.equals (sTriState))
return ETriState.TRUE;
if (JSON_TRISTATE_FALSE.equals (sTriState))
return ETriState.FALSE;
if (JSON_TRISTATE_UNDEFINED.equals (sTriState))
return ETriState.UNDEFINED;
return null;
}
/**
* Get the JSON representation of a stack trace.
*
*
* {
* "class" : string,
* "message" : string?,
* "stackTrace" : string
* }
*
*
* @param t
* The exception to convert to a JSON object. May be null
.
* @return null
if the parameter is null
, the JSON
* object otherwise.
* @see PhiveRestoredException for a representation after reading
*/
@Nullable
public static IJsonObject getJsonStackTrace (@Nullable final Throwable t)
{
if (t == null)
return null;
if (t instanceof PhiveRestoredException)
return ((PhiveRestoredException) t).getAsJson ();
return new JsonObject ().add (PhiveRestoredException.JSON_CLASS, t.getClass ().getName ())
.addIfNotNull (PhiveRestoredException.JSON_MESSAGE, t.getMessage ())
.add (PhiveRestoredException.JSON_STACK_TRACE, StackTraceHelper.getStackAsString (t));
}
/**
* Get the JSON representation of a location.
*
*
* {
* "resource" : string?,
* "line" : number?,
* "col" : number?
* }
*
*
* @param aLocation
* The location to convert to a JSON object. May be null
.
* @return null
if the parameter is null
, the JSON
* object otherwise.
*/
@Nullable
public static IJsonObject getJsonErrorLocation (@Nullable final ILocation aLocation)
{
if (aLocation == null || !aLocation.isAnyInformationPresent ())
return null;
final IJsonObject ret = new JsonObject ();
if (aLocation.hasResourceID ())
ret.add (JSON_RESOURCE_ID, aLocation.getResourceID ());
if (aLocation.hasLineNumber ())
ret.add (JSON_LINE_NUM, aLocation.getLineNumber ());
if (aLocation.hasColumnNumber ())
ret.add (JSON_COLUMN_NUM, aLocation.getColumnNumber ());
return ret;
}
@Nullable
public static ILocation getAsErrorLocation (@Nullable final IJsonObject aObj)
{
if (aObj == null)
return null;
final String sResourceID = aObj.getAsString (JSON_RESOURCE_ID);
final int nLineNumber = aObj.getAsInt (JSON_LINE_NUM, -1);
final int nColumnNumber = aObj.getAsInt (JSON_COLUMN_NUM, -1);
if (StringHelper.hasNoText (sResourceID) && nLineNumber < 0 && nColumnNumber < 0)
return null;
return new SimpleLocation (sResourceID, nLineNumber, nColumnNumber);
}
/**
* Get the JSON representation of an error.
*
*
* {
* "errorLevel" : string,
* "errorID" : string?,
* "errorFieldName" : string?,
* "errorLocation" : object?,
* "test" : string?,
* "errorText" : string,
* "exception : object?
* }
*
*
* @param aErrorLevel
* The error level to use. May not be null
.
* @param sErrorID
* The ID of the error. May be null
.
* @param sErrorFieldName
* The field name of the error. May be null
.
* @param aErrorLocation
* The location of the error. May be null
.
* @param sTest
* The performed test (e.g. for Schematrons). May be null
.
* @param sErrorText
* The main error text. May not be null
.
* @param t
* The optional stack trace of the error. May be null
.
* @return The JSON object with the error. Never null
.
* @see #getJsonErrorLevel(IErrorLevel)
* @see #getJsonErrorLocation(ILocation)
* @see #getJsonStackTrace(Throwable)
* @see #getJsonError(IError, Locale)
*/
@Nonnull
public static IJsonObject getJsonError (@Nonnull final IErrorLevel aErrorLevel,
@Nullable final String sErrorID,
@Nullable final String sErrorFieldName,
@Nullable final ILocation aErrorLocation,
@Nullable final String sTest,
@Nonnull final String sErrorText,
@Nullable final Throwable t)
{
ValueEnforcer.notNull (aErrorLevel, "ErrorLevel");
ValueEnforcer.notNull (sErrorText, "ErrorText");
return new JsonErrorBuilder ().errorLevel (aErrorLevel)
.errorID (sErrorID)
.errorFieldName (sErrorFieldName)
.errorLocation (aErrorLocation)
.test (sTest)
.errorText (sErrorText)
.exception (t)
.build ();
}
/**
* Get the JSON representation of an error.
*
*
* {
* "errorLevel" : string,
* "errorID" : string?,
* "errorFieldName" : string?,
* "errorLocation" : object?,
* "test" : string?,
* "errorText" : string,
* "exception : object?
* }
*
*
* @param aError
* The structured error. May not be null
.
* @param aDisplayLocale
* The display locale to resolve the error text. May not be
* null
.
* @return The JSON object with the error. Never null
.
* @see #getJsonErrorLevel(IErrorLevel)
* @see #getJsonStackTrace(Throwable)
* @see #getJsonError(IErrorLevel, String, String, ILocation, String, String,
* Throwable)
*/
@Nonnull
public static IJsonObject getJsonError (@Nonnull final IError aError, @Nonnull final Locale aDisplayLocale)
{
return jsonErrorBuilder (aError, aDisplayLocale).build ();
}
/**
* Create an empty builder
*
* @return Never null
.
* @since 7.2.3
*/
@Nonnull
public static JsonErrorBuilder jsonErrorBuilder ()
{
return new JsonErrorBuilder ();
}
/**
* Create a builder that is pre-filled with the error details.
*
* @param aError
* The structured error. May not be null
.
* @param aDisplayLocale
* The display locale to resolve the error text. May not be
* null
.
* @return Never null
.
* @since 7.2.3
*/
@Nonnull
public static JsonErrorBuilder jsonErrorBuilder (@Nonnull final IError aError, @Nonnull final Locale aDisplayLocale)
{
ValueEnforcer.notNull (aError, "Error");
ValueEnforcer.notNull (aDisplayLocale, "DisplayLocale");
return new JsonErrorBuilder ().errorDateTime (aError.getErrorDateTime ())
.errorLevel (aError.getErrorLevel ())
.errorID (aError.getErrorID ())
.errorFieldName (aError.getErrorFieldName ())
.errorLocation (aError.hasErrorLocation () ? aError.getErrorLocation () : null)
.test (aError instanceof SVRLResourceError ? ((SVRLResourceError) aError).getTest ()
: null)
.errorText (aError.getErrorText (aDisplayLocale))
.exception (aError.getLinkedException ());
}
@Nonnull
public static IError getAsIError (@Nonnull final IJsonObject aObj)
{
final LocalDateTime aErrorDT = PDTWebDateHelper.getLocalDateTimeFromXSD (aObj.getAsString (JSON_ERROR_DATETIME));
final IErrorLevel aErrorLevel = getAsErrorLevel (aObj.getAsString (JSON_ERROR_LEVEL));
final String sErrorID = aObj.getAsString (JSON_ERROR_ID);
final String sErrorFieldName = aObj.getAsString (JSON_ERROR_FIELD_NAME);
// Try new structured version
ILocation aErrorLocation = getAsErrorLocation (aObj.getAsObject (JSON_ERROR_LOCATION_OBJ));
if (aErrorLocation == null)
{
final IJsonValue aErrorLocationValue = aObj.getAsValue (JSON_ERROR_LOCATION_STR);
if (aErrorLocationValue != null)
{
// It's a string - old version
aErrorLocation = new SimpleLocation (aErrorLocationValue.getAsString ());
}
}
final String sErrorText = aObj.getAsString (JSON_ERROR_TEXT);
final String sTest = aObj.getAsString (JSON_TEST);
final PhiveRestoredException aLinkedException = PhiveRestoredException.createFromJson (aObj.getAsObject (JSON_EXCEPTION));
if (sTest != null)
return new SVRLResourceError (aErrorDT,
aErrorLevel,
sErrorID,
sErrorFieldName,
aErrorLocation,
new ConstantHasErrorText (sErrorText),
aLinkedException,
sTest);
return new SingleError (aErrorDT,
aErrorLevel,
sErrorID,
sErrorFieldName,
aErrorLocation,
new ConstantHasErrorText (sErrorText),
aLinkedException);
}
/**
* Create the VES details as a JSON Object.
*
*
* {
* "vesid" : string,
* "name" : string,
* "deprecated" : boolean,
* "status" : {
* "lastModification" : dateTime
* "type" : string,
* "validFrom" : string?,
* "validTo" : string?,
* "deprecationReason" : string?
* "replacementVesid" : string?
* }
* }
*
*
* @param aVES
* The VES to use. May not be null
.
* @return The created JSON object.
*/
@Nonnull
public static IJsonObject getJsonVES (@Nonnull final IValidationExecutorSet > aVES)
{
ValueEnforcer.notNull (aVES, "VES");
final IValidationExecutorSetStatus aStatus = aVES.getStatus ();
final IJsonObject aStatusJson = new JsonObject ().add (JSON_STATUS_LAST_MODIFICATION,
PDTWebDateHelper.getAsStringXSD (aStatus.getStatusLastModification ()))
.add (JSON_STATUS_TYPE, aStatus.getType ().getID ())
.addIfNotNull (JSON_STATUS_VALID_FROM,
PDTWebDateHelper.getAsStringXSD (aStatus.getValidFrom ()))
.addIfNotNull (JSON_STATUS_VALID_TO,
PDTWebDateHelper.getAsStringXSD (aStatus.getValidTo ()))
.addIfNotEmpty (JSON_STATUS_DEPRECATION_REASON,
aStatus.getDeprecationReason ());
if (aStatus.hasReplacementVESID ())
aStatusJson.add (JSON_STATUS_REPLACEMENT_VESID, aStatus.getReplacementVESID ().getAsSingleID ());
return new JsonObject ().add (JSON_VESID, aVES.getID ().getAsSingleID ())
.add (JSON_NAME, aVES.getDisplayName ())
.add (JSON_DEPRECATED, aStatus.isDeprecated ())
.addJson (JSON_STATUS, aStatusJson);
}
/**
* Add one global error to the response. Afterwards no validation results
* should be added. The layout of the response object is very similar to the
* one created by
* {@link #applyValidationResultList(IJsonObject, IValidationExecutorSet, List, Locale, long, MutableInt, MutableInt)}.
*
*
*
* {
* "success" : boolean,
* "interrupted" : boolean,
* "mostSevereErrorLevel" : string,
* "results" : array {
* "success" : string, // as defined by {@link #getJsonTriState(ETriState)}
* "artifactType" : string,
* "artifactPath" : string,
* "items" : array {
* error structure as in {@link #getJsonError(IError, Locale)}
* }
* },
* "durationMS" : number
* }
*
*
* @param aResponse
* The response JSON object to add to. May not be null
.
* @param sErrorMsg
* The error message to use. May not be null
.
* @param nDurationMilliseconds
* The duration of the validation in milliseconds. Must be ≥ 0.
*/
public static void applyGlobalError (@Nonnull final IJsonObject aResponse,
@Nonnull final String sErrorMsg,
@Nonnegative final long nDurationMilliseconds)
{
ValueEnforcer.notNull (aResponse, "Response");
ValueEnforcer.notNull (sErrorMsg, "ErrorMsg");
ValueEnforcer.isGE0 (nDurationMilliseconds, "DurationMilliseconds");
final IJsonArray aResultArray = new JsonArray ();
aResultArray.add (new JsonObject ().add (JSON_SUCCESS, getJsonTriState (false))
.add (JSON_ARTIFACT_TYPE, ARTIFACT_TYPE_INPUT_PARAMETER)
.add (JSON_ARTIFACT_PATH, ARTIFACT_PATH_NONE)
.addJson (JSON_ITEMS,
new JsonArray (jsonErrorBuilder ().errorLevel (EErrorLevel.ERROR)
.errorText (sErrorMsg)
.build ())));
aResponse.add (JSON_SUCCESS, false);
aResponse.add (JSON_INTERRUPTED, false);
aResponse.add (JSON_MOST_SEVERE_ERROR_LEVEL, getJsonErrorLevel (EErrorLevel.ERROR));
aResponse.addJson (JSON_RESULTS, aResultArray);
aResponse.add (JSON_DURATION_MS, nDurationMilliseconds);
}
@Nonnull
@Nonempty
public static String getArtifactPathType (@Nonnull final IReadableResource aRes)
{
if (aRes instanceof ClassPathResource)
return "classpath";
if (aRes instanceof FileSystemResource)
return "file";
if (aRes instanceof URLResource)
return "url";
if (aRes instanceof IMemoryReadableResource)
return "in-memory";
if (aRes instanceof IWrappedReadableResource)
return "wrapped";
return "unknown";
}
/**
* Apply the results of a full validation onto a JSON object.The layout of the
* response object is very similar to the one created by
* {@link #applyGlobalError(IJsonObject, String, long)}.
*
*
* {
* "ves" : object as defined by {@link #getJsonVES(IValidationExecutorSet)}
* "success" : boolean,
* "interrupted" : boolean,
* "mostSevereErrorLevel" : string,
* "results" : array {
* "success" : string, // as defined by {@link #getJsonTriState(ETriState)}
* "artifactType" : string,
* "artifactPathType" : string?,
* "artifactPath" : string,
* "items" : array {
* error structure as in {@link #getJsonError(IError, Locale)}
* }
* },
* "durationMS" : number
* }
*
*
* @param aResponse
* The response JSON object to add to. May not be null
.
* @param aVES
* The Validation executor set that was used to perform validation. May
* be null
.
* @param aValidationResultList
* The validation result list containing the validation results per
* layer. May not be null
.
* @param aDisplayLocale
* The display locale to be used. May not be null
.
* @param nDurationMilliseconds
* The duration of the validation in milliseconds. Must be ≥ 0.
* @param aWarningCount
* Optional callback value to store the overall warnings. If not
* null
if will contain a ≥ 0 value afterwards.
* @param aErrorCount
* Optional callback value to store the overall errors. If not
* null
if will contain a ≥ 0 value afterwards.
*/
public static void applyValidationResultList (@Nonnull final IJsonObject aResponse,
@Nullable final IValidationExecutorSet > aVES,
@Nonnull final List extends ValidationResult> aValidationResultList,
@Nonnull final Locale aDisplayLocale,
@Nonnegative final long nDurationMilliseconds,
@Nullable final MutableInt aWarningCount,
@Nullable final MutableInt aErrorCount)
{
new JsonValidationResultListHelper ().ves (aVES)
.warningCount (aWarningCount)
.errorCount (aErrorCount)
.applyTo (aResponse,
aValidationResultList,
aDisplayLocale,
nDurationMilliseconds);
}
@Nullable
public static IValidationExecutorSet getAsVES (@Nonnull final ValidationExecutorSetRegistry aRegistry,
@Nullable final IJsonObject aJson)
{
ValueEnforcer.notNull (aRegistry, "Registry");
if (aJson != null)
{
IJsonObject aObj = aJson.getAsObject (JSON_VES);
if (aObj == null)
aObj = aJson;
final String sVESID = aObj.getAsString (JSON_VESID);
if (StringHelper.hasText (sVESID))
{
final DVRCoordinate aVESID = DVRCoordinate.parseOrNull (sVESID);
if (aVESID != null)
return aRegistry.getOfID (aVESID);
}
}
return null;
}
@Nullable
public static IReadableResource getAsValidationResource (@Nullable final String sArtefactPathType,
@Nullable final String sArtefactPath)
{
if (StringHelper.hasNoText (sArtefactPathType))
return null;
if (StringHelper.hasNoText (sArtefactPath))
return null;
if ("file".equals (sArtefactPathType))
return new FileSystemResource (sArtefactPath);
if ("url".equals (sArtefactPathType))
try
{
return new URLResource (sArtefactPath);
}
catch (final MalformedURLException ex)
{
return null;
}
// Default to class path
return new ClassPathResource (sArtefactPath);
}
@Nullable
public static ValidationResultList getAsValidationResultList (@Nullable final IJsonObject aJson)
{
// By default we're only resolving in the enum
return getAsValidationResultList (aJson, EValidationType::getFromIDOrNull);
}
/**
* Try to parse a JSON structure and convert it back to a
* {@link ValidationResultList}.
*
* @param aJson
* The JSON to be read. May be null
.
* @param aValidationTypeResolver
* The validation type resolver to be used. May not be
* null
.
* @return null
in case reverse operation fails.
*/
@Nullable
public static ValidationResultList getAsValidationResultList (@Nullable final IJsonObject aJson,
@Nonnull final Function aValidationTypeResolver)
{
ValueEnforcer.notNull (aValidationTypeResolver, "ValidationTypeResolver");
if (aJson == null)
return null;
final IJsonArray aResults = aJson.getAsArray (JSON_RESULTS);
if (aResults == null)
return null;
final ValidationResultList ret = new ValidationResultList ();
for (final IJson aResult : aResults)
{
final IJsonObject aResultObj = aResult.getAsObject ();
if (aResultObj != null)
{
// Fall back to previous status
final String sSuccess = aResultObj.getAsString (JSON_SUCCESS);
final ETriState eSuccess = getAsTriState (sSuccess);
if (eSuccess == null)
{
if (LOGGER.isDebugEnabled ())
LOGGER.debug ("Failed to resolve TriState '" + sSuccess + "'");
continue;
}
final EExtendedValidity eValidity;
switch (eSuccess)
{
case TRUE:
eValidity = EExtendedValidity.VALID;
break;
case FALSE:
eValidity = EExtendedValidity.INVALID;
break;
case UNDEFINED:
eValidity = EExtendedValidity.SKIPPED;
break;
default:
throw new IllegalStateException ("Oops");
}
final String sValidationType = aResultObj.getAsString (JSON_ARTIFACT_TYPE);
final IValidationType aValidationType = aValidationTypeResolver.apply (sValidationType);
if (aValidationType == null)
{
if (LOGGER.isDebugEnabled ())
LOGGER.debug ("Failed to resolve ValidationType '" + sValidationType + "'");
continue;
}
final String sArtefactPathType = aResultObj.getAsString (JSON_ARTIFACT_PATH_TYPE);
final String sArtefactPath = aResultObj.getAsString (JSON_ARTIFACT_PATH);
final IReadableResource aRes = getAsValidationResource (sArtefactPathType, sArtefactPath);
if (aRes == null)
{
if (LOGGER.isDebugEnabled ())
LOGGER.debug ("Failed to resolve ValidationArtefact '" +
sArtefactPathType +
"' with path '" +
sArtefactPath +
"'");
continue;
}
final ValidationArtefact aVA = new ValidationArtefact (aValidationType, aRes);
if (eValidity.isSkipped ())
{
// Ignored level
ret.add (ValidationResult.createSkippedResult (aVA));
}
else
{
// We have results
final IJsonArray aItems = aResultObj.getAsArray (JSON_ITEMS);
final ErrorList aErrorList = new ErrorList ();
for (final IJson aItem : aItems)
{
final IJsonObject aItemObj = aItem.getAsObject ();
if (aItemObj != null)
{
final IError aError = getAsIError (aItemObj);
aErrorList.add (aError);
}
}
final ValidationResult aVR = new ValidationResult (aVA, aErrorList);
ret.add (aVR);
}
}
}
return ret;
}
}