/** * Removes all the successful minor results. Also checks if the result is roughly consistent and * complete. (e.g. does not have unknown operation status, etc.) * * <p>The argument "e" is for easier use of the cleanup in the exceptions handlers. The original * exception is passed to the IAE that this method produces for easier debugging. */ public void cleanupResult(Throwable e) { if (status == OperationResultStatus.UNKNOWN) { LOGGER.error( "Attempt to cleanup result of operation " + operation + " that is still UNKNOWN:\n{}", this.debugDump()); throw new IllegalStateException( "Attempt to cleanup result of operation " + operation + " that is still UNKNOWN"); } if (subresults == null) { return; } Iterator<OperationResult> iterator = subresults.iterator(); while (iterator.hasNext()) { OperationResult subresult = iterator.next(); if (subresult.getStatus() == OperationResultStatus.UNKNOWN) { String message = "Subresult " + subresult.getOperation() + " of operation " + operation + " is still UNKNOWN during cleanup"; LOGGER.error("{}:\n{}", message, this.debugDump(), e); if (e == null) { throw new IllegalStateException(message); } else { throw new IllegalStateException(message + "; during handling of exception " + e, e); } } if (subresult.canCleanup()) { iterator.remove(); } } }
/** Set all error status in this result and all subresults as handled. */ public void setErrorsHandled() { if (isError()) { setStatus(OperationResultStatus.HANDLED_ERROR); } for (OperationResult subresult : getSubresults()) { subresult.setErrorsHandled(); } }
/** * Returns true if result status is UNKNOWN or any of the subresult status is unknown (recursive). * * <p>May come handy in tests to check if all the operations fill out the status as they should. */ public boolean hasUnknownStatus() { if (status == OperationResultStatus.UNKNOWN) { return true; } for (OperationResult subresult : getSubresults()) { if (subresult.hasUnknownStatus()) { return true; } } return false; }
public OperationResult findSubresult(String operation) { if (subresults == null) { return null; } for (OperationResult subResult : getSubresults()) { if (operation.equals(subResult.getOperation())) { return subResult; } } return null; }
public List<OperationResult> findSubresults(String operation) { List<OperationResult> found = new ArrayList<>(); if (subresults == null) { return found; } for (OperationResult subResult : getSubresults()) { if (operation.equals(subResult.getOperation())) { found.add(subResult); } } return found; }
public void summarize() { Iterator<OperationResult> iterator = getSubresults().iterator(); while (iterator.hasNext()) { OperationResult subresult = iterator.next(); if (subresult.getCount() > 1) { // Already summarized continue; } if (subresult.isError() && summarizeErrors) { // go on } else if (subresult.isPartialError() && summarizePartialErrors) { // go on } else if (subresult.isSuccess() && summarizeSuccesses) { // go on } else { continue; } OperationResult similar = findSimilarSubresult(subresult); if (similar == null) { // Nothing to summarize to continue; } merge(similar, subresult); iterator.remove(); } // subresult stripping if necessary // we strip subresults that have same operation name and status, if there are more of them than // threshold Map<OperationStatusKey, Integer> counter = new HashMap<OperationStatusKey, Integer>(); iterator = getSubresults().iterator(); while (iterator.hasNext()) { OperationResult sr = iterator.next(); OperationStatusKey key = new OperationStatusKey(sr.getOperation(), sr.getStatus()); if (counter.containsKey(key)) { int count = counter.get(key); if (count > SUBRESULT_STRIP_THRESHOLD) { iterator.remove(); } else { counter.put(key, ++count); } } else { counter.put(key, 1); } } }
public static OperationResult createOperationResult(OperationResultType result) { if (result == null) { return null; } Map<String, Serializable> params = ParamsTypeUtil.fromParamsType(result.getParams()); // if (result.getParams() != null) { // params = new HashMap<String, Serializable>(); // for (EntryType entry : result.getParams().getEntry()) { // params.put(entry.getKey(), (Serializable) entry.getEntryValue()); // } // } Map<String, Serializable> context = ParamsTypeUtil.fromParamsType(result.getContext()); // if (result.getContext() != null) { // context = new HashMap<String, Serializable>(); // for (EntryType entry : result.getContext().getEntry()) { // context.put(entry.getKey(), (Serializable) entry.getEntryValue()); // } // } Map<String, Serializable> returns = ParamsTypeUtil.fromParamsType(result.getReturns()); // if (result.getReturns() != null) { // returns = new HashMap<String, Serializable>(); // for (EntryType entry : result.getReturns().getEntry()) { // returns.put(entry.getKey(), (Serializable) entry.getEntryValue()); // } // } List<OperationResult> subresults = null; if (!result.getPartialResults().isEmpty()) { subresults = new ArrayList<OperationResult>(); for (OperationResultType subResult : result.getPartialResults()) { subresults.add(createOperationResult(subResult)); } } LocalizedMessageType message = result.getLocalizedMessage(); String localizedMessage = message == null ? null : message.getKey(); List<Serializable> localizedArguments = message == null ? null : (List<Serializable>) (List) message.getArgument(); // FIXME: brutal hack OperationResult opResult = new OperationResult( result.getOperation(), params, context, returns, OperationResultStatus.parseStatusType(result.getStatus()), result.getToken(), result.getMessageCode(), result.getMessage(), localizedMessage, localizedArguments, null, subresults); if (result.getCount() != null) { opResult.setCount(result.getCount()); } return opResult; }
public void muteLastSubresultError() { OperationResult lastSubresult = getLastSubresult(); if (lastSubresult != null) { lastSubresult.muteError(); } }
/** * Used when the result contains several composite sub-result that are of equivalent meaning. If * all of them fail the result will be fatal error as well. If only some of them fail the result * will be partial error. Handled error is considered a success. */ public void computeStatusComposite() { if (getSubresults().isEmpty()) { if (status == OperationResultStatus.UNKNOWN) { status = OperationResultStatus.NOT_APPLICABLE; } return; } boolean allFatalError = true; boolean allNotApplicable = true; boolean hasInProgress = false; boolean hasHandledError = false; boolean hasError = false; boolean hasWarning = false; for (OperationResult sub : getSubresults()) { if (sub.getStatus() != OperationResultStatus.NOT_APPLICABLE) { allNotApplicable = false; } if (sub.getStatus() != OperationResultStatus.FATAL_ERROR) { allFatalError = false; } if (sub.getStatus() == OperationResultStatus.FATAL_ERROR) { hasError = true; if (message == null) { message = sub.getMessage(); } else { message = message + ", " + sub.getMessage(); } } if (sub.getStatus() == OperationResultStatus.PARTIAL_ERROR) { hasError = true; if (message == null) { message = sub.getMessage(); } else { message = message + ", " + sub.getMessage(); } } if (sub.getStatus() == OperationResultStatus.HANDLED_ERROR) { hasHandledError = true; if (message == null) { message = sub.getMessage(); } else { message = message + ", " + sub.getMessage(); } } if (sub.getStatus() == OperationResultStatus.IN_PROGRESS) { hasInProgress = true; if (message == null) { message = sub.getMessage(); } else { message = message + ", " + sub.getMessage(); } } if (sub.getStatus() == OperationResultStatus.WARNING) { hasWarning = true; if (message == null) { message = sub.getMessage(); } else { message = message + ", " + sub.getMessage(); } } } if (allNotApplicable) { status = OperationResultStatus.NOT_APPLICABLE; } else if (allFatalError) { status = OperationResultStatus.FATAL_ERROR; } else if (hasInProgress) { status = OperationResultStatus.IN_PROGRESS; } else if (hasError) { status = OperationResultStatus.PARTIAL_ERROR; } else if (hasWarning) { status = OperationResultStatus.WARNING; } else if (hasHandledError) { status = OperationResultStatus.HANDLED_ERROR; } else { status = OperationResultStatus.SUCCESS; } }
/** Computes operation result status based on subtask status. */ public void computeStatus() { if (getSubresults().isEmpty()) { if (status == OperationResultStatus.UNKNOWN) { status = OperationResultStatus.SUCCESS; } return; } if (status == OperationResultStatus.FATAL_ERROR) { return; } OperationResultStatus newStatus = OperationResultStatus.UNKNOWN; boolean allSuccess = true; boolean allNotApplicable = true; String newMessage = null; for (OperationResult sub : getSubresults()) { if (sub.getStatus() != OperationResultStatus.NOT_APPLICABLE) { allNotApplicable = false; } if (sub.getStatus() == OperationResultStatus.FATAL_ERROR) { status = OperationResultStatus.FATAL_ERROR; if (message == null) { message = sub.getMessage(); } else { message = message + ": " + sub.getMessage(); } return; } if (sub.getStatus() == OperationResultStatus.IN_PROGRESS) { status = OperationResultStatus.IN_PROGRESS; if (message == null) { message = sub.getMessage(); } else { message = message + ": " + sub.getMessage(); } return; } if (sub.getStatus() == OperationResultStatus.PARTIAL_ERROR) { newStatus = OperationResultStatus.PARTIAL_ERROR; newMessage = sub.getMessage(); } if (newStatus != OperationResultStatus.PARTIAL_ERROR) { if (sub.getStatus() == OperationResultStatus.HANDLED_ERROR) { newStatus = OperationResultStatus.HANDLED_ERROR; newMessage = sub.getMessage(); } } if (sub.getStatus() != OperationResultStatus.SUCCESS && sub.getStatus() != OperationResultStatus.NOT_APPLICABLE) { allSuccess = false; } if (newStatus != OperationResultStatus.HANDLED_ERROR) { if (sub.getStatus() == OperationResultStatus.WARNING) { newStatus = OperationResultStatus.WARNING; newMessage = sub.getMessage(); } } } if (allNotApplicable && !getSubresults().isEmpty()) { status = OperationResultStatus.NOT_APPLICABLE; } if (allSuccess && !getSubresults().isEmpty()) { status = OperationResultStatus.SUCCESS; } else { status = newStatus; if (message == null) { message = newMessage; } else { message = message + ": " + newMessage; } } }
/** @return last subresult status, or null if there are no subresults. */ public OperationResultStatus getLastSubresultStatus() { OperationResult last = getLastSubresult(); return last != null ? last.getStatus() : null; }
public OperationResult createMinorSubresult(String operation) { OperationResult subresult = createSubresult(operation); subresult.minor = true; return subresult; }
public OperationResult clone() { OperationResult clone = new OperationResult(operation); clone.status = status; clone.params = CloneUtil.clone(params); clone.context = CloneUtil.clone(context); clone.returns = CloneUtil.clone(returns); clone.token = token; clone.messageCode = messageCode; clone.message = message; clone.localizationMessage = localizationMessage; clone.localizationArguments = CloneUtil.clone(localizationArguments); clone.cause = CloneUtil.clone(cause); clone.count = count; if (subresults != null) { clone.subresults = new ArrayList<>(subresults.size()); for (OperationResult subresult : subresults) { if (subresult != null) { clone.subresults.add(subresult.clone()); } } } clone.details = CloneUtil.clone(details); clone.summarizeErrors = summarizeErrors; clone.summarizePartialErrors = summarizePartialErrors; clone.summarizeSuccesses = summarizeSuccesses; clone.minor = minor; return clone; }
private void dumpIndent(StringBuilder sb, int indent, boolean printStackTrace) { for (int i = 0; i < indent; i++) { sb.append(INDENT_STRING); } sb.append("*op* "); sb.append(operation); sb.append(", st: "); sb.append(status); if (minor) { sb.append(", MINOR"); } sb.append(", msg: "); sb.append(message); if (count > 1) { sb.append(" x"); sb.append(count); } sb.append("\n"); for (Map.Entry<String, Serializable> entry : getParams().entrySet()) { for (int i = 0; i < indent + 2; i++) { sb.append(INDENT_STRING); } sb.append("[p]"); sb.append(entry.getKey()); sb.append("="); sb.append(dumpEntry(indent + 2, entry.getValue())); sb.append("\n"); } for (Map.Entry<String, Serializable> entry : getContext().entrySet()) { for (int i = 0; i < indent + 2; i++) { sb.append(INDENT_STRING); } sb.append("[c]"); sb.append(entry.getKey()); sb.append("="); sb.append(dumpEntry(indent + 2, entry.getValue())); sb.append("\n"); } for (Map.Entry<String, Serializable> entry : getReturns().entrySet()) { for (int i = 0; i < indent + 2; i++) { sb.append(INDENT_STRING); } sb.append("[r]"); sb.append(entry.getKey()); sb.append("="); sb.append(dumpEntry(indent + 2, entry.getValue())); sb.append("\n"); } for (String line : details) { for (int i = 0; i < indent + 2; i++) { sb.append(INDENT_STRING); } sb.append("[d]"); sb.append(line); sb.append("\n"); } if (cause != null) { for (int i = 0; i < indent + 2; i++) { sb.append(INDENT_STRING); } sb.append("[cause]"); sb.append(cause.getClass().getSimpleName()); sb.append(":"); sb.append(cause.getMessage()); sb.append("\n"); if (printStackTrace) { dumpStackTrace(sb, cause.getStackTrace(), indent + 4); dumpInnerCauses(sb, cause.getCause(), indent + 3); } } for (OperationResult sub : getSubresults()) { sub.dumpIndent(sb, indent + 1, printStackTrace); } }
private void merge(OperationResult target, OperationResult source) { mergeMap(target.getParams(), source.getParams()); mergeMap(target.getContext(), source.getContext()); mergeMap(target.getReturns(), source.getReturns()); target.incrementCount(); }
private OperationResultType createOperationResultType(OperationResult opResult) { OperationResultType result = new OperationResultType(); result.setToken(opResult.getToken()); result.setStatus(OperationResultStatus.createStatusType(opResult.getStatus())); if (opResult.getCount() != 1) { result.setCount(opResult.getCount()); } result.setOperation(opResult.getOperation()); result.setMessage(opResult.getMessage()); result.setMessageCode(opResult.getMessageCode()); if (opResult.getCause() != null || !opResult.details.isEmpty()) { StringBuilder detailsb = new StringBuilder(); // Record text messages in details (if present) if (!opResult.details.isEmpty()) { for (String line : opResult.details) { detailsb.append(line); detailsb.append("\n"); } } // Record stack trace in details if a cause is present if (opResult.getCause() != null) { Throwable ex = opResult.getCause(); detailsb.append(ex.getClass().getName()); detailsb.append(": "); detailsb.append(ex.getMessage()); detailsb.append("\n"); StackTraceElement[] stackTrace = ex.getStackTrace(); for (int i = 0; i < stackTrace.length; i++) { detailsb.append(stackTrace[i].toString()); detailsb.append("\n"); } } result.setDetails(detailsb.toString()); } if (StringUtils.isNotEmpty(opResult.getLocalizationMessage())) { LocalizedMessageType message = new LocalizedMessageType(); message.setKey(opResult.getLocalizationMessage()); if (opResult.getLocalizationArguments() != null) { message.getArgument().addAll(opResult.getLocalizationArguments()); } result.setLocalizedMessage(message); } // Set<Entry<String, Serializable>> params = opResult.getParams(); // if (!params.isEmpty()) { ParamsType paramsType = ParamsTypeUtil.toParamsType(opResult.getParams()); result.setParams(paramsType); // for (Entry<String, Serializable> entry : params) { // paramsType.getEntry().add(createEntryElement(entry.getKey(),entry.getValue())); // } // } // Set<Entry<String, Serializable>> context = opResult.getContext().entrySet(); // if (!context.isEmpty()) { paramsType = ParamsTypeUtil.toParamsType(opResult.getContext()); result.setContext(paramsType); // for (Entry<String, Serializable> entry : context) { // paramsType.getEntry().add(createEntryElement(entry.getKey(),entry.getValue())); // } // } // Set<Entry<String, Serializable>> returns = opResult.getReturns().entrySet(); // if (!returns.isEmpty()) { paramsType = ParamsTypeUtil.toParamsType(opResult.getReturns()); result.setReturns(paramsType); // for (Entry<String, Serializable> entry : returns) { // paramsType.getEntry().add(createEntryElement(entry.getKey(),entry.getValue())); // } // } for (OperationResult subResult : opResult.getSubresults()) { result.getPartialResults().add(opResult.createOperationResultType(subResult)); } return result; }