diff --git a/src/main/java/org/opensrp/web/rest/RestUtils.java b/src/main/java/org/opensrp/web/rest/RestUtils.java index 56c42e752..940acfff1 100644 --- a/src/main/java/org/opensrp/web/rest/RestUtils.java +++ b/src/main/java/org/opensrp/web/rest/RestUtils.java @@ -20,6 +20,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.joda.time.DateTime; +import org.json.JSONObject; import org.keycloak.KeycloakPrincipal; import org.keycloak.KeycloakSecurityContext; import org.keycloak.representations.AccessToken; @@ -27,107 +28,112 @@ import org.opensrp.domain.Multimedia; import org.opensrp.service.multimedia.MultimediaFileManager; import org.opensrp.service.multimedia.S3MultimediaFileManager; -import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.security.core.Authentication; public class RestUtils { - public static final String DATE_FORMAT = "dd-MM-yyyy"; - public static final SimpleDateFormat SDF = new SimpleDateFormat("dd-MM-yyyy"); - public static final String DATETIME_FORMAT = "dd-MM-yyyy HH:mm"; - public static final SimpleDateFormat SDTF = new SimpleDateFormat("dd-MM-yyyy HH:mm"); - - private static final Logger logger = LogManager.getLogger(RestUtils.class.toString()); - - - public static String getStringFilter(String filter, HttpServletRequest req) - { - return StringUtils.isBlank(req.getParameter(filter)) ? null : req.getParameter(filter); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static Enum getEnumFilter(String filter, Class cls, HttpServletRequest req) - { - String filterVal = getStringFilter(filter, req); - if (filterVal != null) { - return Enum.valueOf(cls, filterVal); - } - return null; - } - - public static Integer getIntegerFilter(String filter, HttpServletRequest req) - { - String strval = getStringFilter(filter, req); - return strval == null ? null : Integer.parseInt(strval); - } - - public static Float getFloatFilter(String filter, HttpServletRequest req) - { - String strval = getStringFilter(filter, req); - return strval == null ? null : Float.parseFloat(strval); - } - - public static DateTime getDateFilter(String filter, HttpServletRequest req) throws ParseException - { - String strval = getStringFilter(filter, req); - return strval == null ? null : new DateTime(strval); - } - - public static DateTime[] getDateRangeFilter(String filter, HttpServletRequest req) throws ParseException - { - String strval = getStringFilter(filter, req); - if(strval == null){ - return null; - } - if (!strval.contains(":")) { - return new DateTime[] { new DateTime(strval), new DateTime(strval) }; - } - DateTime d1 = new DateTime(strval.substring(0, strval.indexOf(":"))); - DateTime d2 = new DateTime(strval.substring(strval.indexOf(":")+1)); - return new DateTime[]{d1,d2}; - } - - public static boolean getBooleanFilter(String filter, HttpServletRequest req) { - String stringFilter = getStringFilter(filter, req); - return Boolean.parseBoolean(stringFilter); - } - - public static void main(String[] args) { - System.out.println(new DateTime("​1458932400000")); - } - - public static synchronized String setDateFilter(Date date) throws ParseException - { - return date == null ? null : SDF.format(date); - } - - public static void verifyRequiredProperties(List properties, T entity) { - if(properties != null) - for (String p : properties) { - Field[] aaa = entity.getClass().getDeclaredFields(); - for (Field field : aaa) { - if(field.getName().equals(p)){ - field.setAccessible(true); - try { - if(field.get(entity) == null || field.get(entity).toString().trim().equalsIgnoreCase("")){ - throw new RuntimeException("A required field "+p+" was found empty"); - } - } catch (IllegalArgumentException e) { - e.printStackTrace(); - throw new RuntimeException("A required field "+p+" was not found in resource class"); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - } - } - - public static HttpHeaders getJSONUTF8Headers() { - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.add("Content-Type", "application/json; charset=utf-8"); - return responseHeaders; - } + public static final String DATE_FORMAT = "dd-MM-yyyy"; + public static final SimpleDateFormat SDF = new SimpleDateFormat("dd-MM-yyyy"); + public static final String DATETIME_FORMAT = "dd-MM-yyyy HH:mm"; + public static final SimpleDateFormat SDTF = new SimpleDateFormat("dd-MM-yyyy HH:mm"); + + private static final Logger logger = LogManager.getLogger(RestUtils.class.toString()); + + + public static String getStringFilter(String filter, HttpServletRequest req) { + return StringUtils.isBlank(req.getParameter(filter)) ? null : req.getParameter(filter); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public static Enum getEnumFilter(String filter, Class cls, HttpServletRequest req) { + String filterVal = getStringFilter(filter, req); + if (filterVal != null) { + return Enum.valueOf(cls, filterVal); + } + return null; + } + + public static Integer getIntegerFilter(String filter, HttpServletRequest req) { + String strval = getStringFilter(filter, req); + return strval == null ? null : Integer.parseInt(strval); + } + + public static Float getFloatFilter(String filter, HttpServletRequest req) { + String strval = getStringFilter(filter, req); + return strval == null ? null : Float.parseFloat(strval); + } + + public static DateTime getDateFilter(String filter, HttpServletRequest req) throws ParseException { + String strval = getStringFilter(filter, req); + return strval == null ? null : new DateTime(strval); + } + + public static DateTime[] getDateRangeFilter(String filter, HttpServletRequest req) throws ParseException { + String strval = getStringFilter(filter, req); + if (strval == null) { + return null; + } + if (!strval.contains(":")) { + return new DateTime[]{new DateTime(strval), new DateTime(strval)}; + } + DateTime d1 = new DateTime(strval.substring(0, strval.indexOf(":"))); + DateTime d2 = new DateTime(strval.substring(strval.indexOf(":") + 1)); + return new DateTime[]{d1, d2}; + } + + public static DateTime[] getDateRangeFilter(String filter, JSONObject jsonObject) throws ParseException { + String strval = jsonObject.optString(filter); + if (strval.equals("")) { + return null; + } + if (!strval.contains(":")) { + return new DateTime[]{new DateTime(strval), new DateTime(strval)}; + } + DateTime d1 = new DateTime(strval.substring(0, strval.indexOf(":"))); + DateTime d2 = new DateTime(strval.substring(strval.indexOf(":") + 1)); + return new DateTime[]{d1, d2}; + } + + public static boolean getBooleanFilter(String filter, HttpServletRequest req) { + String stringFilter = getStringFilter(filter, req); + return Boolean.parseBoolean(stringFilter); + } + + public static void main(String[] args) { + System.out.println(new DateTime("​1458932400000")); + } + + public static synchronized String setDateFilter(Date date) throws ParseException { + return date == null ? null : SDF.format(date); + } + + public static void verifyRequiredProperties(List properties, T entity) { + if (properties != null) + for (String p : properties) { + Field[] aaa = entity.getClass().getDeclaredFields(); + for (Field field : aaa) { + if (field.getName().equals(p)) { + field.setAccessible(true); + try { + if (field.get(entity) == null || field.get(entity).toString().trim().equalsIgnoreCase("")) { + throw new RuntimeException("A required field " + p + " was found empty"); + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + throw new RuntimeException("A required field " + p + " was not found in resource class"); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + } + } + + public static HttpHeaders getJSONUTF8Headers() { + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add("Content-Type", "application/json; charset=utf-8"); + return responseHeaders; + } /** * Zips multimedia files and writes content to {@param zipOutputStream} @@ -136,91 +142,88 @@ public static HttpHeaders getJSONUTF8Headers() { * @param multimediaFiles * @throws IOException */ - public static void zipFiles(ZipOutputStream zipOutputStream, List multimediaFiles, MultimediaFileManager fileManager) throws IOException { - for (Multimedia multiMedia : multimediaFiles) { - FileInputStream inputStream; - File file = fileManager.retrieveFile(multiMedia.getFilePath()); - if (file != null) { - logger.info("Adding " + file.getName()); - zipOutputStream.putNextEntry(new ZipEntry(file.getName())); - try { - inputStream = new FileInputStream(file); - } catch (FileNotFoundException e) { - logger.warn("Could not find file " + file.getAbsolutePath()); - continue; - } - - // Write the contents of the file - BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); - int data; - while ((data = bufferedInputStream.read()) != -1) { - zipOutputStream.write(data); - } - bufferedInputStream.close(); - zipOutputStream.closeEntry(); - logger.info("Done downloading file " + file.getName()); - - // clean up temp files (may want to cache in future) - if (fileManager instanceof S3MultimediaFileManager) { - file.delete(); - } - } - } - } - - public static User currentUser(Authentication authentication) { - if (authentication != null && authentication.getPrincipal() instanceof KeycloakPrincipal) { - @SuppressWarnings("unchecked") - KeycloakPrincipal kp = (KeycloakPrincipal) authentication - .getPrincipal(); - AccessToken token = kp.getKeycloakSecurityContext().getToken(); - User user = new User(authentication.getName()); - user.setPreferredName(token.getName()); - user.setUsername(token.getPreferredUsername()); - List authorities = authentication.getAuthorities().stream().map(e -> e.getAuthority()) - .collect(Collectors.toList()); - user.setAttributes(token.getOtherClaims()); - user.setRoles(authorities); - user.setPermissions(authorities); - return user; - } - return null; - } - - public static void writeToZipFile(String fileName, ZipOutputStream zipStream, String filePath) throws IOException { - File aFile; - FileInputStream fis = null; - ZipEntry zipEntry; - String tempDirectory = System.getProperty("java.io.tmpdir"); - try{ - if(StringUtils.isNotBlank(fileName)) { - aFile = new File(StringUtils.isNotBlank(filePath) ? filePath : fileName); - fis = new FileInputStream(aFile); - zipEntry = new ZipEntry(StringUtils.isNotBlank(filePath) ? filePath.replace(tempDirectory, "") : fileName); - logger.info("Writing file : '" + fileName + "' to zip file"); - } - else { - fis = new FileInputStream(filePath); - zipEntry = new ZipEntry(filePath); - logger.info("Writing file : '" + filePath + "' to zip file"); - } - zipStream.putNextEntry(zipEntry); - byte[] bytes = new byte[1024]; - int length; - while ((length = fis.read(bytes)) >= 0) { - zipStream.write(bytes, 0, length); - } - - zipStream.closeEntry(); - } - catch (IOException e) { - logger.error("IO Exception occurred: " + e.getMessage()); - } - finally { - if (fis != null) { - fis.close(); - } - } - } + public static void zipFiles(ZipOutputStream zipOutputStream, List multimediaFiles, MultimediaFileManager fileManager) throws IOException { + for (Multimedia multiMedia : multimediaFiles) { + FileInputStream inputStream; + File file = fileManager.retrieveFile(multiMedia.getFilePath()); + if (file != null) { + logger.info("Adding " + file.getName()); + zipOutputStream.putNextEntry(new ZipEntry(file.getName())); + try { + inputStream = new FileInputStream(file); + } catch (FileNotFoundException e) { + logger.warn("Could not find file " + file.getAbsolutePath()); + continue; + } + + // Write the contents of the file + BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); + int data; + while ((data = bufferedInputStream.read()) != -1) { + zipOutputStream.write(data); + } + bufferedInputStream.close(); + zipOutputStream.closeEntry(); + logger.info("Done downloading file " + file.getName()); + + // clean up temp files (may want to cache in future) + if (fileManager instanceof S3MultimediaFileManager) { + file.delete(); + } + } + } + } + + public static User currentUser(Authentication authentication) { + if (authentication != null && authentication.getPrincipal() instanceof KeycloakPrincipal) { + @SuppressWarnings("unchecked") + KeycloakPrincipal kp = (KeycloakPrincipal) authentication + .getPrincipal(); + AccessToken token = kp.getKeycloakSecurityContext().getToken(); + User user = new User(authentication.getName()); + user.setPreferredName(token.getName()); + user.setUsername(token.getPreferredUsername()); + List authorities = authentication.getAuthorities().stream().map(e -> e.getAuthority()) + .collect(Collectors.toList()); + user.setAttributes(token.getOtherClaims()); + user.setRoles(authorities); + user.setPermissions(authorities); + return user; + } + return null; + } + + public static void writeToZipFile(String fileName, ZipOutputStream zipStream, String filePath) throws IOException { + File aFile; + FileInputStream fis = null; + ZipEntry zipEntry; + String tempDirectory = System.getProperty("java.io.tmpdir"); + try { + if (StringUtils.isNotBlank(fileName)) { + aFile = new File(StringUtils.isNotBlank(filePath) ? filePath : fileName); + fis = new FileInputStream(aFile); + zipEntry = new ZipEntry(StringUtils.isNotBlank(filePath) ? filePath.replace(tempDirectory, "") : fileName); + logger.info("Writing file : '" + fileName + "' to zip file"); + } else { + fis = new FileInputStream(filePath); + zipEntry = new ZipEntry(filePath); + logger.info("Writing file : '" + filePath + "' to zip file"); + } + zipStream.putNextEntry(zipEntry); + byte[] bytes = new byte[1024]; + int length; + while ((length = fis.read(bytes)) >= 0) { + zipStream.write(bytes, 0, length); + } + + zipStream.closeEntry(); + } catch (IOException e) { + logger.error("IO Exception occurred: " + e.getMessage()); + } finally { + if (fis != null) { + fis.close(); + } + } + } } diff --git a/src/main/java/org/opensrp/web/rest/SearchResource.java b/src/main/java/org/opensrp/web/rest/SearchResource.java index 75b1d186d..713919661 100644 --- a/src/main/java/org/opensrp/web/rest/SearchResource.java +++ b/src/main/java/org/opensrp/web/rest/SearchResource.java @@ -4,6 +4,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.joda.time.DateTime; +import org.json.JSONObject; import org.opensrp.common.AllConstants.BaseEntity; import org.opensrp.search.ClientSearchBean; import org.opensrp.service.ClientService; @@ -17,6 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -45,209 +47,274 @@ @Controller @RequestMapping(value = "/rest/search") public class SearchResource extends RestResource { - - private static Logger logger = LogManager.getLogger(SearchResource.class.toString()); - - private SearchService searchService; - - private ClientService clientService; - - private EventService eventService; - - @Autowired - public SearchResource(SearchService searchService, ClientService clientService, EventService eventService) { - this.searchService = searchService; - this.clientService = clientService; - this.eventService = eventService; - } - - /** - * @param request - * contains search parameter of with attributes and full colon e.g - * 1. search?attributes=phone_number:072700000 - * or search parameter without attribute and without colon e.g - * 2. search?phone_number=072700000 - * @throws ParseException - */ - @Override - public List search(HttpServletRequest request) throws ParseException {//TODO search should not call different url but only add params - String firstName = getStringFilter(FIRST_NAME, request); - String middleName = getStringFilter(MIDDLE_NAME, request); - String lastName = getStringFilter(LAST_NAME, request); - Optional phoneNumber = Optional.ofNullable(getStringFilter(PHONE_NUMBER, request)); - Optional altPhoneNumber = Optional.ofNullable(getStringFilter(ALT_PHONE_NUMBER, request)); - Optional alternateName = Optional.ofNullable(getStringFilter(ALT_NAME, request)); - ClientSearchBean searchBean = new ClientSearchBean(); - searchBean.setNameLike(getStringFilter(NAME, request)); - - searchBean.setGender(getStringFilter(GENDER, request)); - DateTime[] birthdate = RestUtils.getDateRangeFilter(BIRTH_DATE, request);//TODO add ranges like fhir do http://hl7.org/fhir/search.html - DateTime[] lastEdit = RestUtils.getDateRangeFilter(LAST_UPDATE, request);//TODO client by provider id - //TODO lookinto Swagger https://slack-files.com/files-pri-safe/T0EPSEJE9-F0TBD0N77/integratingswagger.pdf?c=1458211183-179d2bfd2e974585c5038fba15a86bf83097810a - - if (birthdate != null) { - searchBean.setBirthdateFrom(birthdate[0]); - searchBean.setBirthdateTo(birthdate[1]); - } - if (lastEdit != null) { - searchBean.setLastEditFrom(lastEdit[0]); - searchBean.setLastEditTo(lastEdit[1]); - } - Map attributeMap = new HashMap<>(); - String attributes = getStringFilter(ATTRIBUTE, request); - if (!StringUtils.isBlank(attributes)) { - String attributeType = StringUtils.isBlank(attributes) ? null : attributes.split(":", -1)[0]; - String attributeValue = StringUtils.isBlank(attributes) ? null : attributes.split(":", -1)[1]; - attributeMap.put(attributeType, attributeValue); - } - phoneNumber.ifPresent(phoneValue -> attributeMap.put(PHONE_NUMBER, phoneValue)); - altPhoneNumber.ifPresent(altPhoneValue -> attributeMap.put(ALT_PHONE_NUMBER, altPhoneValue)); - alternateName.ifPresent(altNameValue -> attributeMap.put(ALT_NAME, altNameValue)); - searchBean.setAttributes(attributeMap); - - Map identifierMap = null; - String identifiers = getStringFilter(IDENTIFIER, request); - if (!StringUtils.isBlank(identifiers)) { - String identifierType = StringUtils.isBlank(identifiers) ? null : identifiers.split(":", -1)[0]; - String identifierValue = StringUtils.isBlank(identifiers) ? null : identifiers.split(":", -1)[1]; - - identifierMap = new HashMap(); - identifierMap.put(identifierType, identifierValue); - } - - searchBean.setIdentifiers(identifierMap); - return searchService.searchClient(searchBean, firstName, middleName, lastName, null); - } - - @RequestMapping(method = RequestMethod.GET, value = "/path", produces = { MediaType.APPLICATION_JSON_VALUE }) - private List searchPathBy(HttpServletRequest request) throws ParseException { - try { - - //Process clients search via demographics - - ClientSearchBean searchBean = new ClientSearchBean(); - List children = new ArrayList(); - - SearchEntityWrapper childSearchEntity = SearchHelper.childSearchParamProcessor(request); - - if (childSearchEntity.isValid()) { - searchBean = childSearchEntity.getClientSearchBean(); - children = searchService.searchClient(searchBean, searchBean.getFirstName(), searchBean.getMiddleName(), - searchBean.getLastName(), childSearchEntity.getLimit()); - } - - //Process mothers search via mother demographics - - SearchEntityWrapper motherSearchEntity = SearchHelper.motherSearchParamProcessor(request); - ClientSearchBean motherSearchBean = new ClientSearchBean(); - List mothers = new ArrayList(); - - if (motherSearchEntity.isValid()) { - motherSearchBean = motherSearchEntity.getClientSearchBean(); - mothers = searchService.searchClient(motherSearchBean, motherSearchBean.getFirstName(), - motherSearchBean.getMiddleName(), motherSearchBean.getLastName(), motherSearchEntity.getLimit()); - } - - //Process clients search via contact phone number - - String contactPhoneNumber = SearchHelper.getContactPhoneNumberParam(request); - - List clientBaseEntityIds = getClientBaseEntityIdsByContactPhoneNumber(contactPhoneNumber); - - List eventChildren = clientService.findByFieldValue(BaseEntity.BASE_ENTITY_ID, clientBaseEntityIds); - - children = SearchHelper.intersection(children, eventChildren);// Search conjunction is "AND" find intersection - - List linkedMothers = new ArrayList(); - - String RELATIONSHIP_KEY = "mother"; - if (!children.isEmpty()) { - List clientIds = new ArrayList(); - for (Client c : children) { - String relationshipId = SearchHelper.getRelationalId(c, RELATIONSHIP_KEY); - if (relationshipId != null && !clientIds.contains(relationshipId)) { - clientIds.add(relationshipId); - } - } - - linkedMothers = clientService.findByFieldValue(BaseEntity.BASE_ENTITY_ID, clientIds); - - } - - List linkedChildren = new ArrayList(); - - if (!mothers.isEmpty()) { - for (Client client : mothers) { - linkedChildren.addAll(clientService.findByRelationship(client.getBaseEntityId())); - } - } - - children = SearchHelper.intersection(children, linkedChildren);// Search conjunction is "AND" find intersection - - for (Client linkedMother : linkedMothers) { - if (!SearchHelper.contains(mothers, linkedMother)) { - mothers.add(linkedMother); - } - } - - return SearchHelper.processSearchResult(children, mothers, RELATIONSHIP_KEY); - - } - catch (Exception e) { - - logger.error("", e); - return new ArrayList(); - } - } - - public List getClientBaseEntityIdsByContactPhoneNumber(String motherGuardianPhoneNumber) { - List clientBaseEntityIds = new ArrayList(); - - if (!StringUtils.isBlank(motherGuardianPhoneNumber)) { - - List events = eventService.findEventsByConceptAndValue("159635AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - motherGuardianPhoneNumber); - if (events != null && !events.isEmpty()) { - for (Event event : events) { - String entityId = event.getBaseEntityId(); - if (entityId != null && !clientBaseEntityIds.contains(entityId)) { - clientBaseEntityIds.add(entityId); - } - } - - } - } - return clientBaseEntityIds; - } - - @Override - public List filter(String query) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Client getByUniqueId(String uniqueId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public List requiredProperties() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Client create(Client entity) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Client update(Client entity) { - // TODO Auto-generated method stub - return null; - } - + + private static Logger logger = LogManager.getLogger(SearchResource.class.toString()); + + private SearchService searchService; + + private ClientService clientService; + + private EventService eventService; + + @Autowired + public SearchResource(SearchService searchService, ClientService clientService, EventService eventService) { + this.searchService = searchService; + this.clientService = clientService; + this.eventService = eventService; + } + + /** + * @param request contains search parameter of with attributes and full colon e.g + * 1. search?attributes=phone_number:072700000 + * or search parameter without attribute and without colon e.g + * 2. search?phone_number=072700000 + * @throws ParseException + */ + @Override + public List search(HttpServletRequest request) throws ParseException {//TODO search should not call different url but only add params + String firstName = getStringFilter(FIRST_NAME, request); + String middleName = getStringFilter(MIDDLE_NAME, request); + String lastName = getStringFilter(LAST_NAME, request); + Optional phoneNumber = Optional.ofNullable(getStringFilter(PHONE_NUMBER, request)); + Optional altPhoneNumber = Optional.ofNullable(getStringFilter(ALT_PHONE_NUMBER, request)); + Optional alternateName = Optional.ofNullable(getStringFilter(ALT_NAME, request)); + ClientSearchBean searchBean = new ClientSearchBean(); + searchBean.setNameLike(getStringFilter(NAME, request)); + + searchBean.setGender(getStringFilter(GENDER, request)); + DateTime[] birthdate = RestUtils.getDateRangeFilter(BIRTH_DATE, request);//TODO add ranges like fhir do http://hl7.org/fhir/search.html + DateTime[] lastEdit = RestUtils.getDateRangeFilter(LAST_UPDATE, request);//TODO client by provider id + //TODO lookinto Swagger https://slack-files.com/files-pri-safe/T0EPSEJE9-F0TBD0N77/integratingswagger.pdf?c=1458211183-179d2bfd2e974585c5038fba15a86bf83097810a + + if (birthdate != null) { + searchBean.setBirthdateFrom(birthdate[0]); + searchBean.setBirthdateTo(birthdate[1]); + } + if (lastEdit != null) { + searchBean.setLastEditFrom(lastEdit[0]); + searchBean.setLastEditTo(lastEdit[1]); + } + Map attributeMap = new HashMap<>(); + String attributes = getStringFilter(ATTRIBUTE, request); + if (!StringUtils.isBlank(attributes)) { + String attributeType = StringUtils.isBlank(attributes) ? null : attributes.split(":", -1)[0]; + String attributeValue = StringUtils.isBlank(attributes) ? null : attributes.split(":", -1)[1]; + attributeMap.put(attributeType, attributeValue); + } + phoneNumber.ifPresent(phoneValue -> attributeMap.put(PHONE_NUMBER, phoneValue)); + altPhoneNumber.ifPresent(altPhoneValue -> attributeMap.put(ALT_PHONE_NUMBER, altPhoneValue)); + alternateName.ifPresent(altNameValue -> attributeMap.put(ALT_NAME, altNameValue)); + searchBean.setAttributes(attributeMap); + + Map identifierMap = null; + String identifiers = getStringFilter(IDENTIFIER, request); + if (!StringUtils.isBlank(identifiers)) { + String identifierType = StringUtils.isBlank(identifiers) ? null : identifiers.split(":", -1)[0]; + String identifierValue = StringUtils.isBlank(identifiers) ? null : identifiers.split(":", -1)[1]; + + identifierMap = new HashMap(); + identifierMap.put(identifierType, identifierValue); + } + + searchBean.setIdentifiers(identifierMap); + return searchService.searchClient(searchBean, firstName, middleName, lastName, null); + } + + @RequestMapping(method = RequestMethod.POST, value = "/search", produces = {MediaType.APPLICATION_JSON_VALUE}) + public List searchByPost(@RequestBody String jsonRequestBody) throws ParseException {//TODO search should not call different url but only add params + JSONObject jsonObject = new JSONObject(jsonRequestBody); + String firstName = jsonObject.optString(FIRST_NAME); + String middleName = jsonObject.optString(MIDDLE_NAME); + String lastName = jsonObject.optString(LAST_NAME); + Optional phoneNumber = Optional.ofNullable(jsonObject.optString(PHONE_NUMBER)); + Optional altPhoneNumber = Optional.ofNullable(jsonObject.optString(ALT_PHONE_NUMBER)); + Optional alternateName = Optional.ofNullable(jsonObject.optString(ALT_NAME)); + ClientSearchBean searchBean = new ClientSearchBean(); + searchBean.setNameLike(jsonObject.optString(NAME)); + + searchBean.setGender(jsonObject.optString(GENDER)); + DateTime[] birthdate = RestUtils.getDateRangeFilter(BIRTH_DATE, jsonObject);//TODO add ranges like fhir do http://hl7.org/fhir/search.html + DateTime[] lastEdit = RestUtils.getDateRangeFilter(LAST_UPDATE, jsonObject);//TODO client by provider id + //TODO lookinto Swagger https://slack-files.com/files-pri-safe/T0EPSEJE9-F0TBD0N77/integratingswagger.pdf?c=1458211183-179d2bfd2e974585c5038fba15a86bf83097810a + + if (birthdate != null) { + searchBean.setBirthdateFrom(birthdate[0]); + searchBean.setBirthdateTo(birthdate[1]); + } + if (lastEdit != null) { + searchBean.setLastEditFrom(lastEdit[0]); + searchBean.setLastEditTo(lastEdit[1]); + } + Map attributeMap = new HashMap<>(); + String attributes = jsonObject.optString(ATTRIBUTE); + if (!StringUtils.isBlank(attributes)) { + String attributeType = StringUtils.isBlank(attributes) ? null : attributes.split(":", -1)[0]; + String attributeValue = StringUtils.isBlank(attributes) ? null : attributes.split(":", -1)[1]; + attributeMap.put(attributeType, attributeValue); + } + phoneNumber.ifPresent(phoneValue -> attributeMap.put(PHONE_NUMBER, phoneValue)); + altPhoneNumber.ifPresent(altPhoneValue -> attributeMap.put(ALT_PHONE_NUMBER, altPhoneValue)); + alternateName.ifPresent(altNameValue -> attributeMap.put(ALT_NAME, altNameValue)); + searchBean.setAttributes(attributeMap); + + Map identifierMap = null; + String identifiers = jsonObject.optString(IDENTIFIER); + if (!StringUtils.isBlank(identifiers)) { + String identifierType = StringUtils.isBlank(identifiers) ? null : identifiers.split(":", -1)[0]; + String identifierValue = StringUtils.isBlank(identifiers) ? null : identifiers.split(":", -1)[1]; + + identifierMap = new HashMap(); + identifierMap.put(identifierType, identifierValue); + } + + searchBean.setIdentifiers(identifierMap); + return searchService.searchClient(searchBean, firstName, middleName, lastName, null); + } + + @RequestMapping(method = RequestMethod.GET, value = "/path", produces = {MediaType.APPLICATION_JSON_VALUE}) + private List searchPathByGet(HttpServletRequest request) throws ParseException { + + String contactPhoneNumber = SearchHelper.getContactPhoneNumberParam(request); + SearchEntityWrapper childSearchEntity = SearchHelper.childSearchParamProcessor(request); + SearchEntityWrapper motherSearchEntity = SearchHelper.motherSearchParamProcessor(request); + + return searchAndProcess(childSearchEntity, motherSearchEntity, contactPhoneNumber); + } + + @RequestMapping(method = RequestMethod.POST, value = "/path", produces = {MediaType.APPLICATION_JSON_VALUE}) + private List searchPathByPost(@RequestBody String jsonRequestBody) throws ParseException { + + JSONObject jsonRequestBodyObject = new JSONObject(jsonRequestBody); + SearchEntityWrapper childSearchEntity = SearchHelper.childSearchParamProcessor(jsonRequestBodyObject); + SearchEntityWrapper motherSearchEntity = SearchHelper.motherSearchParamProcessor(jsonRequestBodyObject); + String contactPhoneNumber = SearchHelper.getContactPhoneNumberParam(jsonRequestBodyObject); + + return searchAndProcess(childSearchEntity, motherSearchEntity, contactPhoneNumber); + + } + + private List searchAndProcess(SearchEntityWrapper childSearchEntity, SearchEntityWrapper motherSearchEntity, + String contactPhoneNumber) { + try { + //Process clients search via demographics + + ClientSearchBean searchBean = new ClientSearchBean(); + List children = new ArrayList(); + if (childSearchEntity.isValid()) { + searchBean = childSearchEntity.getClientSearchBean(); + children = searchService.searchClient(searchBean, searchBean.getFirstName(), searchBean.getMiddleName(), + searchBean.getLastName(), childSearchEntity.getLimit()); + } + + //Process mothers search via mother demographics + + ClientSearchBean motherSearchBean = new ClientSearchBean(); + List mothers = new ArrayList(); + + if (motherSearchEntity.isValid()) { + motherSearchBean = motherSearchEntity.getClientSearchBean(); + mothers = searchService.searchClient(motherSearchBean, motherSearchBean.getFirstName(), + motherSearchBean.getMiddleName(), motherSearchBean.getLastName(), motherSearchEntity.getLimit()); + } + + //Process clients search via contact phone number + + + List clientBaseEntityIds = getClientBaseEntityIdsByContactPhoneNumber(contactPhoneNumber); + + List eventChildren = clientService.findByFieldValue(BaseEntity.BASE_ENTITY_ID, clientBaseEntityIds); + + children = SearchHelper.intersection(children, eventChildren);// Search conjunction is "AND" find intersection + + List linkedMothers = new ArrayList(); + + String RELATIONSHIP_KEY = "mother"; + if (!children.isEmpty()) { + List clientIds = new ArrayList(); + for (Client c : children) { + String relationshipId = SearchHelper.getRelationalId(c, RELATIONSHIP_KEY); + if (relationshipId != null && !clientIds.contains(relationshipId)) { + clientIds.add(relationshipId); + } + } + + linkedMothers = clientService.findByFieldValue(BaseEntity.BASE_ENTITY_ID, clientIds); + + } + + List linkedChildren = new ArrayList(); + + if (!mothers.isEmpty()) { + for (Client client : mothers) { + linkedChildren.addAll(clientService.findByRelationship(client.getBaseEntityId())); + } + } + + children = SearchHelper.intersection(children, linkedChildren);// Search conjunction is "AND" find intersection + + for (Client linkedMother : linkedMothers) { + if (!SearchHelper.contains(mothers, linkedMother)) { + mothers.add(linkedMother); + } + } + + return SearchHelper.processSearchResult(children, mothers, RELATIONSHIP_KEY); + + } catch (Exception e) { + + logger.error("", e); + return new ArrayList(); + } + } + + public List getClientBaseEntityIdsByContactPhoneNumber(String motherGuardianPhoneNumber) { + List clientBaseEntityIds = new ArrayList(); + + if (!StringUtils.isBlank(motherGuardianPhoneNumber)) { + + List events = eventService.findEventsByConceptAndValue("159635AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + motherGuardianPhoneNumber); + if (events != null && !events.isEmpty()) { + for (Event event : events) { + String entityId = event.getBaseEntityId(); + if (entityId != null && !clientBaseEntityIds.contains(entityId)) { + clientBaseEntityIds.add(entityId); + } + } + + } + } + return clientBaseEntityIds; + } + + @Override + public List filter(String query) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Client getByUniqueId(String uniqueId) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List requiredProperties() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Client create(Client entity) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Client update(Client entity) { + // TODO Auto-generated method stub + return null; + } + } diff --git a/src/main/java/org/opensrp/web/utils/SearchHelper.java b/src/main/java/org/opensrp/web/utils/SearchHelper.java index bf111db4f..d34930572 100644 --- a/src/main/java/org/opensrp/web/utils/SearchHelper.java +++ b/src/main/java/org/opensrp/web/utils/SearchHelper.java @@ -2,6 +2,7 @@ import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; +import org.json.JSONObject; import org.opensrp.search.ClientSearchBean; import org.opensrp.web.rest.RestUtils; import org.smartregister.domain.Client; @@ -18,289 +19,406 @@ public class SearchHelper { - public static SearchEntityWrapper childSearchParamProcessor(HttpServletRequest request) throws ParseException { + public static final String ZEIR_ID = "zeir_id"; + public static final String OPENSRP_ID = "opensrp_id"; - ClientSearchBean searchBean = new ClientSearchBean(); + public static final String SIM_PRINT_GUID = "simprints_guid"; - String ZEIR_ID = "zeir_id"; - String OPENSRP_ID = "opensrp_id"; + public static final String FIRST_NAME = "first_name"; + public static final String MIDDLE_NAME = "middle_name"; + public static final String LAST_NAME = "last_name"; + public static final String BIRTH_DATE = "birth_date"; - String SIM_PRINT_GUID = "simprints_guid"; + //Attributes + public static final String INACTIVE = "inactive"; + public static final String LOST_TO_FOLLOW_UP = "lost_to_follow_up"; + public static final String NFC_CARD_IDENTIFIER = "nfc_card_identifier"; - String FIRST_NAME = "first_name"; - String MIDDLE_NAME = "middle_name"; - String LAST_NAME = "last_name"; - String BIRTH_DATE = "birth_date"; + // Mother + public static final String MOTHER_GUARDIAN_FIRST_NAME = "mother_first_name"; + public static final String MOTHER_GUARDIAN_LAST_NAME = "mother_last_name"; + public static final String MOTHER_GUARDIAN_NRC_NUMBER = "mother_nrc_number"; + public static final String MOTHER_COMPASS_RELATIONSHIP_ID = "mother_compass_relationship_id"; - //Attributes - String INACTIVE = "inactive"; - String LOST_TO_FOLLOW_UP = "lost_to_follow_up"; - String NFC_CARD_IDENTIFIER = "nfc_card_identifier"; + public static final String NRC_NUMBER_KEY = "NRC_Number"; + public static final String COMPASS_RELATIONSHIP_ID = "Compass_Relationship_ID"; - Integer limit = RestUtils.getIntegerFilter("limit", request); - if (limit == null || limit.intValue() == 0) { - limit = 100; - } + public static SearchEntityWrapper childSearchParamProcessor(HttpServletRequest request) throws ParseException { - DateTime[] lastEdit = RestUtils.getDateRangeFilter(LAST_UPDATE, request);//TODO client by provider id - if (lastEdit != null) { - searchBean.setLastEditFrom(lastEdit[0]); - searchBean.setLastEditTo(lastEdit[1]); - } + ClientSearchBean searchBean = new ClientSearchBean(); - String zeirId = RestUtils.getStringFilter(ZEIR_ID, request); - String opensrpId = RestUtils.getStringFilter(OPENSRP_ID, request); - String simprintsGuid = RestUtils.getStringFilter(SIM_PRINT_GUID, request); - searchBean.setFirstName(RestUtils.getStringFilter(FIRST_NAME, request)); - searchBean.setMiddleName(RestUtils.getStringFilter(MIDDLE_NAME, request)); - searchBean.setLastName(RestUtils.getStringFilter(LAST_NAME, request)); - searchBean.setGender(RestUtils.getStringFilter(GENDER, request)); + Integer limit = RestUtils.getIntegerFilter("limit", request); + if (limit == null || limit.intValue() == 0) { + limit = 100; + } - String inActive = RestUtils.getStringFilter(INACTIVE, request); - String lostToFollowUp = RestUtils.getStringFilter(LOST_TO_FOLLOW_UP, request); - String nfcCardIdentifier = RestUtils.getStringFilter(NFC_CARD_IDENTIFIER, request); + DateTime[] lastEdit = RestUtils.getDateRangeFilter(LAST_UPDATE, request);//TODO client by provider id + if (lastEdit != null) { + searchBean.setLastEditFrom(lastEdit[0]); + searchBean.setLastEditTo(lastEdit[1]); + } - DateTime[] birthdate = RestUtils - .getDateRangeFilter(BIRTH_DATE, request);//TODO add ranges like fhir do http://hl7.org/fhir/search.html + searchBean.setFirstName(RestUtils.getStringFilter(FIRST_NAME, request)); + searchBean.setMiddleName(RestUtils.getStringFilter(MIDDLE_NAME, request)); + searchBean.setLastName(RestUtils.getStringFilter(LAST_NAME, request)); + searchBean.setGender(RestUtils.getStringFilter(GENDER, request)); - //TODO lookinto Swagger https://slack-files.com/files-pri-safe/T0EPSEJE9-F0TBD0N77/integratingswagger.pdf?c=1458211183-179d2bfd2e974585c5038fba15a86bf83097810a + DateTime[] birthdate = RestUtils + .getDateRangeFilter(BIRTH_DATE, request);//TODO add ranges like fhir do http://hl7.org/fhir/search.html - if (birthdate != null) { - searchBean.setBirthdateFrom(birthdate[0]); - searchBean.setBirthdateTo(birthdate[1]); - } - Map identifiers = new HashMap(); - // - if (!StringUtils.isBlank(zeirId)) { - identifiers.put(ZEIR_ID, zeirId); - identifiers.put("ZEIR_ID", zeirId); //Maintains backward compatibility with upper case key - } + //TODO lookinto Swagger https://slack-files.com/files-pri-safe/T0EPSEJE9-F0TBD0N77/integratingswagger.pdf?c=1458211183-179d2bfd2e974585c5038fba15a86bf83097810a - if (!StringUtils.isBlank(opensrpId)) { - identifiers.put(OPENSRP_ID, opensrpId); - } - if (!StringUtils.isBlank(simprintsGuid)) { - identifiers.put(SIM_PRINT_GUID, simprintsGuid); - } + if (birthdate != null) { + searchBean.setBirthdateFrom(birthdate[0]); + searchBean.setBirthdateTo(birthdate[1]); + } - Map attributes = new HashMap(); - if (!StringUtils.isBlank(inActive) || !StringUtils.isBlank(lostToFollowUp) - || !StringUtils.isBlank(nfcCardIdentifier)) { - if (!StringUtils.isBlank(inActive)) { - attributes.put(INACTIVE, inActive); - } + Map commonSearchParams = new HashMap<>(); + commonSearchParams.put(ZEIR_ID, RestUtils.getStringFilter(ZEIR_ID, request)); + commonSearchParams.put(OPENSRP_ID, RestUtils.getStringFilter(OPENSRP_ID, request)); + commonSearchParams.put(SIM_PRINT_GUID, RestUtils.getStringFilter(SIM_PRINT_GUID, request)); + commonSearchParams.put(INACTIVE, RestUtils.getStringFilter(INACTIVE, request)); + commonSearchParams.put(LOST_TO_FOLLOW_UP, RestUtils.getStringFilter(LOST_TO_FOLLOW_UP, request)); + commonSearchParams.put(NFC_CARD_IDENTIFIER, RestUtils.getStringFilter(NFC_CARD_IDENTIFIER, request)); - if (!StringUtils.isBlank(lostToFollowUp)) { - attributes.put(LOST_TO_FOLLOW_UP, lostToFollowUp); - } + setIdentifiersAndAttributeToChildSearchBean(commonSearchParams, searchBean); - if (!StringUtils.isBlank(nfcCardIdentifier)) { - attributes.put("NFC_Card_Identifier", nfcCardIdentifier);//Key different case than constant - } - } - - searchBean.setIdentifiers(identifiers); - searchBean.setAttributes(attributes); - - boolean isValid = isSearchValid(searchBean); - - return new SearchEntityWrapper(isValid, searchBean, limit); - } - - public static SearchEntityWrapper motherSearchParamProcessor(HttpServletRequest request) throws ParseException { + boolean isValid = isSearchValid(searchBean); - ClientSearchBean motherSearchBean = new ClientSearchBean(); - - Integer limit = setCoreFilters(request, motherSearchBean); + return new SearchEntityWrapper(isValid, searchBean, limit); + } - // Mother - String MOTHER_GUARDIAN_FIRST_NAME = "mother_first_name"; - String MOTHER_GUARDIAN_LAST_NAME = "mother_last_name"; - String MOTHER_GUARDIAN_NRC_NUMBER = "mother_nrc_number"; - String MOTHER_COMPASS_RELATIONSHIP_ID = "mother_compass_relationship_id"; - - String motherGuardianNrc = RestUtils.getStringFilter(MOTHER_GUARDIAN_NRC_NUMBER, request); - String compassRelationshipId = RestUtils.getStringFilter(MOTHER_COMPASS_RELATIONSHIP_ID, request); - - motherSearchBean.setFirstName(RestUtils.getStringFilter(MOTHER_GUARDIAN_FIRST_NAME, request)); - motherSearchBean.setLastName(RestUtils.getStringFilter(MOTHER_GUARDIAN_LAST_NAME, request)); - - String NRC_NUMBER_KEY = "NRC_Number"; - String COMPASS_RELATIONSHIP_ID = "Compass_Relationship_ID"; - - Map motherAttributes = new HashMap<>(); - if (!StringUtils.isBlank(motherGuardianNrc)) { - motherAttributes.put(NRC_NUMBER_KEY, motherGuardianNrc); - } - if (!StringUtils.isBlank(compassRelationshipId)) { - motherAttributes.put(COMPASS_RELATIONSHIP_ID, compassRelationshipId); - } - - String nameLike = null; - - if (!StringUtils.isBlank(motherSearchBean.getFirstName()) - && StringUtils.containsWhitespace(motherSearchBean.getFirstName().trim()) - && StringUtils.isBlank(motherSearchBean.getLastName())) { - String[] arr = motherSearchBean.getFirstName().split("\\s+"); - nameLike = arr[0]; - motherSearchBean.setFirstName(null); - } - - motherSearchBean.setNameLike(nameLike); - motherSearchBean.setAttributes(motherAttributes); - - boolean isValid = isSearchValid(motherSearchBean); - - return new SearchEntityWrapper(isValid, motherSearchBean, limit); - } + public static SearchEntityWrapper motherSearchParamProcessor(HttpServletRequest request) throws ParseException { - public static Integer setCoreFilters(HttpServletRequest request, ClientSearchBean searchBean) throws ParseException { - - Integer limit = RestUtils.getIntegerFilter("limit", request); - if (limit == null || limit.intValue() == 0) { - limit = 100; - } - - DateTime[] lastEdit = RestUtils.getDateRangeFilter(LAST_UPDATE, request);//TODO client by provider id - if (lastEdit != null) { - searchBean.setLastEditFrom(lastEdit[0]); - searchBean.setLastEditTo(lastEdit[1]); - } - - return limit; - } - - /** - * Here we check to see if the search entity param is valid for use in child search Some form of - * reflections and custom annotations might have been better - * - * @param searchBean model with search params - * @return boolean whether the search entity is valid - */ - - public static boolean isSearchValid(ClientSearchBean searchBean) { - - return !StringUtils.isBlank(searchBean.getFirstName()) - || !StringUtils.isBlank(searchBean.getMiddleName()) - || !StringUtils.isBlank(searchBean.getLastName()) - || !StringUtils.isBlank(searchBean.getGender()) - || (searchBean.getAttributes() != null && !searchBean.getAttributes().isEmpty()) - || searchBean.getBirthdateFrom() != null || searchBean.getBirthdateTo() != null - || searchBean.getLastEditFrom() != null || searchBean.getLastEditTo() != null - || (searchBean.getIdentifiers() != null && !searchBean.getIdentifiers().isEmpty()) - || !StringUtils.isBlank(searchBean.getNameLike()); - - } - - /** - * // Method returns the intersection of two lists - * - * @param list1_ - * @param list2_ - * @return merged intersection list - */ - public static List intersection(List list1_, List list2_) { - - List list1 = list1_; - List list2 = list2_; - - list1 = createClientListIfEmpty(list1); - - list2 = createClientListIfEmpty(list2); - - if (list1.isEmpty() && list2.isEmpty()) { - return new ArrayList(); - } - - if (list1.isEmpty() && !list2.isEmpty()) { - return list2; - } - - if (list2.isEmpty() && !list1.isEmpty()) { - return list1; - } - - List list = new ArrayList(); - - for (Client t : list1) { - if (contains(list2, t)) { - list.add(t); - } - } - - return list; - } - - public static List createClientListIfEmpty(List list_) { - List list = list_; - - if (list == null) { - list = new ArrayList(); - } - - return list; - } - - public static boolean contains(List clients, Client c) { - if (clients == null || clients.isEmpty() || c == null || c.getBaseEntityId() == null) { - return false; - } - for (Client client : clients) { - - if (client != null && client.getBaseEntityId() != null - && c.getBaseEntityId().equals(client.getBaseEntityId())) { - - return true; - - } - } - return false; - } - - public static String getContactPhoneNumberParam(HttpServletRequest request) { - //Search by mother contact number - String MOTHER_GUARDIAN_PHONE_NUMBER = "mother_contact_phone_number"; - String CONTACT_PHONE_NUMBER = "contact_phone_number"; - String motherGuardianPhoneNumber = RestUtils.getStringFilter(MOTHER_GUARDIAN_PHONE_NUMBER, request); - motherGuardianPhoneNumber = StringUtils.isBlank(motherGuardianPhoneNumber) - ? RestUtils.getStringFilter(CONTACT_PHONE_NUMBER, request) - : motherGuardianPhoneNumber; - - return motherGuardianPhoneNumber; - } - - public static List processSearchResult(List children, List mothers, - String RELATIONSHIP_KEY) { - List childMotherList = new ArrayList(); - for (Client child : children) { - for (Client mother : mothers) { - String relationalId = getRelationalId(child, RELATIONSHIP_KEY); - String motherEntityId = mother.getBaseEntityId(); - if (relationalId != null && relationalId.equalsIgnoreCase(motherEntityId)) { - childMotherList.add(new ChildMother(child, mother)); - } - } - } - - return childMotherList; - } - - public static String getRelationalId(Client c, String relationshipKey) { - Map> relationships = c.getRelationships(); - if (relationships != null) { - for (Map.Entry> entry : relationships.entrySet()) { - String key = entry.getKey(); - if (key.equalsIgnoreCase(relationshipKey)) { - List rList = entry.getValue(); - if (!rList.isEmpty()) { - return rList.get(0); - } - } - } - } - - return null; - } + ClientSearchBean motherSearchBean = new ClientSearchBean(); + + Integer limit = setCoreFilters(request, motherSearchBean); + + + String motherGuardianNrc = RestUtils.getStringFilter(MOTHER_GUARDIAN_NRC_NUMBER, request); + String compassRelationshipId = RestUtils.getStringFilter(MOTHER_COMPASS_RELATIONSHIP_ID, request); + + motherSearchBean.setFirstName(RestUtils.getStringFilter(MOTHER_GUARDIAN_FIRST_NAME, request)); + motherSearchBean.setLastName(RestUtils.getStringFilter(MOTHER_GUARDIAN_LAST_NAME, request)); + + setNameLikeAndAtrributesOnMotherSearchBean(motherGuardianNrc, compassRelationshipId, motherSearchBean); + + boolean isValid = isSearchValid(motherSearchBean); + + return new SearchEntityWrapper(isValid, motherSearchBean, limit); + } + + public static SearchEntityWrapper childSearchParamProcessor(JSONObject jsonObject) throws ParseException { + + ClientSearchBean searchBean = new ClientSearchBean(); + + Integer limit = !jsonObject.optString("limit").equals("") ? Integer.parseInt(jsonObject.optString("limit")) + : jsonObject.optInt("limit"); + if (limit == 0) { + limit = 100; + } + + DateTime[] lastEdit = RestUtils.getDateRangeFilter(LAST_UPDATE, jsonObject);//TODO client by provider id + if (lastEdit != null) { + searchBean.setLastEditFrom(lastEdit[0]); + searchBean.setLastEditTo(lastEdit[1]); + } + + searchBean.setFirstName(jsonObject.optString(FIRST_NAME)); + searchBean.setMiddleName(jsonObject.optString(MIDDLE_NAME)); + searchBean.setLastName(jsonObject.optString(LAST_NAME)); + searchBean.setGender(jsonObject.optString(GENDER)); + + DateTime[] birthdate = RestUtils + .getDateRangeFilter(BIRTH_DATE, jsonObject);//TODO add ranges like fhir do http://hl7.org/fhir/search.html + + //TODO lookinto Swagger https://slack-files.com/files-pri-safe/T0EPSEJE9-F0TBD0N77/integratingswagger.pdf?c=1458211183-179d2bfd2e974585c5038fba15a86bf83097810a + + if (birthdate != null) { + searchBean.setBirthdateFrom(birthdate[0]); + searchBean.setBirthdateTo(birthdate[1]); + } + + Map commonSearchParams = new HashMap<>(); + commonSearchParams.put(ZEIR_ID, jsonObject.optString(ZEIR_ID)); + commonSearchParams.put(OPENSRP_ID, jsonObject.optString(OPENSRP_ID)); + commonSearchParams.put(SIM_PRINT_GUID, jsonObject.optString(SIM_PRINT_GUID)); + commonSearchParams.put(INACTIVE, jsonObject.optString(INACTIVE)); + commonSearchParams.put(LOST_TO_FOLLOW_UP, jsonObject.optString(LOST_TO_FOLLOW_UP)); + commonSearchParams.put(NFC_CARD_IDENTIFIER, jsonObject.optString(NFC_CARD_IDENTIFIER)); + + setIdentifiersAndAttributeToChildSearchBean(commonSearchParams, searchBean); + + boolean isValid = isSearchValid(searchBean); + + return new SearchEntityWrapper(isValid, searchBean, limit); + } + + public static SearchEntityWrapper motherSearchParamProcessor(JSONObject jsonObject) throws ParseException { + + ClientSearchBean motherSearchBean = new ClientSearchBean(); + + Integer limit = setCoreFilters(jsonObject, motherSearchBean); + + String motherGuardianNrc = jsonObject.optString(MOTHER_GUARDIAN_NRC_NUMBER); + String compassRelationshipId = jsonObject.optString(MOTHER_COMPASS_RELATIONSHIP_ID); + + motherSearchBean.setFirstName(jsonObject.optString(MOTHER_GUARDIAN_FIRST_NAME)); + motherSearchBean.setLastName(jsonObject.optString(MOTHER_GUARDIAN_LAST_NAME)); + + setNameLikeAndAtrributesOnMotherSearchBean(motherGuardianNrc, compassRelationshipId, motherSearchBean); + + boolean isValid = isSearchValid(motherSearchBean); + + return new SearchEntityWrapper(isValid, motherSearchBean, limit); + } + + public static void setNameLikeAndAtrributesOnMotherSearchBean(String motherGuardianNrc, + String compassRelationshipId, + ClientSearchBean motherSearchBean) { + Map motherAttributes = new HashMap<>(); + if (!StringUtils.isBlank(motherGuardianNrc)) { + motherAttributes.put(NRC_NUMBER_KEY, motherGuardianNrc); + } + if (!StringUtils.isBlank(compassRelationshipId)) { + motherAttributes.put(COMPASS_RELATIONSHIP_ID, compassRelationshipId); + } + + String nameLike = null; + + if (!StringUtils.isBlank(motherSearchBean.getFirstName()) + && StringUtils.containsWhitespace(motherSearchBean.getFirstName().trim()) + && StringUtils.isBlank(motherSearchBean.getLastName())) { + String[] arr = motherSearchBean.getFirstName().split("\\s+"); + nameLike = arr[0]; + motherSearchBean.setFirstName(null); + } + + motherSearchBean.setNameLike(nameLike); + motherSearchBean.setAttributes(motherAttributes); + + } + + public static void setIdentifiersAndAttributeToChildSearchBean(Map commonSearchParams, ClientSearchBean searchBean) { + Map identifiers = new HashMap(); + + String zeirId = commonSearchParams.get(ZEIR_ID); + String opensrpId = commonSearchParams.get(OPENSRP_ID); + String simprintsGuid = commonSearchParams.get(SIM_PRINT_GUID); + String lostToFollowUp = commonSearchParams.get(LOST_TO_FOLLOW_UP); + String inActive = commonSearchParams.get(INACTIVE); + String nfcCardIdentifier = commonSearchParams.get(NFC_CARD_IDENTIFIER); + + if (!StringUtils.isBlank(zeirId)) { + identifiers.put(ZEIR_ID, zeirId); + identifiers.put("ZEIR_ID", zeirId); //Maintains backward compatibility with upper case key + } + + if (!StringUtils.isBlank(opensrpId)) { + identifiers.put(OPENSRP_ID, opensrpId); + } + if (!StringUtils.isBlank(simprintsGuid)) { + identifiers.put(SIM_PRINT_GUID, simprintsGuid); + } + + Map attributes = new HashMap(); + if (!StringUtils.isBlank(inActive) || !StringUtils.isBlank(lostToFollowUp) + || !StringUtils.isBlank(nfcCardIdentifier)) { + + if (!StringUtils.isBlank(inActive)) { + attributes.put(INACTIVE, inActive); + } + + if (!StringUtils.isBlank(lostToFollowUp)) { + attributes.put(LOST_TO_FOLLOW_UP, lostToFollowUp); + } + + if (!StringUtils.isBlank(nfcCardIdentifier)) { + attributes.put("NFC_Card_Identifier", nfcCardIdentifier);//Key different case than constant + } + } + + searchBean.setIdentifiers(identifiers); + searchBean.setAttributes(attributes); + + } + + public static Integer setCoreFilters(HttpServletRequest request, ClientSearchBean searchBean) throws ParseException { + + Integer limit = RestUtils.getIntegerFilter("limit", request); + if (limit == null || limit.intValue() == 0) { + limit = 100; + } + + DateTime[] lastEdit = RestUtils.getDateRangeFilter(LAST_UPDATE, request);//TODO client by provider id + if (lastEdit != null) { + searchBean.setLastEditFrom(lastEdit[0]); + searchBean.setLastEditTo(lastEdit[1]); + } + + return limit; + } + + public static Integer setCoreFilters(JSONObject jsonObject, ClientSearchBean searchBean) throws ParseException { + + Integer limit = !jsonObject.optString("limit").equals("") ? Integer.parseInt(jsonObject.optString("limit")) + : jsonObject.optInt("limit"); + if (limit == 0) { + limit = 100; + } + + DateTime[] lastEdit = RestUtils.getDateRangeFilter(LAST_UPDATE, jsonObject);//TODO client by provider id + if (lastEdit != null) { + searchBean.setLastEditFrom(lastEdit[0]); + searchBean.setLastEditTo(lastEdit[1]); + } + + return limit; + } + + /** + * Here we check to see if the search entity param is valid for use in child search Some form of + * reflections and custom annotations might have been better + * + * @param searchBean model with search params + * @return boolean whether the search entity is valid + */ + + public static boolean isSearchValid(ClientSearchBean searchBean) { + + return !StringUtils.isBlank(searchBean.getFirstName()) + || !StringUtils.isBlank(searchBean.getMiddleName()) + || !StringUtils.isBlank(searchBean.getLastName()) + || !StringUtils.isBlank(searchBean.getGender()) + || (searchBean.getAttributes() != null && !searchBean.getAttributes().isEmpty()) + || searchBean.getBirthdateFrom() != null || searchBean.getBirthdateTo() != null + || searchBean.getLastEditFrom() != null || searchBean.getLastEditTo() != null + || (searchBean.getIdentifiers() != null && !searchBean.getIdentifiers().isEmpty()) + || !StringUtils.isBlank(searchBean.getNameLike()); + + } + + /** + * // Method returns the intersection of two lists + * + * @param list1_ + * @param list2_ + * @return merged intersection list + */ + public static List intersection(List list1_, List list2_) { + + List list1 = list1_; + List list2 = list2_; + + list1 = createClientListIfEmpty(list1); + + list2 = createClientListIfEmpty(list2); + + if (list1.isEmpty() && list2.isEmpty()) { + return new ArrayList(); + } + + if (list1.isEmpty() && !list2.isEmpty()) { + return list2; + } + + if (list2.isEmpty() && !list1.isEmpty()) { + return list1; + } + + List list = new ArrayList(); + + for (Client t : list1) { + if (contains(list2, t)) { + list.add(t); + } + } + + return list; + } + + public static List createClientListIfEmpty(List list_) { + List list = list_; + + if (list == null) { + list = new ArrayList(); + } + + return list; + } + + public static boolean contains(List clients, Client c) { + if (clients == null || clients.isEmpty() || c == null || c.getBaseEntityId() == null) { + return false; + } + for (Client client : clients) { + + if (client != null && client.getBaseEntityId() != null + && c.getBaseEntityId().equals(client.getBaseEntityId())) { + + return true; + + } + } + return false; + } + + public static String getContactPhoneNumberParam(HttpServletRequest request) { + //Search by mother contact number + String MOTHER_GUARDIAN_PHONE_NUMBER = "mother_contact_phone_number"; + String CONTACT_PHONE_NUMBER = "contact_phone_number"; + String motherGuardianPhoneNumber = RestUtils.getStringFilter(MOTHER_GUARDIAN_PHONE_NUMBER, request); + motherGuardianPhoneNumber = StringUtils.isBlank(motherGuardianPhoneNumber) + ? RestUtils.getStringFilter(CONTACT_PHONE_NUMBER, request) + : motherGuardianPhoneNumber; + + return motherGuardianPhoneNumber; + } + + public static String getContactPhoneNumberParam(JSONObject jsonObject) { + //Search by mother contact number + String MOTHER_GUARDIAN_PHONE_NUMBER = "mother_contact_phone_number"; + String CONTACT_PHONE_NUMBER = "contact_phone_number"; + String motherGuardianPhoneNumber = jsonObject.optString(MOTHER_GUARDIAN_PHONE_NUMBER); + motherGuardianPhoneNumber = StringUtils.isBlank(motherGuardianPhoneNumber) + ? jsonObject.optString(CONTACT_PHONE_NUMBER) + : motherGuardianPhoneNumber; + + return motherGuardianPhoneNumber; + } + + public static List processSearchResult(List children, List mothers, + String RELATIONSHIP_KEY) { + List childMotherList = new ArrayList(); + for (Client child : children) { + for (Client mother : mothers) { + String relationalId = getRelationalId(child, RELATIONSHIP_KEY); + String motherEntityId = mother.getBaseEntityId(); + if (relationalId != null && relationalId.equalsIgnoreCase(motherEntityId)) { + childMotherList.add(new ChildMother(child, mother)); + } + } + } + + return childMotherList; + } + + public static String getRelationalId(Client c, String relationshipKey) { + Map> relationships = c.getRelationships(); + if (relationships != null) { + for (Map.Entry> entry : relationships.entrySet()) { + String key = entry.getKey(); + if (key.equalsIgnoreCase(relationshipKey)) { + List rList = entry.getValue(); + if (!rList.isEmpty()) { + return rList.get(0); + } + } + } + } + + return null; + } } diff --git a/src/test/java/org/opensrp/web/rest/SearchResourceTest.java b/src/test/java/org/opensrp/web/rest/SearchResourceTest.java index c9dfe147d..493dc874b 100755 --- a/src/test/java/org/opensrp/web/rest/SearchResourceTest.java +++ b/src/test/java/org/opensrp/web/rest/SearchResourceTest.java @@ -8,14 +8,18 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; +import org.opensrp.repository.PlanRepository; +import org.opensrp.service.ClientService; +import org.opensrp.service.EventService; +import org.opensrp.service.ExportEventDataMapper; +import org.opensrp.service.SearchService; +import org.opensrp.service.TaskGenerator; +import org.smartregister.domain.Client; import org.opensrp.repository.ClientsRepository; import org.opensrp.repository.EventsRepository; -import org.opensrp.repository.PlanRepository; import org.opensrp.repository.SearchRepository; -import org.opensrp.service.*; import org.opensrp.web.rest.it.TestWebContextLoader; import org.opensrp.web.utils.SearchHelper; -import org.smartregister.domain.Client; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.test.context.ContextConfiguration; @@ -27,77 +31,85 @@ import java.util.List; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(loader = TestWebContextLoader.class, locations = { "classpath:test-webmvc-config.xml", }) +@ContextConfiguration(loader = TestWebContextLoader.class, locations = {"classpath:test-webmvc-config.xml",}) public class SearchResourceTest { - - @Autowired - protected WebApplicationContext webApplicationContext; - - private SearchService searchService; - - private ClientService clientService; - - private EventService eventService; - - private ExportEventDataMapper exportEventDataMapper; - - - private TaskGenerator taskGenerator; - - private PlanRepository planRepository; - MockHttpServletRequest mockHttpServletRequest; - String phoneNumber = "0727000000"; - String town = "town"; - - String firstName = "name"; - - String male = "male"; - - DateTime birthDate = new DateTime(0l, DateTimeZone.UTC); - - @Before - public void setUp() { - SearchRepository searchRepository = Mockito.mock(SearchRepository.class); - ClientsRepository clientRepository = Mockito.mock(ClientsRepository.class); - EventsRepository eventsRepository = Mockito.mock(EventsRepository.class); - - searchService = Mockito.spy(new SearchService(searchRepository)); - clientService = Mockito.spy(new ClientService(clientRepository)); - eventService = Mockito.spy(new EventService(eventsRepository, clientService,taskGenerator,planRepository, exportEventDataMapper)); - - } - - @Test - public void testInstantanceCreatesCorrectly() { - - SearchResource searchResource = new SearchResource(searchService, clientService, eventService); - Assert.assertNotNull(searchResource); - - } - - @Test - public void testIntersectionMethodReturnsCorrectResult() throws Exception { - - Client clientA = Mockito.mock(Client.class); - List listA = Arrays.asList(new Client[] { clientA }); - List result = SearchHelper.intersection(null, listA); - - Assert.assertNotNull(result); - Assert.assertEquals(listA, result); - - } - @Test - public void shouldSearchClient() throws ParseException { - mockHttpServletRequest = new MockHttpServletRequest(); - mockHttpServletRequest.addParameter("ff", "ona"); - mockHttpServletRequest.addParameter("phone_number", phoneNumber); - mockHttpServletRequest.addParameter("alt_phone_number", phoneNumber); - mockHttpServletRequest.addParameter("alt_name", firstName); - mockHttpServletRequest.addParameter("attribute", "next_contact_date:2022-06-15"); - mockHttpServletRequest.addParameter("dob", String.valueOf(birthDate)); - mockHttpServletRequest.addParameter("identifier", "fsdf"+":"+ "sfdf"); - SearchResource searchResource=new SearchResource(searchService,clientService,eventService); - List clients = searchResource.search(mockHttpServletRequest); - Assert.assertNotNull(clients); - } + + @Autowired + protected WebApplicationContext webApplicationContext; + + private SearchService searchService; + + private ClientService clientService; + + private EventService eventService; + + private ExportEventDataMapper exportEventDataMapper; + + + private TaskGenerator taskGenerator; + + private PlanRepository planRepository; + + MockHttpServletRequest mockHttpServletRequest; + String phoneNumber = "0727000000"; + String firstName = "name"; + DateTime birthDate = new DateTime(0l, DateTimeZone.UTC); + + @Before + public void setUp() { + SearchRepository searchRepository = Mockito.mock(SearchRepository.class); + ClientsRepository clientRepository = Mockito.mock(ClientsRepository.class); + EventsRepository eventsRepository = Mockito.mock(EventsRepository.class); + + searchService = Mockito.spy(new SearchService(searchRepository)); + clientService = Mockito.spy(new ClientService(clientRepository)); + eventService = Mockito.spy(new EventService(eventsRepository, clientService, taskGenerator, planRepository, exportEventDataMapper)); + + } + + @Test + public void testInstantanceCreatesCorrectly() { + + SearchResource searchResource = new SearchResource(searchService, clientService, eventService); + Assert.assertNotNull(searchResource); + + } + + @Test + public void testIntersectionMethodReturnsCorrectResult() throws Exception { + + Client clientA = Mockito.mock(Client.class); + List listA = Arrays.asList(new Client[]{clientA}); + List result = SearchHelper.intersection(null, listA); + + Assert.assertNotNull(result); + Assert.assertEquals(listA, result); + + } + + @Test + public void shouldSearchClientWithGetRequest() throws ParseException { + mockHttpServletRequest = new MockHttpServletRequest(); + mockHttpServletRequest.addParameter("ff", "ona"); + mockHttpServletRequest.addParameter("phone_number", phoneNumber); + mockHttpServletRequest.addParameter("alt_phone_number", phoneNumber); + mockHttpServletRequest.addParameter("alt_name", firstName); + mockHttpServletRequest.addParameter("attribute", "next_contact_date:2022-06-15"); + mockHttpServletRequest.addParameter("dob", String.valueOf(birthDate)); + mockHttpServletRequest.addParameter("identifier", "fsdf" + ":" + "sfdf"); + SearchResource searchResource = new SearchResource(searchService, clientService, eventService); + List clients = searchResource.search(mockHttpServletRequest); + Assert.assertNotNull(clients); + } + + @Test + public void shouldSearchClientWithPostRequest() throws ParseException { + String jsonRequestString = "{\"ff\":\"ona\",\"identifier\":\"fsdf:sfdf\",\"alt_name\":\"name\"," + + "\"alt_phone_number\":\"0727000000\",\"dob\":\"1970-01-01T00:00:00.000Z\",\"phone_number\":\"0727000000\"," + + "\"attribute\":\"next_contact_date:2022-06-15\"}"; + SearchResource searchResource = new SearchResource(searchService, clientService, eventService); + List clients = searchResource.searchByPost(jsonRequestString); + Assert.assertNotNull(clients); + + } } diff --git a/src/test/java/org/opensrp/web/utils/SearchHelperTest.java b/src/test/java/org/opensrp/web/utils/SearchHelperTest.java index d43337dc8..523c6538a 100644 --- a/src/test/java/org/opensrp/web/utils/SearchHelperTest.java +++ b/src/test/java/org/opensrp/web/utils/SearchHelperTest.java @@ -1,9 +1,11 @@ package org.opensrp.web.utils; +import org.json.JSONObject; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import org.opensrp.common.util.EasyMap; +import org.opensrp.search.ClientSearchBean; import org.smartregister.domain.Client; import org.springframework.mock.web.MockHttpServletRequest; @@ -250,7 +252,7 @@ public void testProcessSearchResult() { } @Test - public void testMotherSearchParamProcessor() throws ParseException { + public void testMotherSearchParamProcessorForHttpServletRequest() throws ParseException { HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class); Mockito.when(httpServletRequest.getParameter("limit")).thenReturn("0"); Mockito.when(httpServletRequest.getParameter("mother_first_name")).thenReturn("Jane"); @@ -266,4 +268,110 @@ public void testMotherSearchParamProcessor() throws ParseException { Assert.assertEquals("2093980", result.get("NRC_Number")); } + @Test + public void testMotherSearchParamProcessorForJSONObject() throws ParseException { + JSONObject jsonObject = Mockito.mock(JSONObject.class); + Mockito.when(jsonObject.optString("limit")).thenReturn("0"); + Mockito.when(jsonObject.optString("mother_first_name")).thenReturn("Jane"); + Mockito.when(jsonObject.optString("mother_last_name")).thenReturn("Doe"); + Mockito.when(jsonObject.optString("mother_nrc_number")).thenReturn("2093980"); + Mockito.when(jsonObject.optString("NRC_Number")).thenReturn("20939801123"); + Mockito.when(jsonObject.optString("mother_compass_relationship_id")).thenReturn("dab102f71bd"); + Mockito.when(jsonObject.optString("lastEdited")).thenReturn(""); + SearchEntityWrapper searchEntityWrapper = SearchHelper.motherSearchParamProcessor(jsonObject); + Map result = searchEntityWrapper.getClientSearchBean().getAttributes(); + Assert.assertEquals(2, result.size()); + Assert.assertTrue( result.containsKey("NRC_Number")); + Assert.assertTrue( result.containsKey("Compass_Relationship_ID")); + Assert.assertEquals("2093980", result.get("NRC_Number")); + } + + @Test + public void testChildSearchParamProcessorForJSONObject() throws ParseException { + JSONObject jsonObject = Mockito.mock(JSONObject.class); + Mockito.when(jsonObject.optString("limit")).thenReturn("50"); + Mockito.when(jsonObject.optString("lastEdited")).thenReturn(""); + Mockito.when(jsonObject.optString(SearchHelper.BIRTH_DATE)).thenReturn(""); + Mockito.when(jsonObject.optString(SearchHelper.ZEIR_ID)).thenReturn("1234"); + Mockito.when(jsonObject.optString(SearchHelper.OPENSRP_ID)).thenReturn("4567"); + Mockito.when(jsonObject.optString(SearchHelper.SIM_PRINT_GUID)).thenReturn("91011"); + Mockito.when(jsonObject.optString(SearchHelper.INACTIVE)).thenReturn("false"); + Mockito.when(jsonObject.optString(SearchHelper.LOST_TO_FOLLOW_UP)).thenReturn("true"); + Mockito.when(jsonObject.optString(SearchHelper.NFC_CARD_IDENTIFIER)).thenReturn("nfc_card_identifier_1"); + SearchEntityWrapper searchEntityWrapper = SearchHelper.childSearchParamProcessor(jsonObject); + + Map attributes = searchEntityWrapper.getClientSearchBean().getAttributes(); + Assert.assertEquals(3, attributes.size()); + + Map identifiers = searchEntityWrapper.getClientSearchBean().getIdentifiers(); + Assert.assertEquals(4, identifiers.size()); + + Assert.assertTrue(identifiers.containsKey(SearchHelper.ZEIR_ID)); + Assert.assertTrue(identifiers.containsKey("ZEIR_ID")); //check backward compatibility with upper case key + Assert.assertTrue(identifiers.containsKey(SearchHelper.SIM_PRINT_GUID)); + + Assert.assertTrue(attributes.containsKey(SearchHelper.INACTIVE)); + Assert.assertTrue(attributes.containsKey(SearchHelper.LOST_TO_FOLLOW_UP)); + Assert.assertTrue(attributes.containsKey("NFC_Card_Identifier")); + + Assert.assertEquals(identifiers.get(SearchHelper.ZEIR_ID), "1234"); + Assert.assertEquals(attributes.get("NFC_Card_Identifier"), "nfc_card_identifier_1"); + } + + @Test + public void testChildSearchParamProcessorForHttpServletRequest() throws ParseException { + HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class); + Mockito.when(httpServletRequest.getParameter("limit")).thenReturn("50"); + Mockito.when(httpServletRequest.getParameter("lastEdited")).thenReturn(""); + Mockito.when(httpServletRequest.getParameter(SearchHelper.BIRTH_DATE)).thenReturn(""); + Mockito.when(httpServletRequest.getParameter(SearchHelper.ZEIR_ID)).thenReturn("1234"); + Mockito.when(httpServletRequest.getParameter(SearchHelper.OPENSRP_ID)).thenReturn("4567"); + Mockito.when(httpServletRequest.getParameter(SearchHelper.SIM_PRINT_GUID)).thenReturn("91011"); + Mockito.when(httpServletRequest.getParameter(SearchHelper.INACTIVE)).thenReturn("false"); + Mockito.when(httpServletRequest.getParameter(SearchHelper.LOST_TO_FOLLOW_UP)).thenReturn("true"); + Mockito.when(httpServletRequest.getParameter(SearchHelper.NFC_CARD_IDENTIFIER)).thenReturn("nfc_card_identifier_1"); + SearchEntityWrapper searchEntityWrapper = SearchHelper.childSearchParamProcessor(httpServletRequest); + + Map attributes = searchEntityWrapper.getClientSearchBean().getAttributes(); + Assert.assertEquals(3, attributes.size()); + + Map identifiers = searchEntityWrapper.getClientSearchBean().getIdentifiers(); + Assert.assertEquals(4, identifiers.size()); + + Assert.assertTrue(identifiers.containsKey(SearchHelper.ZEIR_ID)); + Assert.assertTrue(identifiers.containsKey("ZEIR_ID")); //check backward compatibility with upper case key + Assert.assertTrue(identifiers.containsKey(SearchHelper.SIM_PRINT_GUID)); + + Assert.assertTrue(attributes.containsKey(SearchHelper.INACTIVE)); + Assert.assertTrue(attributes.containsKey(SearchHelper.LOST_TO_FOLLOW_UP)); + Assert.assertTrue(attributes.containsKey("NFC_Card_Identifier")); + + Assert.assertEquals(identifiers.get(SearchHelper.ZEIR_ID), "1234"); + Assert.assertEquals(attributes.get("NFC_Card_Identifier"), "nfc_card_identifier_1"); + } + + @Test + public void testSetCoreFiltersForJSONObjectWithIntegerLimitReturnsValue(){ + JSONObject jsonObject = new JSONObject(); + jsonObject.put("limit", 50); + try { + int result = SearchHelper.setCoreFilters(jsonObject, new ClientSearchBean()); + Assert.assertEquals(50,result); + } catch (ParseException e) { + e.printStackTrace(); + } + } + + @Test + public void testSetCoreFiltersForJSONObjectWithStringLimitReturnsValue(){ + JSONObject jsonObject = new JSONObject(); + jsonObject.put("limit", "50"); + try { + int result = SearchHelper.setCoreFilters(jsonObject, new ClientSearchBean()); + Assert.assertEquals(50,result); + } catch (ParseException e) { + e.printStackTrace(); + } + } + }