
001package ca.uhn.fhir.jpa.search.elastic; 002 003/*- 004 * #%L 005 * HAPI FHIR JPA Server 006 * %% 007 * Copyright (C) 2014 - 2022 Smile CDR, Inc. 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import ca.uhn.fhir.i18n.Msg; 024import ca.uhn.fhir.context.ConfigurationException; 025import ca.uhn.fhir.jpa.api.config.DaoConfig; 026import org.apache.commons.lang3.StringUtils; 027import org.hibernate.search.backend.elasticsearch.index.layout.IndexLayoutStrategy; 028import org.hibernate.search.backend.elasticsearch.logging.impl.Log; 029import org.hibernate.search.util.common.logging.impl.LoggerFactory; 030import org.springframework.beans.factory.annotation.Autowired; 031import org.springframework.stereotype.Service; 032 033import java.lang.invoke.MethodHandles; 034import java.util.regex.Matcher; 035import java.util.regex.Pattern; 036 037/** 038 * This class instructs hibernate search on how to create index names for indexed entities. 039 * In our case, we use this class to add an optional prefix to all indices which are created, which can be controlled via 040 * {@link DaoConfig#setElasticSearchIndexPrefix(String)}. 041 */ 042@Service 043public class IndexNamePrefixLayoutStrategy implements IndexLayoutStrategy { 044 045 @Autowired 046 private DaoConfig myDaoConfig; 047 048 static final Log log = LoggerFactory.make(Log.class, MethodHandles.lookup()); 049 public static final String NAME = "prefix"; 050 public static final Pattern UNIQUE_KEY_EXTRACTION_PATTERN = Pattern.compile("(.*)-\\d{6}"); 051 052 public String createInitialElasticsearchIndexName(String hibernateSearchIndexName) { 053 return addPrefixIfNecessary(hibernateSearchIndexName + "-000001"); 054 } 055 056 public String createWriteAlias(String hibernateSearchIndexName) { 057 return addPrefixIfNecessary(hibernateSearchIndexName +"-write"); 058 } 059 060 public String createReadAlias(String hibernateSearchIndexName) { 061 return addPrefixIfNecessary(hibernateSearchIndexName + "-read"); 062 } 063 064 private String addPrefixIfNecessary(String theCandidateName) { 065 validateDaoConfigIsPresent(); 066 if (!StringUtils.isBlank(myDaoConfig.getElasticSearchIndexPrefix())) { 067 return myDaoConfig.getElasticSearchIndexPrefix() + "-" + theCandidateName; 068 } else { 069 return theCandidateName; 070 } 071 } 072 073 public String extractUniqueKeyFromHibernateSearchIndexName(String hibernateSearchIndexName) { 074 return hibernateSearchIndexName; 075 } 076 077 public String extractUniqueKeyFromElasticsearchIndexName(String elasticsearchIndexName) { 078 Matcher matcher = UNIQUE_KEY_EXTRACTION_PATTERN.matcher(elasticsearchIndexName); 079 if (!matcher.matches()) { 080 throw log.invalidIndexPrimaryName(elasticsearchIndexName, UNIQUE_KEY_EXTRACTION_PATTERN); 081 } else { 082 String candidateUniqueKey= matcher.group(1); 083 return removePrefixIfNecessary(candidateUniqueKey); 084 } 085 } 086 087 private String removePrefixIfNecessary(String theCandidateUniqueKey) { 088 validateDaoConfigIsPresent(); 089 if (!StringUtils.isBlank(myDaoConfig.getElasticSearchIndexPrefix())) { 090 return theCandidateUniqueKey.replace(myDaoConfig.getElasticSearchIndexPrefix() + "-", ""); 091 } else { 092 return theCandidateUniqueKey; 093 } 094 } 095 private void validateDaoConfigIsPresent() { 096 if (myDaoConfig == null) { 097 throw new ConfigurationException(Msg.code(1168) + "While attempting to boot HAPI FHIR, the Hibernate Search bootstrapper failed to find the DaoConfig. This probably means Hibernate Search has been recently upgraded, or somebody modified HapiFhirLocalContainerEntityManagerFactoryBean."); 098 } 099 } 100}