
001package org.hl7.fhir.r5.terminologies.utilities; 002 003import java.util.List; 004 005import lombok.extern.slf4j.Slf4j; 006import org.hl7.fhir.exceptions.FHIRException; 007import org.hl7.fhir.exceptions.TerminologyServiceException; 008import org.hl7.fhir.r5.context.IWorkerContext; 009import org.hl7.fhir.r5.model.OperationOutcome.IssueType; 010import org.hl7.fhir.r5.terminologies.utilities.TerminologyOperationContext.TerminologyServiceProtectionException; 011import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage; 012import org.hl7.fhir.utilities.Utilities; 013import org.hl7.fhir.utilities.i18n.I18nConstants; 014import org.hl7.fhir.utilities.validation.ValidationOptions; 015 016import java.util.ArrayList; 017 018@MarkedToMoveToAdjunctPackage 019@Slf4j 020public class TerminologyOperationContext { 021 022 public static class TerminologyServiceProtectionException extends FHIRException { 023 024 private TerminologyServiceErrorClass error; 025 private IssueType type; 026 private String diagnostics; 027 028 public TerminologyServiceProtectionException(String message, TerminologyServiceErrorClass error, IssueType type) { 029 super(message); 030 this.error = error; 031 this.type = type; 032 } 033 public TerminologyServiceProtectionException(String message, TerminologyServiceErrorClass error, IssueType type, String diagnostics) { 034 super(message); 035 this.error = error; 036 this.type = type; 037 this.diagnostics = diagnostics; 038 } 039 040 public TerminologyServiceErrorClass getError() { 041 return error; 042 } 043 044 public IssueType getType() { 045 return type; 046 } 047 public String getDiagnostics() { 048 return diagnostics; 049 } 050 051 } 052 053 public static boolean debugging = java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments().toString().indexOf("-agentlib:jdwp") > 0; 054 private static final int EXPANSION_DEAD_TIME_SECS = 60; 055 private long deadTime; 056 private int nestCount = 0; 057 private long startTime; 058 private List<String> contexts = new ArrayList<>(); 059 private IWorkerContext worker; 060 private boolean original; 061 private ValidationOptions options; 062 private String name; 063 private List<String> notes = new ArrayList<>(); 064 065 public TerminologyOperationContext(IWorkerContext worker, ValidationOptions options, String name) { 066 super(); 067 this.worker = worker; 068 this.original = true; 069 this.options = options; 070 this.name = name; 071 this.startTime = System.currentTimeMillis(); 072 073 if (EXPANSION_DEAD_TIME_SECS == 0 || debugging) { 074 deadTime = 0; 075 } else { 076 deadTime = System.currentTimeMillis() + (EXPANSION_DEAD_TIME_SECS * 1000); 077 } 078 } 079 080 private TerminologyOperationContext(ValidationOptions options, String name) { 081 super(); 082 this.options = options; 083 this.name = name; 084 this.startTime = System.currentTimeMillis(); 085 } 086 087 public TerminologyOperationContext copy() { 088 TerminologyOperationContext ret = new TerminologyOperationContext(this.options, name); 089 ret.worker = worker; 090 ret.contexts.addAll(contexts); 091 ret.deadTime = deadTime; 092 ret.notes = notes; 093 ret.startTime = startTime; 094 ret.nestCount = nestCount + 1; 095 return ret; 096 } 097 098 public void deadCheck(String note) { 099 note(note); 100 if (deadTime != 0 && System.currentTimeMillis() > deadTime) { 101 log.error("Operation took too long - longer than "+(deadTime - startTime)+"ms"); 102 for (String s : notes) { 103 log.error(s); 104 } 105 throw new TerminologyServiceProtectionException(worker.formatMessage(I18nConstants.VALUESET_TOO_COSTLY_TIME, contexts.get(0), EXPANSION_DEAD_TIME_SECS, name+" (local)"), TerminologyServiceErrorClass.TOO_COSTLY, IssueType.TOOCOSTLY); 106 } 107 } 108 109 public void seeContext(String context) { 110 if (contexts.contains(context)) { 111 throw new TerminologyServiceProtectionException(worker.formatMessage(I18nConstants.VALUESET_CIRCULAR_REFERENCE, context, contexts.toString()), TerminologyServiceErrorClass.PROCESSING, IssueType.PROCESSING); 112 } 113 contexts.add(context); 114 } 115 116 public boolean isOriginal() { 117 return original; 118 } 119 120 public ValidationOptions getOptions() { 121 return options; 122 } 123 124 public void note(String s) { 125 s = Utilities.padLeft("", ' ', nestCount)+" "+(System.currentTimeMillis() - startTime)+" "+s; 126 notes.add(s); 127 } 128}