001package org.hl7.fhir.validation.instance.utils;
002
003import org.hl7.fhir.r5.elementmodel.Element;
004import org.hl7.fhir.utilities.Utilities;
005import org.hl7.fhir.validation.instance.InstanceValidator;
006
007public class ChildIterator {
008    private final InstanceValidator instanceValidator;
009    private String basePath;
010    private Element parent;
011    private int cursor;
012    private int lastCount;
013
014    public ChildIterator(InstanceValidator instanceValidator, String path, Element element) {
015        this.instanceValidator = instanceValidator;
016        parent = element;
017        basePath = path;
018        cursor = -1;
019    }
020
021    public InstanceValidator getInstanceValidator() {
022        return instanceValidator;
023    }
024
025    public String getBasePath() {
026        return basePath;
027    }
028
029    public ChildIterator setBasePath(String basePath) {
030        this.basePath = basePath;
031        return this;
032    }
033
034    public Element getParent() {
035        return parent;
036    }
037
038    public ChildIterator setParent(Element parent) {
039        this.parent = parent;
040        return this;
041    }
042
043    public int getCursor() {
044        return cursor;
045    }
046
047    public ChildIterator setCursor(int cursor) {
048        this.cursor = cursor;
049        return this;
050    }
051
052    public int getLastCount() {
053        return lastCount;
054    }
055
056    public ChildIterator setLastCount(int lastCount) {
057        this.lastCount = lastCount;
058        return this;
059    }
060
061    public Element element() {
062        return parent.getChildren().get(cursor);
063    }
064
065    public String name() {
066        return element().getName();
067    }
068
069    public int count() {
070        String nb = cursor == 0 ? "--" : parent.getChildren().get(cursor - 1).getName();
071        String na = cursor >= parent.getChildren().size() - 1 ? "--" : parent.getChildren().get(cursor + 1).getName();
072        if (name().equals(nb) || name().equals(na)) {
073          return lastCount;
074        } else if (element().isBaseList()) {
075          return 0;          
076        } else {
077          return -1;
078        }
079    }
080
081    public boolean next() {
082        if (cursor == -1) {
083            cursor++;
084            lastCount = 0;
085        } else {
086            String lastName = name();
087            cursor++;
088            if (cursor < parent.getChildren().size() && name().equals(lastName))
089                lastCount++;
090            else
091                lastCount = 0;
092        }
093        return cursor < parent.getChildren().size();
094    }
095
096    public String path() {
097        int i = count();
098        String sfx = "";
099        String n = name();
100        String fn = "";
101        if (element().getProperty().isChoice()) {
102          if (element().getProperty().getName().endsWith("[x]")) {
103            String en = element().getProperty().getName();
104            en = en.substring(0, en.length() - 3);
105            String t = n.substring(en.length());
106            if (instanceValidator.isPrimitiveType(Utilities.uncapitalize(t)))
107                t = Utilities.uncapitalize(t);
108            n = en;
109            fn = ".ofType(" + t + ")";
110          } else {
111             // nothing to do? 
112          }
113        }
114        if (i > -1 || (element().getSpecial() == null && element().isList())) {
115            sfx = "[" + Integer.toString(lastCount) + "]";
116        }
117        return basePath + "." + n + sfx + fn;
118    }
119}