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