001/*- 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.entity; 021 022import org.hibernate.search.engine.backend.document.DocumentElement; 023import org.hibernate.search.engine.backend.document.model.dsl.IndexSchemaElement; 024import org.hibernate.search.engine.backend.types.dsl.IndexFieldTypeFactory; 025import org.hibernate.search.mapper.pojo.bridge.PropertyBridge; 026import org.hibernate.search.mapper.pojo.bridge.binding.PropertyBindingContext; 027import org.hibernate.search.mapper.pojo.bridge.mapping.programmatic.PropertyBinder; 028import org.hibernate.search.mapper.pojo.bridge.runtime.PropertyBridgeWriteContext; 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032import java.util.Collection; 033 034import static org.apache.commons.lang3.StringUtils.isNotBlank; 035 036/** 037 * Allows hibernate search to index individual concepts' properties 038 */ 039public class TermConceptPropertyBinder implements PropertyBinder { 040 041 public static final String CONCEPT_PROPERTY_PREFIX_NAME = "P:"; 042 043 private static final Logger ourLog = LoggerFactory.getLogger(TermConceptPropertyBinder.class); 044 045 @Override 046 public void bind(PropertyBindingContext thePropertyBindingContext) { 047 thePropertyBindingContext.dependencies().use("myKey").use("myValue"); 048 IndexSchemaElement indexSchemaElement = thePropertyBindingContext.indexSchemaElement(); 049 050 // In order to support dynamic fields, we have to use field templates. We _must_ define the template at 051 // bootstrap time and cannot 052 // create them adhoc. 053 // https://docs.jboss.org/hibernate/search/6.0/reference/en-US/html_single/#mapper-orm-bridge-index-field-dsl-dynamic 054 indexSchemaElement 055 .fieldTemplate("propTemplate", IndexFieldTypeFactory::asString) 056 .matchingPathGlob(CONCEPT_PROPERTY_PREFIX_NAME + "*") 057 .multiValued(); 058 059 thePropertyBindingContext.bridge(Collection.class, new TermConceptPropertyBridge()); 060 } 061 062 @SuppressWarnings("rawtypes") 063 private static class TermConceptPropertyBridge implements PropertyBridge<Collection> { 064 065 @Override 066 public void write( 067 DocumentElement theDocument, 068 Collection theObject, 069 PropertyBridgeWriteContext thePropertyBridgeWriteContext) { 070 071 @SuppressWarnings("unchecked") 072 Collection<TermConceptProperty> properties = (Collection<TermConceptProperty>) theObject; 073 074 if (properties != null) { 075 for (TermConceptProperty next : properties) { 076 theDocument.addValue(CONCEPT_PROPERTY_PREFIX_NAME + next.getKey(), next.getValue()); 077 ourLog.trace( 078 "Adding Prop: {}{} -- {}", CONCEPT_PROPERTY_PREFIX_NAME, next.getKey(), next.getValue()); 079 if (next.getType() == TermConceptPropertyTypeEnum.CODING && isNotBlank(next.getDisplay())) { 080 theDocument.addValue(CONCEPT_PROPERTY_PREFIX_NAME + next.getKey(), next.getDisplay()); 081 ourLog.trace( 082 "Adding multivalue Prop: {}{} -- {}", 083 CONCEPT_PROPERTY_PREFIX_NAME, 084 next.getKey(), 085 next.getDisplay()); 086 } 087 } 088 } 089 } 090 } 091}