001package org.dcm4che3.conf.core.util; 002 003import org.dcm4che3.conf.core.api.Path; 004import org.dcm4che3.conf.core.api.internal.ConfigProperty; 005import org.dcm4che3.conf.core.api.internal.ConfigReflection; 006 007import java.util.ArrayDeque; 008import java.util.Deque; 009import java.util.List; 010 011/** 012 * @author rawmahn 013 */ 014public class PathFollower { 015 016 017 /** 018 * Walk the given path 'through' the class structures and return the 'trace' of all visited properties 019 * 020 * @return 021 */ 022 public static Deque<ConfigProperty> traceProperties(Class rootConfigurableClazz, Path path) { 023 024 025 ArrayDeque<ConfigProperty> trace = new ArrayDeque<ConfigProperty>(path.getPathItems().size()); 026 027 ConfigProperty current = ConfigReflection.getDummyPropertyForClass(rootConfigurableClazz); 028 029 for (Object i : path.getPathItems()) { 030 031 trace.addLast(current); 032 033 if ((i instanceof String && !current.isConfObject() && !current.isMap()) 034 || (i instanceof Number && !current.isCollection())) { 035 throw new IllegalArgumentException( 036 "Unexpected path element " + i + " in path " + path + " for root class " + rootConfigurableClazz + ", corresponding property " + current 037 ); 038 } 039 040 if (current.isConfObject()) { 041 List<ConfigProperty> props = ConfigReflection.getAllConfigurableFields(current.getRawClass()); 042 043 boolean found = false; 044 for (ConfigProperty prop : props) { 045 if (prop.getAnnotatedName().equals(i)) { 046 current = prop; 047 found = true; 048 break; 049 } 050 } 051 052 if (!found) { 053 throw new IllegalArgumentException("Cannot find the property with name " + i + " in class " + current.getRawClass() + " while tracing path " + path); 054 } 055 056 } else if (current.isMap() || current.isCollection()) { 057 current = current.getPseudoPropertyForCollectionElement(); 058 } else 059 throw new IllegalArgumentException("Path " + path + " cannot be followed - property " + current + " is not supposed to have no children"); 060 061 062 // TODO: add support for extensions - for now there are no usecases that involve referables *inside* extensions (hl7apps however are a good example) 063 064 } 065 066 trace.addLast(current); 067 068 return trace; 069 } 070 071 072}