docs: @Override
  	public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
  		HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<>();
  
  		String resourceName = getContext().getResourceDefinition(theResource).getName();
  
  		Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
  		for (RuntimeSearchParam nextSpDef : searchParams) {
  			if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.STRING) {
  				continue;
  			}
  
  			String nextPath = nextSpDef.getPath();
  			String nextSpName = nextSpDef.getName();
  
  			if (isBlank(nextPath)) {
  
  				// // TODO: implement phonetic, and any others that have no path
  				//
  				// // TODO: do we still need this check?
  				// if ("Questionnaire".equals(nextSpName) && nextSpDef.getName().equals("title")) {
  				// Questionnaire q = (Questionnaire) theResource;
  				// String title = "";// q.getGroup().getTitle();
  				// addSearchTerm(theEntity, retVal, nextSpName, title);
  				// }
  
  				continue;
  			}
  
  			for (Object nextObject : extractValues(nextPath, theResource)) {
  				if (nextObject == null || ((IBase) nextObject).isEmpty()) {
  					continue;
  				}
  
  				boolean multiType = false;
  				if (nextPath.endsWith("[x]")) {
  					multiType = true;
  				}
  
  				if (nextObject instanceof IPrimitiveType<?>) {
  					IPrimitiveType<?> nextValue = (IPrimitiveType<?>) nextObject;
  					String searchTerm = nextValue.getValueAsString();
  					addSearchTerm(theEntity, retVal, nextSpName, searchTerm);
  				} else {
  					if (nextObject instanceof HumanName) {
  						ArrayList<StringType> allNames = new ArrayList<>();
  						HumanName nextHumanName = (HumanName) nextObject;
  						if (isNotBlank(nextHumanName.getFamily())) {
  							allNames.add(nextHumanName.getFamilyElement());
  						}
  						allNames.addAll(nextHumanName.getGiven());
  						for (StringType nextName : allNames) {
  							addSearchTerm(theEntity, retVal, nextSpName, nextName.getValue());
  						}
  					} else if (nextObject instanceof Address) {
  						ArrayList<StringType> allNames = new ArrayList<>();
  						Address nextAddress = (Address) nextObject;
  						allNames.addAll(nextAddress.getLine());
  						allNames.add(nextAddress.getCityElement());
  						allNames.add(nextAddress.getStateElement());
  						allNames.add(nextAddress.getCountryElement());
  						allNames.add(nextAddress.getPostalCodeElement());
  						for (StringType nextName : allNames) {
  							addSearchTerm(theEntity, retVal, nextSpName, nextName.getValue());
  						}
  					} else if (nextObject instanceof ContactPoint) {
  						ContactPoint nextContact = (ContactPoint) nextObject;
  						if (nextContact.getValueElement().isEmpty() == false) {
  							addSearchTerm(theEntity, retVal, nextSpName, nextContact.getValue());
  						}
  					} else if (nextObject instanceof Quantity) {
  						BigDecimal value = ((Quantity) nextObject).getValue();
  						if (value != null) {
  							addSearchTerm(theEntity, retVal, nextSpName, value.toPlainString());
  						}
  					} else if (nextObject instanceof Range) {
  						Quantity low = ((Range) nextObject).getLow();
  						if (low != null) {
  							BigDecimal value = low.getValue();
  							if (value != null) {
  								addSearchTerm(theEntity, retVal, nextSpName, value.toPlainString());
  							}
  						}
  					} else {
  						if (!multiType) {
  							throw new ConfigurationException("Search param " + nextSpName + " is of unexpected datatype: " + nextObject.getClass());
  						}
  					}
  				}
  			}
  		}
  
  		return retVal;
  	}