001package org.hl7.fhir.r5.comparison;
002
003import java.util.ArrayList;
004import java.util.List;
005
006import org.hl7.fhir.r5.comparison.ResourceComparer.MessageCounts;
007import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
008import org.hl7.fhir.utilities.validation.ValidationMessage;
009import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
010
011@MarkedToMoveToAdjunctPackage
012public class StructuralMatch<T> {
013
014  private String name; // this is used in some contexts to carry name when T is a pretty abstract type
015  private T left;
016  private T right;
017  private List<ValidationMessage> messages = new ArrayList<>();
018  private List<StructuralMatch<T>> children = new ArrayList<>();
019 
020  public StructuralMatch() {
021    // root, just a place holder...
022  }
023 
024  public StructuralMatch(T left, T right) {
025    super();
026    this.left = left;
027    this.right = right;
028  }
029 
030  public StructuralMatch(T left, T right, ValidationMessage msg) {
031    super();
032    this.left = left;
033    this.right = right;
034    if (msg != null) {
035      this.messages.add(msg);
036    }
037  }
038 
039  public StructuralMatch(ValidationMessage msg, T right) {
040    super();
041    this.messages.add(msg);
042    this.right = right;
043  }
044
045  public StructuralMatch(T left, ValidationMessage msg) {
046    super();
047    this.left = left;
048    this.messages.add(msg);
049  }
050   
051  public T getLeft() {
052    return left;
053  }
054  public T getRight() {
055    return right;
056  }
057
058  public List<StructuralMatch<T>> getChildren() {
059    return children;
060  }
061
062  /**
063   * return left if it exists, or return right (which might be null)
064   *
065   * This is used when accessing whatever makes the items common
066   *
067   * @return
068   */
069  public T either() {
070    return left != null ? left : right;
071  }
072
073  public boolean hasLeft() {
074    return left != null;
075  }
076 
077  public boolean hasRight() {
078    return right != null;
079  }
080
081  public List<ValidationMessage> getMessages() {
082    return messages;
083  }
084
085  public boolean hasErrors() {
086    for (ValidationMessage vm : messages) {
087      if (vm.getLevel() == IssueSeverity.ERROR) {
088        return true;
089      }
090    }
091    return false;
092  }
093
094  public void countMessages(MessageCounts cnts) {
095    for (ValidationMessage vm : getMessages()) {
096      if (vm.getLevel() == IssueSeverity.ERROR) {
097        cnts.error();
098      } else if (vm.getLevel() == IssueSeverity.WARNING) {
099        cnts.warning();
100      } else if (vm.getLevel() == IssueSeverity.INFORMATION) {
101        cnts.hint();
102      } 
103    }
104    for (StructuralMatch<T> c : children) {
105      c.countMessages(cnts);
106    }
107  }
108
109  public String getName() {
110    return name;
111  }
112
113  public StructuralMatch<T> setName(String name) {
114    this.name = name;
115    return this;
116  }
117
118  public boolean isDifferent() {
119    return (left == null) != (right == null) || !messages.isEmpty();
120  }
121  
122}