/**
* The contents of this file are subject to the OpenMRS Public License
* Version 1.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://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.web.dwr;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.Concept;
import org.openmrs.GlobalProperty;
import org.openmrs.Location;
import org.openmrs.Patient;
import org.openmrs.PatientIdentifier;
import org.openmrs.PatientIdentifierType;
import org.openmrs.PersonAddress;
import org.openmrs.activelist.Allergy;
import org.openmrs.activelist.AllergySeverity;
import org.openmrs.activelist.AllergyType;
import org.openmrs.activelist.Problem;
import org.openmrs.activelist.ProblemModifier;
import org.openmrs.api.APIAuthenticationException;
import org.openmrs.api.APIException;
import org.openmrs.api.ConceptService;
import org.openmrs.api.DuplicateIdentifierException;
import org.openmrs.api.GlobalPropertyListener;
import org.openmrs.api.IdentifierNotUniqueException;
import org.openmrs.api.InsufficientIdentifiersException;
import org.openmrs.api.InvalidCheckDigitException;
import org.openmrs.api.InvalidIdentifierFormatException;
import org.openmrs.api.LocationService;
import org.openmrs.api.PatientIdentifierException;
import org.openmrs.api.PatientService;
import org.openmrs.api.context.Context;
import org.openmrs.patient.IdentifierValidator;
import org.openmrs.patient.UnallowedIdentifierException;
import org.openmrs.util.OpenmrsConstants;
/**
* DWR patient methods. The methods in here are used in the webapp to get data from the database via
* javascript calls.
*
* @see PatientService
*/
public class DWRPatientService implements GlobalPropertyListener {
private static final Log log = LogFactory.getLog(DWRPatientService.class);
private static Integer maximumResults;
/**
* Search on the <code>searchValue</code>. If a number is in the search string, do an identifier
* search. Else, do a name search
*
* @param searchValue string to be looked for
* @param includeVoided true/false whether or not to included voided patients
* @return Collection<Object> of PatientListItem or String
* @should return only patient list items with nonnumeric search
* @should return string warning if invalid patient identifier
* @should not return string warning if searching with valid identifier
* @should include string in results if doing extra decapitated search
* @should not return duplicate patient list items if doing decapitated search
* @should not do decapitated search if numbers are in the search string
* @should get results for patients that have edited themselves
* @should logged in user should load their own patient object
*/
public Collection<Object> findPatients(String searchValue, boolean includeVoided) {
return findBatchOfPatients(searchValue, includeVoided, null, null);
}
/**
* Search on the <code>searchValue</code>. If a number is in the search string, do an identifier
* search. Else, do a name search
*
* @see PatientService#getPatients(String, String, List, boolean, int, Integer)
* @param searchValue string to be looked for
* @param includeVoided true/false whether or not to included voided patients
* @param start The starting index for the results to return
* @param length The number of results of return
* @return Collection<Object> of PatientListItem or String
* @since 1.8
*/
@SuppressWarnings("unchecked")
public Collection<Object> findBatchOfPatients(String searchValue, boolean includeVoided, Integer start, Integer length) {
if (maximumResults == null)
maximumResults = getMaximumSearchResults();
if (length != null && length > maximumResults)
length = maximumResults;
// the list to return
List<Object> patientList = new Vector<Object>();
PatientService ps = Context.getPatientService();
Collection<Patient> patients;
try {
patients = ps.getPatients(searchValue, start, length);
}
catch (APIAuthenticationException e) {
patientList.add(Context.getMessageSourceService().getMessage("Patient.search.error") + " - " + e.getMessage());
return patientList;
}
patientList = new Vector<Object>(patients.size());
for (Patient p : patients)
patientList.add(new PatientListItem(p));
// if the length wasn't limited to less than 3 or this is the second ajax call
// and only 2 results found and a number was not in the
// search, then do a decapitated search: trim each word
// down to the first three characters and search again
if ((length == null || length > 2) && patients.size() < 3 && !searchValue.matches(".*\\d+.*")) {
String[] names = searchValue.split(" ");
String newSearch = "";
for (String name : names) {
if (name.length() > 3)
name = name.substring(0, 4);
newSearch += " " + name;
}
newSearch = newSearch.trim();
if (!newSearch.equals(searchValue)) {
Collection<Patient> newPatients = ps.getPatients(newSearch, start, length);
patients = CollectionUtils.union(newPatients, patients); // get unique hits
//reconstruct the results list
if (newPatients.size() > 0) {
patientList = new Vector<Object>(patients.size());
//patientList.add("Minimal patients returned. Results for <b>" + newSearch + "</b>");
for (Patient p : newPatients) {
PatientListItem pi = new PatientListItem(p);
patientList.add(pi);
}
}
}
}
//no results found and a number was in the search --
//should check whether the check digit is correct.
else if (patients.size() == 0 && searchValue.matches(".*\\d+.*")) {
//Looks through all the patient identifier validators to see if this type of identifier
//is supported for any of them. If it isn't, then no need to warn about a bad check
//digit. If it does match, then if any of the validators validates the check digit
//successfully, then the user is notified that the identifier has been entered correctly.
//Otherwise, the user is notified that the identifier was entered incorrectly.
Collection<IdentifierValidator> pivs = ps.getAllIdentifierValidators();
boolean shouldWarnUser = true;
boolean validCheckDigit = false;
boolean identifierMatchesValidationScheme = false;
for (IdentifierValidator piv : pivs) {
try {
if (piv.isValid(searchValue)) {
shouldWarnUser = false;
validCheckDigit = true;
}
identifierMatchesValidationScheme = true;
}
catch (UnallowedIdentifierException e) {}
}
if (identifierMatchesValidationScheme) {
if (shouldWarnUser)
patientList
.add("<p style=\"color:red; font-size:big;\"><b>WARNING: Identifier has been typed incorrectly! Please double check the identifier.</b></p>");
else if (validCheckDigit)
patientList
.add("<p style=\"color:green; font-size:big;\"><b>This identifier has been entered correctly, but still no patients have been found.</b></p>");
}
}
return patientList;
}
/**
* Returns a map of results with the values as count of matches and a partial list of the
* matching patients (depending on values of start and length parameters) while the keys are are
* 'count' and 'objectList' respectively, if the length parameter is not specified, then all
* matches will be returned from the start index if specified.
*
* @param searchValue patient name or identifier
* @param start the beginning index
* @param length the number of matching patients to return
* @param getMatchCount Specifies if the count of matches should be included in the returned map
* @return a map of results
* @throws APIException
* @since 1.8
*/
@SuppressWarnings("unchecked")
public Map<String, Object> findCountAndPatients(String searchValue, Integer start, Integer length, boolean getMatchCount)
throws APIException {
//Map to return
Map<String, Object> resultsMap = new HashMap<String, Object>();
Collection<Object> objectList = new Vector<Object>();
try {
PatientService ps = Context.getPatientService();
int patientCount = 0;
//if this is the first call
if (getMatchCount) {
patientCount += ps.getCountOfPatients(searchValue);
// if only 2 results found and a number was not in the
// search, then do a decapitated search: trim each word
// down to the first three characters and search again
if ((length == null || length > 2) && patientCount < 3 && !searchValue.matches(".*\\d+.*")) {
String[] names = searchValue.split(" ");
String newSearch = "";
for (String name : names) {
if (name.length() > 3)
name = name.substring(0, 4);
newSearch += " " + name;
}
newSearch = newSearch.trim();
if (!newSearch.equals(searchValue)) {
//since we already know that the list is small, it doesn't hurt to load the hits
//so that we can remove them from the list of the new search results and get the
//accurate count of matches
Collection<Patient> patients = ps.getPatients(searchValue);
newSearch = newSearch.trim();
Collection<Patient> newPatients = ps.getPatients(newSearch);
newPatients = CollectionUtils.union(newPatients, patients);
//Re-compute the count of all the unique patient hits
patientCount = newPatients.size();
if (newPatients.size() > 0) {
resultsMap.put("notification", Context.getMessageSourceService().getMessage(
"Patient.warning.minimalSearchResults", new Object[] { newSearch }, Context.getLocale()));
}
}
}
//no results found and a number was in the search --
//should check whether the check digit is correct.
else if (patientCount == 0 && searchValue.matches(".*\\d+.*")) {
//Looks through all the patient identifier validators to see if this type of identifier
//is supported for any of them. If it isn't, then no need to warn about a bad check
//digit. If it does match, then if any of the validators validates the check digit
//successfully, then the user is notified that the identifier has been entered correctly.
//Otherwise, the user is notified that the identifier was entered incorrectly.
Collection<IdentifierValidator> pivs = ps.getAllIdentifierValidators();
boolean shouldWarnUser = true;
boolean validCheckDigit = false;
boolean identifierMatchesValidationScheme = false;
for (IdentifierValidator piv : pivs) {
try {
if (piv.isValid(searchValue)) {
shouldWarnUser = false;
validCheckDigit = true;
}
identifierMatchesValidationScheme = true;
}
catch (UnallowedIdentifierException e) {}
}
if (identifierMatchesValidationScheme) {
if (shouldWarnUser)
resultsMap.put("notification", "<b>"
+ Context.getMessageSourceService().getMessage("Patient.warning.inValidIdentifier")
+ "<b/>");
else if (validCheckDigit)
resultsMap.put("notification", "<b style=\"color:green;\">"
+ Context.getMessageSourceService().getMessage("Patient.message.validIdentifier")
+ "<b/>");
}
} else {
//ensure that count never exceeds this value because the API's service layer would never
//return more than it since it is limited in the DAO layer
if (maximumResults == null)
maximumResults = getMaximumSearchResults();
if (length != null && length > maximumResults)
length = maximumResults;
if (patientCount > maximumResults) {
patientCount = maximumResults;
if (log.isDebugEnabled())
log.debug("Limitng the size of matching patients to " + maximumResults);
}
}
}
//if we have any matches or this isn't the first ajax call when the caller
//requests for the count
if (patientCount > 0 || !getMatchCount)
objectList = findBatchOfPatients(searchValue, false, start, length);
resultsMap.put("count", patientCount);
resultsMap.put("objectList", objectList);
}
catch (Exception e) {
log.error("Error while searching for patients", e);
objectList.clear();
objectList.add(Context.getMessageSourceService().getMessage("Patient.search.error") + " - " + e.getMessage());
resultsMap.put("count", 0);
resultsMap.put("objectList", objectList);
}
return resultsMap;
}
/**
* Convenience method for dwr/javascript to convert a patient id into a Patient object (or at
* least into data about the patient)
*
* @param patientId the {@link Patient#getPatientId()} to match on
* @return a truncated Patient object in the form of a PatientListItem
*/
public PatientListItem getPatient(Integer patientId) {
PatientService ps = Context.getPatientService();
Patient p = ps.getPatient(patientId);
PatientListItem pli = new PatientListItem(p);
if (p != null && p.getAddresses() != null && p.getAddresses().size() > 0) {
PersonAddress pa = (PersonAddress) p.getAddresses().toArray()[0];
pli.setAddress1(pa.getAddress1());
pli.setAddress2(pa.getAddress2());
}
return pli;
}
/**
* find all patients with duplicate attributes (searchOn)
*
* @param searchOn
* @return list of patientListItems
*/
public Vector<Object> findDuplicatePatients(String[] searchOn) {
Vector<Object> patientList = new Vector<Object>();
try {
List<String> options = new Vector<String>(searchOn.length);
for (String s : searchOn)
options.add(s);
List<Patient> patients = Context.getPatientService().getDuplicatePatientsByAttributes(options);
if (patients.size() > 200)
patients.subList(0, 200);
for (Patient p : patients)
patientList.add(new PatientListItem(p));
}
catch (Exception e) {
log.error(e);
patientList.add("Error while attempting to find duplicate patients - " + e.getMessage());
}
return patientList;
}
/**
* Auto generated method comment
*
* @param patientId
* @param identifierType
* @param identifier
* @param identifierLocationId
* @return
*/
public String addIdentifier(Integer patientId, String identifierType, String identifier, Integer identifierLocationId) {
String ret = "";
if (identifier == null || identifier.length() == 0)
return "PatientIdentifier.error.general";
PatientService ps = Context.getPatientService();
LocationService ls = Context.getLocationService();
Patient p = ps.getPatient(patientId);
PatientIdentifierType idType = ps.getPatientIdentifierTypeByName(identifierType);
//ps.updatePatientIdentifier(pi);
Location location = ls.getLocation(identifierLocationId);
log.debug("idType=" + identifierType + "->" + idType + " , location=" + identifierLocationId + "->" + location
+ " identifier=" + identifier);
PatientIdentifier id = new PatientIdentifier();
id.setIdentifierType(idType);
id.setIdentifier(identifier);
id.setLocation(location);
// in case we are editing, check to see if there is already an ID of this type and location
for (PatientIdentifier previousId : p.getActiveIdentifiers()) {
if (previousId.getIdentifierType().equals(idType) && previousId.getLocation().equals(location)) {
log.debug("Found equivalent ID: [" + idType + "][" + location + "][" + previousId.getIdentifier()
+ "], about to remove");
p.removeIdentifier(previousId);
} else {
if (!previousId.getIdentifierType().equals(idType))
log.debug("Previous ID id type does not match: [" + previousId.getIdentifierType().getName() + "]["
+ previousId.getIdentifier() + "]");
if (!previousId.getLocation().equals(location)) {
log.debug("Previous ID location is: " + previousId.getLocation());
log.debug("New location is: " + location);
}
}
}
p.addIdentifier(id);
try {
ps.savePatient(p);
}
catch (InvalidIdentifierFormatException iife) {
log.error(iife);
ret = "PatientIdentifier.error.formatInvalid";
}
catch (InvalidCheckDigitException icde) {
log.error(icde);
ret = "PatientIdentifier.error.checkDigit";
}
catch (IdentifierNotUniqueException inue) {
log.error(inue);
ret = "PatientIdentifier.error.notUnique";
}
catch (DuplicateIdentifierException die) {
log.error(die);
ret = "PatientIdentifier.error.duplicate";
}
catch (InsufficientIdentifiersException iie) {
log.error(iie);
ret = "PatientIdentifier.error.insufficientIdentifiers";
}
catch (PatientIdentifierException pie) {
log.error(pie);
ret = "PatientIdentifier.error.general";
}
return ret;
}
/**
* Auto generated method comment
*
* @param patientId
* @param reasonForExitId
* @param dateOfExit
* @param causeOfDeath
* @param otherReason
* @return
*/
public String exitPatientFromCare(Integer patientId, Integer exitReasonId, String exitDateStr,
Integer causeOfDeathConceptId, String otherReason) {
log.debug("Entering exitfromcare with [" + patientId + "] [" + exitReasonId + "] [" + exitDateStr + "]");
String ret = "";
PatientService ps = Context.getPatientService();
ConceptService cs = Context.getConceptService();
Patient patient = null;
try {
patient = ps.getPatient(patientId);
}
catch (Exception e) {
patient = null;
}
if (patient == null) {
ret = "Unable to find valid patient with the supplied identification information - cannot exit patient from care";
}
// Get the exit reason concept (if possible)
Concept exitReasonConcept = null;
try {
exitReasonConcept = cs.getConcept(exitReasonId);
}
catch (Exception e) {
exitReasonConcept = null;
}
// Exit reason error handling
if (exitReasonConcept == null) {
ret = "Unable to locate reason for exit in dictionary - cannot exit patient from care";
}
// Parse the exit date
Date exitDate = null;
if (exitDateStr != null) {
SimpleDateFormat sdf = Context.getDateFormat();
try {
exitDate = sdf.parse(exitDateStr);
}
catch (ParseException e) {
exitDate = null;
}
}
// Exit date error handling
if (exitDate == null) {
ret = "Invalid date supplied - cannot exit patient from care without a valid date.";
}
// If all data is provided as expected
if (patient != null && exitReasonConcept != null && exitDate != null) {
// need to check first if this is death or not
String patientDiedConceptId = Context.getAdministrationService().getGlobalProperty("concept.patientDied");
Concept patientDiedConcept = null;
if (patientDiedConceptId != null) {
patientDiedConcept = cs.getConcept(patientDiedConceptId);
}
// If there is a concept for death in the dictionary
if (patientDiedConcept != null) {
// If the exist reason == patient died
if (exitReasonConcept.equals(patientDiedConcept)) {
Concept causeOfDeathConcept = null;
try {
causeOfDeathConcept = cs.getConcept(causeOfDeathConceptId);
}
catch (Exception e) {
causeOfDeathConcept = null;
}
// Cause of death concept exists
if (causeOfDeathConcept != null) {
try {
ps.processDeath(patient, exitDate, causeOfDeathConcept, otherReason);
}
catch (Exception e) {
log.debug("Caught error", e);
ret = "Internal error while trying to process patient death - unable to proceed.";
}
}
// cause of death concept does not exist
else {
ret = "Unable to locate cause of death in dictionary - cannot proceed";
}
}
// Otherwise, we process this as an exit
else {
try {
ps.exitFromCare(patient, exitDate, exitReasonConcept);
}
catch (Exception e) {
log.debug("Caught error", e);
ret = "Internal error while trying to exit patient from care - unable to exit patient from care at this time.";
}
}
}
// If the system does not recognize death as a concept, then we exit from care
else {
try {
ps.exitFromCare(patient, exitDate, exitReasonConcept);
}
catch (Exception e) {
log.debug("Caught error", e);
ret = "Internal error while trying to exit patient from care - unable to exit patient from care at this time.";
}
}
log.debug("Exited from care, it seems");
}
return ret;
}
/**
* Auto generated method comment
*
* @param patientId
* @param locationId
* @return
*/
public String changeHealthCenter(Integer patientId, Integer locationId) {
log.warn("Deprecated method in 'DWRPatientService.changeHealthCenter'");
String ret = "";
/*
if ( patientId != null && locationId != null ) {
Patient patient = Context.getPatientService().getPatient(patientId);
Location location = Context.getEncounterService().getLocation(locationId);
if ( patient != null && location != null ) {
patient.setHealthCenter(location);
Context.getPatientService().updatePatient(patient);
}
}
*/
return ret;
}
/**
* Creates an Allergy Item
*
* @param patientId
* @param allergenId
* @param type
* @param pStartDate
* @param severity
* @param reactionId
*/
public void createAllergy(Integer patientId, Integer allergenId, String type, String pStartDate, String severity,
Integer reactionId) {
Date startDate = parseDate(pStartDate);
Patient patient = Context.getPatientService().getPatient(patientId);
Concept allergyConcept = Context.getConceptService().getConcept(allergenId);
Concept reactionConcept = (reactionId == null) ? null : Context.getConceptService().getConcept(reactionId);
AllergySeverity allergySeverity = StringUtils.isBlank(severity) ? null : AllergySeverity.valueOf(severity);
AllergyType allergyType = StringUtils.isBlank(type) ? null : AllergyType.valueOf(type);
Allergy allergy = new Allergy(patient, allergyConcept, startDate, allergyType, reactionConcept, allergySeverity);
Context.getPatientService().saveAllergy(allergy);
}
/**
* Save an Allergy
*
* @param activeListItemId
* @param allergenId Concept ID
* @param type
* @param pStartDate
* @param severity
* @param reactionId
*/
public void saveAllergy(Integer activeListItemId, Integer allergenId, String type, String pStartDate, String severity,
Integer reactionId) {
//get the allergy
Allergy allergy = Context.getPatientService().getAllergy(activeListItemId);
allergy.setAllergen(Context.getConceptService().getConcept(allergenId));
allergy.setAllergyType(type);
allergy.setStartDate(parseDate(pStartDate));
allergy.setSeverity(severity);
allergy.setReaction((reactionId == null) ? null : Context.getConceptService().getConcept(reactionId));
Context.getPatientService().saveAllergy(allergy);
}
/**
* Resolve an allergy
*
* @param activeListId
* @param resolved
* @param reason
* @param pEndDate
*/
public void removeAllergy(Integer activeListId, String reason) {
Allergy allergy = Context.getPatientService().getAllergy(activeListId);
Context.getPatientService().removeAllergy(allergy, reason);
}
/**
* Voids the Allergy
*
* @param activeListId
* @param reason
*/
public void voidAllergy(Integer activeListId, String reason) {
Allergy allergy = Context.getPatientService().getAllergy(activeListId);
if (reason == null) {
reason = "Error - user entered incorrect data from UI";
}
Context.getPatientService().voidAllergy(allergy, reason);
}
/**
* Creates a Problem Item
*
* @param patientId
* @param problemId
* @param status
* @param pStartDate
* @param comments
*/
public void createProblem(Integer patientId, Integer problemId, String status, String pStartDate, String comments) {
Patient patient = Context.getPatientService().getPatient(patientId);
Concept problemConcept = Context.getConceptService().getConcept(problemId);
ProblemModifier modifier = StringUtils.isBlank(status) ? null : ProblemModifier.valueOf(status);
Problem problem = new Problem(patient, problemConcept, parseDate(pStartDate), modifier, comments, null);
Context.getPatientService().saveProblem(problem);
}
/**
* Saves the Problem
*
* @param activeListId
* @param problemId
* @param status
* @param pStartDate
* @param comments
*/
public void saveProblem(Integer activeListId, Integer problemId, String status, String pStartDate, String comments) {
//get the allergy
Problem problem = Context.getPatientService().getProblem(activeListId);
problem.setProblem(Context.getConceptService().getConcept(problemId));
problem.setModifier(status);
problem.setStartDate(parseDate(pStartDate));
problem.setComments(comments);
Context.getPatientService().saveProblem(problem);
}
/**
* Remove a problem, sets the end date
*
* @param activeListId
* @param resolved
* @param reason
* @param pEndDate
*/
public void removeProblem(Integer activeListId, String reason, String pEndDate) {
Problem problem = Context.getPatientService().getProblem(activeListId);
problem.setEndDate(parseDate(pEndDate));
Context.getPatientService().removeProblem(problem, reason);
}
/**
* Voids the Problem
*
* @param activeListId
* @param reason
*/
public void voidProblem(Integer activeListId, String reason) {
Problem problem = Context.getPatientService().getProblem(activeListId);
if (reason == null) {
reason = "Error - user entered incorrect data from UI";
}
Context.getPatientService().voidProblem(problem, reason);
}
/**
* Simple utility method to parse the date object into the correct, local format
*
* @param date
* @return
*/
private Date parseDate(String date) {
if (date != null) {
SimpleDateFormat sdf = Context.getDateFormat();
try {
return sdf.parse(date);
}
catch (ParseException e) {}
}
return null;
}
@Override
public boolean supportsPropertyName(String propertyName) {
return propertyName.equals(OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS);
}
@Override
public void globalPropertyChanged(GlobalProperty newValue) {
try {
maximumResults = Integer.valueOf(newValue.getPropertyValue());
}
catch (NumberFormatException e) {
maximumResults = OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS_DEFAULT_VALUE;
}
}
@Override
public void globalPropertyDeleted(String propertyName) {
maximumResults = OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS_DEFAULT_VALUE;
}
/**
* Fetch the max results value from the global properties table
*
* @return Integer value for the person search max results global property
*/
private static Integer getMaximumSearchResults() {
try {
return Integer.valueOf(Context.getAdministrationService().getGlobalProperty(
OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS,
String.valueOf(OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS_DEFAULT_VALUE)));
}
catch (Exception e) {
log.warn("Unable to convert the global property " + OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS
+ "to a valid integer. Returning the default "
+ OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS_DEFAULT_VALUE);
}
return OpenmrsConstants.GLOBAL_PROPERTY_PERSON_SEARCH_MAX_RESULTS_DEFAULT_VALUE;
}
}