ca.uhn.fhir.jpa.dao.SearchParamExtractorDstu1.java Source code

Java tutorial

Introduction

Here is the source code for ca.uhn.fhir.jpa.dao.SearchParamExtractorDstu1.java

Source

package ca.uhn.fhir.jpa.dao;

/*
 * #%L
 * HAPI FHIR JPA Server
 * %%
 * 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 static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.measure.quantity.Quantity;
import javax.measure.unit.NonSI;
import javax.measure.unit.Unit;

import org.apache.commons.lang3.tuple.Pair;
import org.hl7.fhir.instance.model.api.IBaseResource;

import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.model.api.IDatatype;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.model.base.composite.BaseHumanNameDt;
import ca.uhn.fhir.model.dstu.composite.AddressDt;
import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
import ca.uhn.fhir.model.dstu.composite.ContactDt;
import ca.uhn.fhir.model.dstu.composite.DurationDt;
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.composite.PeriodDt;
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;

public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implements ISearchParamExtractor {

    @Override
    public Set<ResourceIndexedSearchParamCoords> extractSearchParamCoords(ResourceTable theEntity,
            IBaseResource theResource) {
        return Collections.emptySet();
    }

    @Override
    public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity,
            IBaseResource theResource) {
        HashSet<ResourceIndexedSearchParamDate> retVal = new HashSet<ResourceIndexedSearchParamDate>();

        RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
        for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
            if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.DATE) {
                continue;
            }

            String nextPath = nextSpDef.getPath();
            if (isBlank(nextPath)) {
                continue;
            }

            boolean multiType = false;
            if (nextPath.endsWith("[x]")) {
                multiType = true;
            }

            for (Object nextObject : extractValues(nextPath, theResource)) {
                if (nextObject == null) {
                    continue;
                }

                ResourceIndexedSearchParamDate nextEntity;
                if (nextObject instanceof BaseDateTimeDt) {
                    BaseDateTimeDt nextValue = (BaseDateTimeDt) nextObject;
                    if (nextValue.isEmpty()) {
                        continue;
                    }
                    nextEntity = new ResourceIndexedSearchParamDate(nextSpDef.getName(), nextValue.getValue(),
                            nextValue.getValue());
                } else if (nextObject instanceof PeriodDt) {
                    PeriodDt nextValue = (PeriodDt) nextObject;
                    if (nextValue.isEmpty()) {
                        continue;
                    }
                    nextEntity = new ResourceIndexedSearchParamDate(nextSpDef.getName(),
                            nextValue.getStart().getValue(), nextValue.getEnd().getValue());
                } else {
                    if (!multiType) {
                        throw new ConfigurationException("Search param " + nextSpDef.getName()
                                + " is of unexpected datatype: " + nextObject.getClass());
                    } else {
                        continue;
                    }
                }
                if (nextEntity != null) {
                    nextEntity.setResource(theEntity);
                    retVal.add(nextEntity);
                }
            }
        }

        return retVal;
    }

    @Override
    public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity,
            IBaseResource theResource) {
        HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<ResourceIndexedSearchParamNumber>();

        RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
        for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
            if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.NUMBER) {
                continue;
            }

            String nextPath = nextSpDef.getPath();
            if (isBlank(nextPath)) {
                continue;
            }

            for (Object nextObject : extractValues(nextPath, theResource)) {
                if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
                    continue;
                }

                String resourceName = nextSpDef.getName();
                boolean multiType = false;
                if (nextPath.endsWith("[x]")) {
                    multiType = true;
                }

                if (nextObject instanceof DurationDt) {
                    DurationDt nextValue = (DurationDt) nextObject;
                    if (nextValue.getValue().isEmpty()) {
                        continue;
                    }

                    if (new UriDt(BaseHapiFhirDao.UCUM_NS).equals(nextValue.getSystem())) {
                        if (isNotBlank(nextValue.getCode().getValue())) {

                            Unit<? extends Quantity> unit = Unit.valueOf(nextValue.getCode().getValue());
                            javax.measure.converter.UnitConverter dayConverter = unit.getConverterTo(NonSI.DAY);
                            double dayValue = dayConverter.convert(nextValue.getValue().getValue().doubleValue());
                            DurationDt newValue = new DurationDt();
                            newValue.setSystem(BaseHapiFhirDao.UCUM_NS);
                            newValue.setCode(NonSI.DAY.toString());
                            newValue.setValue(dayValue);
                            nextValue = newValue;

                            /*
                             * @SuppressWarnings("unchecked") PhysicsUnit<? extends
                             * org.unitsofmeasurement.quantity.Quantity<?>> unit = (PhysicsUnit<? extends
                             * org.unitsofmeasurement.quantity.Quantity<?>>)
                             * UCUMFormat.getCaseInsensitiveInstance().parse(nextValue.getCode().getValue(), null); if
                             * (unit.isCompatible(UCUM.DAY)) {
                             * 
                             * @SuppressWarnings("unchecked") PhysicsUnit<org.unitsofmeasurement.quantity.Time> timeUnit
                             * = (PhysicsUnit<Time>) unit; UnitConverter conv = timeUnit.getConverterTo(UCUM.DAY);
                             * double dayValue = conv.convert(nextValue.getValue().getValue().doubleValue()); DurationDt
                             * newValue = new DurationDt(); newValue.setSystem(UCUM_NS);
                             * newValue.setCode(UCUM.DAY.getSymbol()); newValue.setValue(dayValue); nextValue=newValue;
                             * }
                             */
                        }
                    }

                    ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName,
                            nextValue.getValue().getValue());
                    nextEntity.setResource(theEntity);
                    retVal.add(nextEntity);
                } else if (nextObject instanceof QuantityDt) {
                    QuantityDt nextValue = (QuantityDt) nextObject;
                    if (nextValue.getValue().isEmpty()) {
                        continue;
                    }

                    ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName,
                            nextValue.getValue().getValue());
                    nextEntity.setResource(theEntity);
                    retVal.add(nextEntity);
                } else if (nextObject instanceof IntegerDt) {
                    IntegerDt nextValue = (IntegerDt) nextObject;
                    if (nextValue.getValue() == null) {
                        continue;
                    }

                    ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName,
                            new BigDecimal(nextValue.getValue()));
                    nextEntity.setResource(theEntity);
                    retVal.add(nextEntity);
                } else {
                    if (!multiType) {
                        throw new ConfigurationException("Search param " + resourceName
                                + " is of unexpected datatype: " + nextObject.getClass());
                    } else {
                        continue;
                    }
                }
            }
        }

        return retVal;
    }

    @Override
    public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity,
            IBaseResource theResource) {
        HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<ResourceIndexedSearchParamQuantity>();

        RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
        for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
            if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.QUANTITY) {
                continue;
            }

            String nextPath = nextSpDef.getPath();
            if (isBlank(nextPath)) {
                continue;
            }

            for (Object nextObject : extractValues(nextPath, theResource)) {
                if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
                    continue;
                }

                String resourceName = nextSpDef.getName();
                boolean multiType = false;
                if (nextPath.endsWith("[x]")) {
                    multiType = true;
                }

                if (nextObject instanceof QuantityDt) {
                    QuantityDt nextValue = (QuantityDt) nextObject;
                    if (nextValue.getValue().isEmpty()) {
                        continue;
                    }

                    ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(
                            resourceName, nextValue.getValue().getValue(), nextValue.getSystem().getValueAsString(),
                            nextValue.getUnits().getValue());
                    nextEntity.setResource(theEntity);
                    retVal.add(nextEntity);
                } else {
                    if (!multiType) {
                        throw new ConfigurationException("Search param " + resourceName
                                + " is of unexpected datatype: " + nextObject.getClass());
                    } else {
                        continue;
                    }
                }
            }
        }

        return retVal;
    }

    @Override
    public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity,
            IBaseResource theResource) {
        HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<ResourceIndexedSearchParamString>();

        RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
        for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
            if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.STRING) {
                continue;
            }

            String nextPath = nextSpDef.getPath();
            if (isBlank(nextPath)) {
                // TODO: implement phoenetic, and any others that have no path
                continue;
            }

            for (Object nextObject : extractValues(nextPath, theResource)) {
                if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
                    continue;
                }

                String resourceName = nextSpDef.getName();
                boolean multiType = false;
                if (nextPath.endsWith("[x]")) {
                    multiType = true;
                }

                if (nextObject instanceof IPrimitiveDatatype<?>) {
                    IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
                    String searchTerm = nextValue.getValueAsString();
                    if (searchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
                        searchTerm = searchTerm.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
                    }

                    ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName,
                            BaseHapiFhirDao.normalizeString(searchTerm), searchTerm);
                    nextEntity.setResource(theEntity);
                    retVal.add(nextEntity);
                } else {
                    if (nextObject instanceof BaseHumanNameDt) {
                        ArrayList<StringDt> allNames = new ArrayList<StringDt>();
                        HumanNameDt nextHumanName = (HumanNameDt) nextObject;
                        allNames.addAll(nextHumanName.getFamily());
                        allNames.addAll(nextHumanName.getGiven());
                        for (StringDt nextName : allNames) {
                            if (nextName.isEmpty()) {
                                continue;
                            }
                            ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(
                                    resourceName, BaseHapiFhirDao.normalizeString(nextName.getValueAsString()),
                                    nextName.getValueAsString());
                            nextEntity.setResource(theEntity);
                            retVal.add(nextEntity);
                        }
                    } else if (nextObject instanceof AddressDt) {
                        ArrayList<StringDt> allNames = new ArrayList<StringDt>();
                        AddressDt nextAddress = (AddressDt) nextObject;
                        allNames.addAll(nextAddress.getLine());
                        allNames.add(nextAddress.getCity());
                        allNames.add(nextAddress.getState());
                        allNames.add(nextAddress.getCountry());
                        allNames.add(nextAddress.getZip());
                        for (StringDt nextName : allNames) {
                            if (nextName.isEmpty()) {
                                continue;
                            }
                            ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(
                                    resourceName, BaseHapiFhirDao.normalizeString(nextName.getValueAsString()),
                                    nextName.getValueAsString());
                            nextEntity.setResource(theEntity);
                            retVal.add(nextEntity);
                        }
                    } else if (nextObject instanceof ContactDt) {
                        ContactDt nextContact = (ContactDt) nextObject;
                        if (nextContact.getValue().isEmpty() == false) {
                            ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(
                                    resourceName,
                                    BaseHapiFhirDao.normalizeString(nextContact.getValue().getValueAsString()),
                                    nextContact.getValue().getValueAsString());
                            nextEntity.setResource(theEntity);
                            retVal.add(nextEntity);
                        }
                    } else {
                        if (!multiType) {
                            throw new ConfigurationException("Search param " + resourceName
                                    + " is of unexpected datatype: " + nextObject.getClass());
                        }
                    }
                }
            }
        }

        return retVal;
    }

    @Override
    public Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity,
            IBaseResource theResource) {
        HashSet<BaseResourceIndexedSearchParam> retVal = new HashSet<BaseResourceIndexedSearchParam>();

        RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
        for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
            if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.TOKEN) {
                continue;
            }

            String nextPath = nextSpDef.getPath();
            if (isBlank(nextPath)) {
                continue;
            }

            boolean multiType = false;
            if (nextPath.endsWith("[x]")) {
                multiType = true;
            }

            List<String> systems = new ArrayList<String>();
            List<String> codes = new ArrayList<String>();

            for (Object nextObject : extractValues(nextPath, theResource)) {
                if (nextObject instanceof IdentifierDt) {
                    IdentifierDt nextValue = (IdentifierDt) nextObject;
                    if (nextValue.isEmpty()) {
                        continue;
                    }
                    systems.add(nextValue.getSystem().getValueAsString());
                    codes.add(nextValue.getValue().getValue());
                } else if (nextObject instanceof IPrimitiveDatatype<?>) {
                    IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
                    if (nextValue.isEmpty()) {
                        continue;
                    }
                    systems.add(null);
                    codes.add(nextValue.getValueAsString());
                } else if (nextObject instanceof CodeableConceptDt) {
                    CodeableConceptDt nextCC = (CodeableConceptDt) nextObject;
                    if (!nextCC.getText().isEmpty()) {
                        ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(
                                nextSpDef.getName(), BaseHapiFhirDao.normalizeString(nextCC.getText().getValue()),
                                nextCC.getText().getValue());
                        nextEntity.setResource(theEntity);
                        retVal.add(nextEntity);
                    }

                    for (CodingDt nextCoding : nextCC.getCoding()) {
                        if (nextCoding.isEmpty()) {
                            continue;
                        }

                        String nextSystem = nextCoding.getSystem().getValueAsString();
                        String nextCode = nextCoding.getCode().getValue();
                        if (isNotBlank(nextSystem) || isNotBlank(nextCode)) {
                            systems.add(nextSystem);
                            codes.add(nextCode);
                        }

                        if (!nextCoding.getDisplay().isEmpty()) {
                            systems.add(null);
                            codes.add(nextCoding.getDisplay().getValue());
                        }

                    }
                } else {
                    if (!multiType) {
                        throw new ConfigurationException("Search param " + nextSpDef.getName()
                                + " is of unexpected datatype: " + nextObject.getClass());
                    } else {
                        continue;
                    }
                }
            }

            assert systems.size() == codes.size() : "Systems contains " + systems + ", codes contains: " + codes;

            Set<Pair<String, String>> haveValues = new HashSet<Pair<String, String>>();
            for (int i = 0; i < systems.size(); i++) {
                String system = systems.get(i);
                String code = codes.get(i);
                if (isBlank(system) && isBlank(code)) {
                    continue;
                }

                if (system != null && system.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
                    system = system.substring(0, ResourceIndexedSearchParamToken.MAX_LENGTH);
                }
                if (code != null && code.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
                    code = code.substring(0, ResourceIndexedSearchParamToken.MAX_LENGTH);
                }

                Pair<String, String> nextPair = Pair.of(system, code);
                if (haveValues.contains(nextPair)) {
                    continue;
                }
                haveValues.add(nextPair);

                ResourceIndexedSearchParamToken nextEntity;
                nextEntity = new ResourceIndexedSearchParamToken(nextSpDef.getName(), system, code);
                nextEntity.setResource(theEntity);
                retVal.add(nextEntity);

            }

        }

        return retVal;
    }

    @Override
    public Set<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity,
            IBaseResource theResource) {
        return Collections.emptySet();
    }

}