From bb59e2d73a46ff6ae2e28b7378f59e9e3956729a Mon Sep 17 00:00:00 2001 From: James Agnew Date: Thu, 1 Nov 2018 10:25:13 -0400 Subject: [PATCH] Fix broken test --- .../java/ca/uhn/fhir/util/FhirTerser.java | 393 +++++++++--------- 1 file changed, 195 insertions(+), 198 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java index 281b6d94077..7fa863b524d 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java @@ -28,9 +28,9 @@ import static org.apache.commons.lang3.StringUtils.*; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -96,34 +96,36 @@ public class FhirTerser { /** * Clones all values from a source object into the equivalent fields in a target object - * @param theSource The source object (must not be null) - * @param theTarget The target object to copy values into (must not be null) + * + * @param theSource The source object (must not be null) + * @param theTarget The target object to copy values into (must not be null) * @param theIgnoreMissingFields The ignore fields in the target which do not exist (if false, an exception will be thrown if the target is unable to accept a value from the source) + * @return Returns the target (which will be the same object that was passed into theTarget) for easy chaining */ - public void cloneInto(IBase theSource, IBase theTarget, boolean theIgnoreMissingFields) { + public IBase cloneInto(IBase theSource, IBase theTarget, boolean theIgnoreMissingFields) { Validate.notNull(theSource, "theSource must not be null"); Validate.notNull(theTarget, "theTarget must not be null"); - + if (theSource instanceof IPrimitiveType) { if (theTarget instanceof IPrimitiveType) { - ((IPrimitiveType)theTarget).setValueAsString(((IPrimitiveType)theSource).getValueAsString()); - return; + ((IPrimitiveType) theTarget).setValueAsString(((IPrimitiveType) theSource).getValueAsString()); + return theSource; } if (theIgnoreMissingFields) { - return; + return theSource; } throw new DataFormatException("Can not copy value from primitive of type " + theSource.getClass().getName() + " into type " + theTarget.getClass().getName()); } - - BaseRuntimeElementCompositeDefinition sourceDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition(theSource.getClass()); + + BaseRuntimeElementCompositeDefinition sourceDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition(theSource.getClass()); BaseRuntimeElementCompositeDefinition targetDef = (BaseRuntimeElementCompositeDefinition) myContext.getElementDefinition(theTarget.getClass()); - + List children = sourceDef.getChildren(); if (sourceDef instanceof RuntimeExtensionDtDefinition) { - children = ((RuntimeExtensionDtDefinition)sourceDef).getChildrenIncludingUrl(); + children = ((RuntimeExtensionDtDefinition) sourceDef).getChildrenIncludingUrl(); } - - for (BaseRuntimeChildDefinition nextChild : children) { + + for (BaseRuntimeChildDefinition nextChild : children) for (IBase nextValue : nextChild.getAccessor().getValues(theSource)) { String elementName = nextChild.getChildNameByDatatype(nextValue.getClass()); BaseRuntimeChildDefinition targetChild = targetDef.getChildByName(elementName); @@ -133,14 +135,15 @@ public class FhirTerser { } throw new DataFormatException("Type " + theTarget.getClass().getName() + " does not have a child with name " + elementName); } - - BaseRuntimeElementDefinition childDef = targetChild.getChildByName(elementName); - IBase target = childDef.newInstance(); + + BaseRuntimeElementDefinition element = myContext.getElementDefinition(nextValue.getClass()); + IBase target = element.newInstance(); + targetChild.getMutator().addValue(theTarget, target); cloneInto(nextValue, target, theIgnoreMissingFields); } - } - + + return theTarget; } /** @@ -153,11 +156,9 @@ public class FhirTerser { * Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well, but will not descend into linked resources (e.g. * {@link BaseResourceReferenceDt#getResource()}) or embedded resources (e.g. Bundle.entry.resource) *

- * - * @param theResource - * The resource instance to search. Must not be null. - * @param theType - * The type to search for. Must not be null. + * + * @param theResource The resource instance to search. Must not be null. + * @param theType The type to search for. Must not be null. * @return Returns a list of all matching elements */ public List getAllPopulatedChildElementsOfType(IBaseResource theResource, final Class theType) { @@ -274,7 +275,7 @@ public class FhirTerser { .collect(Collectors.toList()); if (theAddExtension - && (!(theCurrentObj instanceof IBaseExtension) || (extensionDts.isEmpty() && theSubList.size() == 1))) { + && (!(theCurrentObj instanceof IBaseExtension) || (extensionDts.isEmpty() && theSubList.size() == 1))) { extensionDts.add(createEmptyExtensionDt((ISupportsUndeclaredExtensions) theCurrentObj, extensionUrl)); } @@ -286,7 +287,7 @@ public class FhirTerser { extensionDts = ((IBaseExtension) theCurrentObj).getExtension(); if (theAddExtension - && (extensionDts.isEmpty() && theSubList.size() == 1)) { + && (extensionDts.isEmpty() && theSubList.size() == 1)) { extensionDts.add(createEmptyExtensionDt((IBaseExtension) theCurrentObj, extensionUrl)); } @@ -311,7 +312,7 @@ public class FhirTerser { .collect(Collectors.toList()); if (theAddExtension - && (!(theCurrentObj instanceof IBaseExtension) || (extensions.isEmpty() && theSubList.size() == 1))) { + && (!(theCurrentObj instanceof IBaseExtension) || (extensions.isEmpty() && theSubList.size() == 1))) { extensions.add(createEmptyExtension((IBaseHasExtensions) theCurrentObj, extensionUrl)); } @@ -396,7 +397,7 @@ public class FhirTerser { .collect(Collectors.toList()); if (theAddExtension - && (!(theCurrentObj instanceof IBaseExtension) || (extensions.isEmpty() && theSubList.size() == 1))) { + && (!(theCurrentObj instanceof IBaseExtension) || (extensions.isEmpty() && theSubList.size() == 1))) { extensions.add(createEmptyModifierExtension((IBaseHasModifierExtensions) theCurrentObj, extensionUrl)); } @@ -478,7 +479,7 @@ public class FhirTerser { * type {@link Object}. * * @param theResource The resource instance to be accessed. Must not be null. - * @param thePath The path for the element to be accessed. + * @param thePath The path for the element to be accessed. * @return A list of values of type {@link Object}. */ public List getValues(IBaseResource theResource, String thePath) { @@ -492,8 +493,8 @@ public class FhirTerser { * type {@link Object}. * * @param theResource The resource instance to be accessed. Must not be null. - * @param thePath The path for the element to be accessed. - * @param theCreate When set to true, the terser will create a null-valued element where none exists. + * @param thePath The path for the element to be accessed. + * @param theCreate When set to true, the terser will create a null-valued element where none exists. * @return A list of values of type {@link Object}. */ public List getValues(IBaseResource theResource, String thePath, boolean theCreate) { @@ -506,9 +507,9 @@ public class FhirTerser { * Returns values stored in an element identified by its path. The list of values is of * type {@link Object}. * - * @param theResource The resource instance to be accessed. Must not be null. - * @param thePath The path for the element to be accessed. - * @param theCreate When set to true, the terser will create a null-valued element where none exists. + * @param theResource The resource instance to be accessed. Must not be null. + * @param thePath The path for the element to be accessed. + * @param theCreate When set to true, the terser will create a null-valued element where none exists. * @param theAddExtension When set to true, the terser will add a null-valued extension where one or more such extensions already exist. * @return A list of values of type {@link Object}. */ @@ -522,10 +523,10 @@ public class FhirTerser { * Returns values stored in an element identified by its path. The list of values is of * type theWantedClass. * - * @param theResource The resource instance to be accessed. Must not be null. - * @param thePath The path for the element to be accessed. + * @param theResource The resource instance to be accessed. Must not be null. + * @param thePath The path for the element to be accessed. * @param theWantedClass The desired class to be returned in a list. - * @param Type declared by theWantedClass + * @param Type declared by theWantedClass * @return A list of values of type theWantedClass. */ public List getValues(IBaseResource theResource, String thePath, Class theWantedClass) { @@ -538,11 +539,11 @@ public class FhirTerser { * Returns values stored in an element identified by its path. The list of values is of * type theWantedClass. * - * @param theResource The resource instance to be accessed. Must not be null. - * @param thePath The path for the element to be accessed. + * @param theResource The resource instance to be accessed. Must not be null. + * @param thePath The path for the element to be accessed. * @param theWantedClass The desired class to be returned in a list. - * @param theCreate When set to true, the terser will create a null-valued element where none exists. - * @param Type declared by theWantedClass + * @param theCreate When set to true, the terser will create a null-valued element where none exists. + * @param Type declared by theWantedClass * @return A list of values of type theWantedClass. */ public List getValues(IBaseResource theResource, String thePath, Class theWantedClass, boolean theCreate) { @@ -555,12 +556,12 @@ public class FhirTerser { * Returns values stored in an element identified by its path. The list of values is of * type theWantedClass. * - * @param theResource The resource instance to be accessed. Must not be null. - * @param thePath The path for the element to be accessed. - * @param theWantedClass The desired class to be returned in a list. - * @param theCreate When set to true, the terser will create a null-valued element where none exists. + * @param theResource The resource instance to be accessed. Must not be null. + * @param thePath The path for the element to be accessed. + * @param theWantedClass The desired class to be returned in a list. + * @param theCreate When set to true, the terser will create a null-valued element where none exists. * @param theAddExtension When set to true, the terser will add a null-valued extension where one or more such extensions already exist. - * @param Type declared by theWantedClass + * @param Type declared by theWantedClass * @return A list of values of type theWantedClass. */ public List getValues(IBaseResource theResource, String thePath, Class theWantedClass, boolean theCreate, boolean theAddExtension) { @@ -605,10 +606,10 @@ public class FhirTerser { /** * Returns true if theSource is in the compartment named theCompartmentName * belonging to resource theTarget - * + * * @param theCompartmentName The name of the compartment - * @param theSource The potential member of the compartment - * @param theTarget The owner of the compartment. Note that both the resource type and ID must be filled in on this IIdType or the method will throw an {@link IllegalArgumentException} + * @param theSource The potential member of the compartment + * @param theTarget The owner of the compartment. Note that both the resource type and ID must be filled in on this IIdType or the method will throw an {@link IllegalArgumentException} * @return true if theSource is in the compartment * @throws IllegalArgumentException If theTarget does not contain both a resource type and ID */ @@ -618,16 +619,16 @@ public class FhirTerser { Validate.notNull(theTarget, "theTarget must not be null"); Validate.notBlank(defaultString(theTarget.getResourceType()), "theTarget must have a populated resource type (theTarget.getResourceType() does not return a value)"); Validate.notBlank(defaultString(theTarget.getIdPart()), "theTarget must have a populated ID (theTarget.getIdPart() does not return a value)"); - + String wantRef = theTarget.toUnqualifiedVersionless().getValue(); - + RuntimeResourceDefinition sourceDef = myContext.getResourceDefinition(theSource); if (theSource.getIdElement().hasIdPart()) { if (wantRef.equals(sourceDef.getName() + '/' + theSource.getIdElement().getIdPart())) { return true; } } - + List params = sourceDef.getSearchParamsForCompartmentName(theCompartmentName); for (RuntimeSearchParam nextParam : params) { for (String nextPath : nextParam.getPathsSplit()) { @@ -679,12 +680,12 @@ public class FhirTerser { } } } - + return false; } private void visit(IBase theElement, BaseRuntimeChildDefinition theChildDefinition, BaseRuntimeElementDefinition theDefinition, IModelVisitor2 theCallback, List theContainingElementPath, - List theChildDefinitionPath, List> theElementDefinitionPath) { + List theChildDefinitionPath, List> theElementDefinitionPath) { if (theChildDefinition != null) { theChildDefinitionPath.add(theChildDefinition); } @@ -692,7 +693,7 @@ public class FhirTerser { theElementDefinitionPath.add(theDefinition); theCallback.acceptElement(theElement, Collections.unmodifiableList(theContainingElementPath), Collections.unmodifiableList(theChildDefinitionPath), - Collections.unmodifiableList(theElementDefinitionPath)); + Collections.unmodifiableList(theElementDefinitionPath)); /* * Visit undeclared extensions @@ -710,85 +711,85 @@ public class FhirTerser { * Now visit the children of the given element */ switch (theDefinition.getChildType()) { - case ID_DATATYPE: - case PRIMITIVE_XHTML_HL7ORG: - case PRIMITIVE_XHTML: - case PRIMITIVE_DATATYPE: - // These are primitive types, so we don't need to visit their children - break; - case RESOURCE: - case RESOURCE_BLOCK: - case COMPOSITE_DATATYPE: { - BaseRuntimeElementCompositeDefinition childDef = (BaseRuntimeElementCompositeDefinition) theDefinition; - for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) { - List values = nextChild.getAccessor().getValues(theElement); - if (values != null) { - for (IBase nextValue : values) { - if (nextValue == null) { - continue; - } - if (nextValue.isEmpty()) { - continue; - } - BaseRuntimeElementDefinition childElementDef; - childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass()); - - if (childElementDef == null) { - StringBuilder b = new StringBuilder(); - b.append("Found value of type["); - b.append(nextValue.getClass().getSimpleName()); - b.append("] which is not valid for field["); - b.append(nextChild.getElementName()); - b.append("] in "); - b.append(childDef.getName()); - b.append(" - Valid types: "); - for (Iterator iter = new TreeSet(nextChild.getValidChildNames()).iterator(); iter.hasNext();) { - BaseRuntimeElementDefinition childByName = nextChild.getChildByName(iter.next()); - b.append(childByName.getImplementingClass().getSimpleName()); - if (iter.hasNext()) { - b.append(", "); - } + case ID_DATATYPE: + case PRIMITIVE_XHTML_HL7ORG: + case PRIMITIVE_XHTML: + case PRIMITIVE_DATATYPE: + // These are primitive types, so we don't need to visit their children + break; + case RESOURCE: + case RESOURCE_BLOCK: + case COMPOSITE_DATATYPE: { + BaseRuntimeElementCompositeDefinition childDef = (BaseRuntimeElementCompositeDefinition) theDefinition; + for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) { + List values = nextChild.getAccessor().getValues(theElement); + if (values != null) { + for (IBase nextValue : values) { + if (nextValue == null) { + continue; } - throw new DataFormatException(b.toString()); - } + if (nextValue.isEmpty()) { + continue; + } + BaseRuntimeElementDefinition childElementDef; + childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass()); - if (nextChild instanceof RuntimeChildDirectResource) { - // Don't descend into embedded resources - theContainingElementPath.add(nextValue); - theChildDefinitionPath.add(nextChild); - theElementDefinitionPath.add(myContext.getElementDefinition(nextValue.getClass())); - theCallback.acceptElement(nextValue, Collections.unmodifiableList(theContainingElementPath), Collections.unmodifiableList(theChildDefinitionPath), + if (childElementDef == null) { + StringBuilder b = new StringBuilder(); + b.append("Found value of type["); + b.append(nextValue.getClass().getSimpleName()); + b.append("] which is not valid for field["); + b.append(nextChild.getElementName()); + b.append("] in "); + b.append(childDef.getName()); + b.append(" - Valid types: "); + for (Iterator iter = new TreeSet(nextChild.getValidChildNames()).iterator(); iter.hasNext(); ) { + BaseRuntimeElementDefinition childByName = nextChild.getChildByName(iter.next()); + b.append(childByName.getImplementingClass().getSimpleName()); + if (iter.hasNext()) { + b.append(", "); + } + } + throw new DataFormatException(b.toString()); + } + + if (nextChild instanceof RuntimeChildDirectResource) { + // Don't descend into embedded resources + theContainingElementPath.add(nextValue); + theChildDefinitionPath.add(nextChild); + theElementDefinitionPath.add(myContext.getElementDefinition(nextValue.getClass())); + theCallback.acceptElement(nextValue, Collections.unmodifiableList(theContainingElementPath), Collections.unmodifiableList(theChildDefinitionPath), Collections.unmodifiableList(theElementDefinitionPath)); - theChildDefinitionPath.remove(theChildDefinitionPath.size() - 1); - theContainingElementPath.remove(theContainingElementPath.size() - 1); - theElementDefinitionPath.remove(theElementDefinitionPath.size() - 1); - } else { - visit(nextValue, nextChild, childElementDef, theCallback, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath); + theChildDefinitionPath.remove(theChildDefinitionPath.size() - 1); + theContainingElementPath.remove(theContainingElementPath.size() - 1); + theElementDefinitionPath.remove(theElementDefinitionPath.size() - 1); + } else { + visit(nextValue, nextChild, childElementDef, theCallback, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath); + } } } } + break; } - break; - } - case CONTAINED_RESOURCES: { - BaseContainedDt value = (BaseContainedDt) theElement; - for (IResource next : value.getContainedResources()) { - BaseRuntimeElementCompositeDefinition def = myContext.getResourceDefinition(next); - visit(next, null, def, theCallback, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath); + case CONTAINED_RESOURCES: { + BaseContainedDt value = (BaseContainedDt) theElement; + for (IResource next : value.getContainedResources()) { + BaseRuntimeElementCompositeDefinition def = myContext.getResourceDefinition(next); + visit(next, null, def, theCallback, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath); + } + break; } - break; - } - case EXTENSION_DECLARED: - case UNDECL_EXT: { - throw new IllegalStateException("state should not happen: " + theDefinition.getChildType()); - } - case CONTAINED_RESOURCE_LIST: { - if (theElement != null) { - BaseRuntimeElementDefinition def = myContext.getElementDefinition(theElement.getClass()); - visit(theElement, null, def, theCallback, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath); + case EXTENSION_DECLARED: + case UNDECL_EXT: { + throw new IllegalStateException("state should not happen: " + theDefinition.getChildType()); + } + case CONTAINED_RESOURCE_LIST: { + if (theElement != null) { + BaseRuntimeElementDefinition def = myContext.getElementDefinition(theElement.getClass()); + visit(theElement, null, def, theCallback, theContainingElementPath, theChildDefinitionPath, theElementDefinitionPath); + } + break; } - break; - } } if (theChildDefinition != null) { @@ -800,16 +801,14 @@ public class FhirTerser { /** * Visit all elements in a given resource - * + * *

* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well, but will not descend into linked resources (e.g. * {@link BaseResourceReferenceDt#getResource()}) or embedded resources (e.g. Bundle.entry.resource) *

- * - * @param theResource - * The resource to visit - * @param theVisitor - * The visitor + * + * @param theResource The resource to visit + * @param theVisitor The visitor */ public void visit(IBaseResource theResource, IModelVisitor theVisitor) { BaseRuntimeElementCompositeDefinition def = myContext.getResourceDefinition(theResource); @@ -818,18 +817,16 @@ public class FhirTerser { /** * Visit all elements in a given resource - * + *

* THIS ALTERNATE METHOD IS STILL EXPERIMENTAL - * + * *

* Note on scope: This method will descend into any contained resources ({@link IResource#getContained()}) as well, but will not descend into linked resources (e.g. * {@link BaseResourceReferenceDt#getResource()}) or embedded resources (e.g. Bundle.entry.resource) *

- * - * @param theResource - * The resource to visit - * @param theVisitor - * The visitor + * + * @param theResource The resource to visit + * @param theVisitor The visitor */ void visit(IBaseResource theResource, IModelVisitor2 theVisitor) { BaseRuntimeElementCompositeDefinition def = myContext.getResourceDefinition(theResource); @@ -837,22 +834,22 @@ public class FhirTerser { } private void visit(IdentityHashMap theStack, IBaseResource theResource, IBase theElement, List thePathToElement, BaseRuntimeChildDefinition theChildDefinition, - BaseRuntimeElementDefinition theDefinition, IModelVisitor theCallback) { + BaseRuntimeElementDefinition theDefinition, IModelVisitor theCallback) { List pathToElement = addNameToList(thePathToElement, theChildDefinition); if (theStack.put(theElement, theElement) != null) { return; } - + theCallback.acceptElement(theResource, theElement, pathToElement, theChildDefinition, theDefinition); BaseRuntimeElementDefinition def = theDefinition; if (def.getChildType() == ChildTypeEnum.CONTAINED_RESOURCE_LIST) { def = myContext.getElementDefinition(theElement.getClass()); } - + if (theElement instanceof IBaseReference) { - IBaseResource target = ((IBaseReference)theElement).getResource(); + IBaseResource target = ((IBaseReference) theElement).getResource(); if (target != null) { if (target.getIdElement().hasIdPart() == false || target.getIdElement().isLocal()) { RuntimeResourceDefinition targetDef = myContext.getResourceDefinition(target); @@ -860,71 +857,71 @@ public class FhirTerser { } } } - + switch (def.getChildType()) { - case ID_DATATYPE: - case PRIMITIVE_XHTML_HL7ORG: - case PRIMITIVE_XHTML: - case PRIMITIVE_DATATYPE: - // These are primitive types - break; - case RESOURCE: - case RESOURCE_BLOCK: - case COMPOSITE_DATATYPE: { - BaseRuntimeElementCompositeDefinition childDef = (BaseRuntimeElementCompositeDefinition) def; - for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) { - - List values = nextChild.getAccessor().getValues(theElement); - if (values != null) { - for (Object nextValueObject : values) { - IBase nextValue; - try { - nextValue = (IBase) nextValueObject; - } catch (ClassCastException e) { - String s = "Found instance of " + nextValueObject.getClass() + " - Did you set a field value to the incorrect type? Expected " + IBase.class.getName(); - throw new ClassCastException(s); - } - if (nextValue == null) { - continue; - } - if (nextValue.isEmpty()) { - continue; - } - BaseRuntimeElementDefinition childElementDef; - childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass()); + case ID_DATATYPE: + case PRIMITIVE_XHTML_HL7ORG: + case PRIMITIVE_XHTML: + case PRIMITIVE_DATATYPE: + // These are primitive types + break; + case RESOURCE: + case RESOURCE_BLOCK: + case COMPOSITE_DATATYPE: { + BaseRuntimeElementCompositeDefinition childDef = (BaseRuntimeElementCompositeDefinition) def; + for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) { - if (childElementDef == null) { - childElementDef = myContext.getElementDefinition(nextValue.getClass()); - } + List values = nextChild.getAccessor().getValues(theElement); + if (values != null) { + for (Object nextValueObject : values) { + IBase nextValue; + try { + nextValue = (IBase) nextValueObject; + } catch (ClassCastException e) { + String s = "Found instance of " + nextValueObject.getClass() + " - Did you set a field value to the incorrect type? Expected " + IBase.class.getName(); + throw new ClassCastException(s); + } + if (nextValue == null) { + continue; + } + if (nextValue.isEmpty()) { + continue; + } + BaseRuntimeElementDefinition childElementDef; + childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass()); - if (nextChild instanceof RuntimeChildDirectResource) { - // Don't descend into embedded resources - theCallback.acceptElement(theResource, nextValue, null, nextChild, childElementDef); - } else { - visit(theStack, theResource, nextValue, pathToElement, nextChild, childElementDef, theCallback); + if (childElementDef == null) { + childElementDef = myContext.getElementDefinition(nextValue.getClass()); + } + + if (nextChild instanceof RuntimeChildDirectResource) { + // Don't descend into embedded resources + theCallback.acceptElement(theResource, nextValue, null, nextChild, childElementDef); + } else { + visit(theStack, theResource, nextValue, pathToElement, nextChild, childElementDef, theCallback); + } } } } + break; } - break; - } - case CONTAINED_RESOURCES: { - BaseContainedDt value = (BaseContainedDt) theElement; - for (IResource next : value.getContainedResources()) { - def = myContext.getResourceDefinition(next); - visit(theStack, next, next, pathToElement, null, def, theCallback); + case CONTAINED_RESOURCES: { + BaseContainedDt value = (BaseContainedDt) theElement; + for (IResource next : value.getContainedResources()) { + def = myContext.getResourceDefinition(next); + visit(theStack, next, next, pathToElement, null, def, theCallback); + } + break; + } + case CONTAINED_RESOURCE_LIST: + case EXTENSION_DECLARED: + case UNDECL_EXT: { + throw new IllegalStateException("state should not happen: " + def.getChildType()); } - break; } - case CONTAINED_RESOURCE_LIST: - case EXTENSION_DECLARED: - case UNDECL_EXT: { - throw new IllegalStateException("state should not happen: " + def.getChildType()); - } - } - + theStack.remove(theElement); - + } }