ca.uhn.fhir.util.FhirTerser.java Source code

Java tutorial

Introduction

Here is the source code for ca.uhn.fhir.util.FhirTerser.java

Source

package ca.uhn.fhir.util;

import static org.apache.commons.lang3.StringUtils.defaultString;

/*
 * #%L
 * HAPI FHIR - Core Library
 * %%
 * Copyright (C) 2014 - 2016 University Health Network
 * %%
 * 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.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
import java.util.*;

import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.*;

import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.DataFormatException;

public class FhirTerser {

    private FhirContext myContext;

    public FhirTerser(FhirContext theContext) {
        super();
        myContext = theContext;
    }

    private List<String> addNameToList(List<String> theCurrentList, BaseRuntimeChildDefinition theChildDefinition) {
        if (theChildDefinition == null)
            return null;
        if (theCurrentList == null || theCurrentList.isEmpty())
            return new ArrayList<String>(Arrays.asList(theChildDefinition.getElementName()));
        List<String> newList = new ArrayList<String>(theCurrentList);
        newList.add(theChildDefinition.getElementName());
        return newList;
    }

    /**
     * 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 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)
     */
    public void 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;
            } else {
                if (theIgnoreMissingFields) {
                    return;
                } else {
                    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<?> targetDef = (BaseRuntimeElementCompositeDefinition<?>) myContext
                .getElementDefinition(theTarget.getClass());

        List<BaseRuntimeChildDefinition> children = sourceDef.getChildren();
        if (sourceDef instanceof RuntimeExtensionDtDefinition) {
            children = ((RuntimeExtensionDtDefinition) sourceDef).getChildrenIncludingUrl();
        }

        for (BaseRuntimeChildDefinition nextChild : children) {
            for (IBase nextValue : nextChild.getAccessor().getValues(theSource)) {
                String elementName = nextChild.getChildNameByDatatype(nextValue.getClass());
                BaseRuntimeChildDefinition targetChild = targetDef.getChildByName(elementName);
                if (targetChild == null) {
                    if (theIgnoreMissingFields) {
                        continue;
                    } else {
                        throw new DataFormatException("Type " + theTarget.getClass().getName()
                                + " does not have a child with name " + elementName);
                    }
                }

                BaseRuntimeElementDefinition<?> childDef = targetChild.getChildByName(elementName);
                IBase target = childDef.newInstance();
                targetChild.getMutator().addValue(theTarget, target);
                cloneInto(nextValue, target, theIgnoreMissingFields);
            }
        }

    }

    /**
     * Returns a list containing all child elements (including the resource itself) which are <b>non-empty</b> and are either of the exact type specified, or are a subclass of that type.
     * <p>
     * For example, specifying a type of {@link StringDt} would return all non-empty string instances within the message. Specifying a type of {@link IResource} would return the resource itself, as
     * well as any contained resources.
     * </p>
     * <p>
     * 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)
     * </p>
     * 
     * @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 <T extends IBase> List<T> getAllPopulatedChildElementsOfType(IBaseResource theResource,
            final Class<T> theType) {
        final ArrayList<T> retVal = new ArrayList<T>();
        BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
        visit(new IdentityHashMap<Object, Object>(), theResource, theResource, null, null, def,
                new IModelVisitor() {
                    @SuppressWarnings("unchecked")
                    @Override
                    public void acceptElement(IBaseResource theOuterResource, IBase theElement,
                            List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition,
                            BaseRuntimeElementDefinition<?> theDefinition) {
                        if (theElement == null || theElement.isEmpty()) {
                            return;
                        }

                        if (theType.isAssignableFrom(theElement.getClass())) {
                            retVal.add((T) theElement);
                        }
                    }
                });
        return retVal;
    }

    public List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) {
        final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<ResourceReferenceInfo>();
        BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
        visit(new IdentityHashMap<Object, Object>(), theResource, theResource, null, null, def,
                new IModelVisitor() {
                    @Override
                    public void acceptElement(IBaseResource theOuterResource, IBase theElement,
                            List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition,
                            BaseRuntimeElementDefinition<?> theDefinition) {
                        if (theElement == null || theElement.isEmpty()) {
                            return;
                        }
                        if (IBaseReference.class.isAssignableFrom(theElement.getClass())) {
                            retVal.add(new ResourceReferenceInfo(myContext, theOuterResource, thePathToElement,
                                    (IBaseReference) theElement));
                        }
                    }
                });
        return retVal;
    }

    private BaseRuntimeChildDefinition getDefinition(BaseRuntimeElementCompositeDefinition<?> theCurrentDef,
            List<String> theSubList) {
        BaseRuntimeChildDefinition nextDef = theCurrentDef
                .getChildByNameOrThrowDataFormatException(theSubList.get(0));

        if (theSubList.size() == 1) {
            return nextDef;
        } else {
            BaseRuntimeElementCompositeDefinition<?> cmp = (BaseRuntimeElementCompositeDefinition<?>) nextDef
                    .getChildByName(theSubList.get(0));
            return getDefinition(cmp, theSubList.subList(1, theSubList.size()));
        }
    }

    public BaseRuntimeChildDefinition getDefinition(Class<? extends IBaseResource> theResourceType,
            String thePath) {
        RuntimeResourceDefinition def = myContext.getResourceDefinition(theResourceType);

        BaseRuntimeElementCompositeDefinition<?> currentDef = def;

        List<String> parts = Arrays.asList(thePath.split("\\."));
        List<String> subList = parts.subList(1, parts.size());
        if (subList.size() < 1) {
            throw new ConfigurationException("Invalid path: " + thePath);
        }
        return getDefinition(currentDef, subList);

    }

    public Object getSingleValueOrNull(IBase theTarget, String thePath) {
        Class<Object> wantedType = Object.class;

        return getSingleValueOrNull(theTarget, thePath, wantedType);
    }

    public <T> T getSingleValueOrNull(IBase theTarget, String thePath, Class<T> theWantedType) {
        Validate.notNull(theTarget, "theTarget must not be null");
        Validate.notBlank(thePath, "thePath must not be empty");

        BaseRuntimeElementDefinition<?> def = myContext.getElementDefinition(theTarget.getClass());
        if (!(def instanceof BaseRuntimeElementCompositeDefinition)) {
            throw new IllegalArgumentException("Target is not a composite type: " + theTarget.getClass().getName());
        }

        BaseRuntimeElementCompositeDefinition<?> currentDef = (BaseRuntimeElementCompositeDefinition<?>) def;
        Object currentObj = theTarget;

        List<String> parts = Arrays.asList(thePath.split("\\."));
        List<T> retVal = getValues(currentDef, currentObj, parts, theWantedType);
        if (retVal.isEmpty()) {
            return null;
        } else {
            return retVal.get(0);
        }
    }

    @SuppressWarnings("unchecked")
    private <T> List<T> getValues(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, Object theCurrentObj,
            List<String> theSubList, Class<T> theWantedClass) {
        String name = theSubList.get(0);

        BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(name);
        List<? extends IBase> values = nextDef.getAccessor().getValues(theCurrentObj);
        List<T> retVal = new ArrayList<T>();

        if (theSubList.size() == 1) {
            if (nextDef instanceof RuntimeChildChoiceDefinition) {
                for (IBase next : values) {
                    if (next != null) {
                        if (name.endsWith("[x]")) {
                            if (theWantedClass == null || theWantedClass.isAssignableFrom(next.getClass())) {
                                retVal.add((T) next);
                            }
                        } else {
                            String childName = nextDef.getChildNameByDatatype(next.getClass());
                            if (theSubList.get(0).equals(childName)) {
                                if (theWantedClass == null || theWantedClass.isAssignableFrom(next.getClass())) {
                                    retVal.add((T) next);
                                }
                            }
                        }
                    }
                }
            } else {
                for (IBase next : values) {
                    if (next != null) {
                        if (theWantedClass == null || theWantedClass.isAssignableFrom(next.getClass())) {
                            retVal.add((T) next);
                        }
                    }
                }
            }
        } else {
            for (IBase nextElement : values) {
                BaseRuntimeElementCompositeDefinition<?> nextChildDef = (BaseRuntimeElementCompositeDefinition<?>) myContext
                        .getElementDefinition(nextElement.getClass());
                List<T> foundValues = getValues(nextChildDef, nextElement, theSubList.subList(1, theSubList.size()),
                        theWantedClass);
                retVal.addAll(foundValues);
            }
        }
        return retVal;
    }

    public List<Object> getValues(IBaseResource theResource, String thePath) {
        Class<Object> wantedClass = Object.class;

        return getValues(theResource, thePath, wantedClass);

    }

    public <T> List<T> getValues(IBaseResource theResource, String thePath, Class<T> theWantedClass) {
        RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);

        BaseRuntimeElementCompositeDefinition<?> currentDef = def;
        Object currentObj = theResource;

        List<String> parts = Arrays.asList(thePath.split("\\."));
        List<String> subList = parts.subList(1, parts.size());
        if (subList.size() < 1) {
            throw new ConfigurationException("Invalid path: " + thePath);
        }
        return getValues(currentDef, currentObj, subList, theWantedClass);
    }

    /**
     * Returns <code>true</code> if <code>theSource</code> is in the compartment named <code>theCompartmentName</code>
     * belonging to resource <code>theTarget</code>
     * 
     * @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}
     * @return <code>true</code> if <code>theSource</code> is in the compartment
     * @throws IllegalArgumentException If theTarget does not contain both a resource type and ID
     */
    public boolean isSourceInCompartmentForTarget(String theCompartmentName, IBaseResource theSource,
            IIdType theTarget) {
        Validate.notBlank(theCompartmentName, "theCompartmentName must not be null or blank");
        Validate.notNull(theSource, "theSource must not be null");
        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<RuntimeSearchParam> params = sourceDef.getSearchParamsForCompartmentName(theCompartmentName);
        for (RuntimeSearchParam nextParam : params) {
            for (String nextPath : nextParam.getPathsSplit()) {
                for (IBaseReference nextValue : getValues(theSource, nextPath, IBaseReference.class)) {
                    String nextRef = nextValue.getReferenceElement().toUnqualifiedVersionless().getValue();
                    if (wantRef.equals(nextRef)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    private void visit(IBase theElement, BaseRuntimeChildDefinition theChildDefinition,
            BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor2 theCallback,
            List<IBase> theContainingElementPath, List<BaseRuntimeChildDefinition> theChildDefinitionPath,
            List<BaseRuntimeElementDefinition<?>> theElementDefinitionPath) {
        if (theChildDefinition != null) {
            theChildDefinitionPath.add(theChildDefinition);
        }
        theContainingElementPath.add(theElement);
        theElementDefinitionPath.add(theDefinition);

        theCallback.acceptElement(theElement, Collections.unmodifiableList(theContainingElementPath),
                Collections.unmodifiableList(theChildDefinitionPath),
                Collections.unmodifiableList(theElementDefinitionPath));

        /*
         * Visit undeclared extensions
         */
        if (theElement instanceof ISupportsUndeclaredExtensions) {
            ISupportsUndeclaredExtensions containingElement = (ISupportsUndeclaredExtensions) theElement;
            for (ExtensionDt nextExt : containingElement.getUndeclaredExtensions()) {
                theContainingElementPath.add(nextExt);
                theCallback.acceptUndeclaredExtension(nextExt, theContainingElementPath, theChildDefinitionPath,
                        theElementDefinitionPath);
                theContainingElementPath.remove(theContainingElementPath.size() - 1);
            }
        }

        /*
         * 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<? extends IBase> 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<String> iter = new TreeSet<String>(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);
                        }
                    }
                }
            }
            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);
            }
            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);
            }
            break;
        }
        }

        if (theChildDefinition != null) {
            theChildDefinitionPath.remove(theChildDefinitionPath.size() - 1);
        }
        theContainingElementPath.remove(theContainingElementPath.size() - 1);
        theElementDefinitionPath.remove(theElementDefinitionPath.size() - 1);
    }

    /**
     * Visit all elements in a given resource
     * 
     * <p>
     * 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)
     * </p>
     * 
     * @param theResource
     *           The resource to visit
     * @param theVisitor
     *           The visitor
     */
    public void visit(IBaseResource theResource, IModelVisitor theVisitor) {
        BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
        visit(new IdentityHashMap<Object, Object>(), theResource, theResource, null, null, def, theVisitor);
    }

    /**
     * Visit all elements in a given resource
     * 
     * THIS ALTERNATE METHOD IS STILL EXPERIMENTAL
     * 
     * <p>
     * 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)
     * </p>
     * 
     * @param theResource
     *           The resource to visit
     * @param theVisitor
     *           The visitor
     */
    void visit(IBaseResource theResource, IModelVisitor2 theVisitor) {
        BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
        visit(theResource, null, def, theVisitor, new ArrayList<IBase>(),
                new ArrayList<BaseRuntimeChildDefinition>(), new ArrayList<BaseRuntimeElementDefinition<?>>());
    }

    private void visit(IdentityHashMap<Object, Object> theStack, IBaseResource theResource, IBase theElement,
            List<String> thePathToElement, BaseRuntimeChildDefinition theChildDefinition,
            BaseRuntimeElementDefinition<?> theDefinition, IModelVisitor theCallback) {
        List<String> 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();
            if (target != null) {
                if (target.getIdElement().hasIdPart() == false || target.getIdElement().isLocal()) {
                    RuntimeResourceDefinition targetDef = myContext.getResourceDefinition(target);
                    visit(theStack, target, target, pathToElement, null, targetDef, theCallback);
                }
            }
        }

        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());

                        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;
        }
        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());
        }
        }

        theStack.remove(theElement);

    }

}