/** * This Source Code Form is subject to the terms of the Mozilla Public License, * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. * * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS * graphic logo is a trademark of OpenMRS Inc. */ package org.openmrs.module.webservices.rest.web.resource.api; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.apache.commons.lang.Validate; /** * Search query used by the {@link SearchConfig}. * <p> * Typical usage involves: * <ol> * <li>Get an instance of the {@code Builder} via {@link Builder#Builder(String)} * <li>Set the various search query properties through the respective methods of the static builder * class ({@link Builder#withRequiredParameters(String...)}, * {@link Builder#withOptionalParameters(String...)}.</li> * <li>Build the {@link SearchQuery} instance with the {@link Builder#build()} method.</li> * <li>Get the search query properties through the getter methods (such as * {@link #getRequiredParameters()} or {@link #getOptionalParameters()}).</li> * </ol> */ public class SearchQuery { private Set<SearchParameter> requiredParameters; private Set<SearchParameter> optionalParameters; private String description; private SearchQuery() { } public static class Builder { private SearchQuery searchQuery = new SearchQuery(); /** * Create an instance of the {@code Builder}. * * @param description the search query description */ public Builder(String description) { searchQuery.description = description; } /** * Set the {@code requiredParameters}. * * @param requiredParameters the required empty parameters to be set * @return this builder instance * @should fail if required parameters are already set */ public Builder withRequiredParameters(String... requiredParameters) { if (searchQuery.requiredParameters != null) { throw new IllegalStateException("withRequiredParameters() must not be called twice"); } Set parameters = new HashSet<SearchParameter>(); for (String parameter : requiredParameters) { parameters.add(new SearchParameter(parameter)); } searchQuery.requiredParameters = Collections.unmodifiableSet(parameters); return this; } /** * Set the {@code requiredParameters}. * * @param requiredParameters the required parameters * @return this builder instance */ public Builder withRequiredParameters(SearchParameter... requiredParameters) { if (searchQuery.requiredParameters != null) { throw new IllegalStateException("withRequiredParameters() must not be called twice"); } searchQuery.requiredParameters = Collections.unmodifiableSet(new HashSet<SearchParameter>(Arrays .asList(requiredParameters))); return this; } /** * Set the {@code optionalParameters}. * * @param optionalParameters the optional parameters to be set * @return this builder instance * @should fail if optional parameters are already set */ public Builder withOptionalParameters(String... optionalParameters) { if (searchQuery.optionalParameters != null) { throw new IllegalStateException("withOptionalParameters() must not be called twice"); } Set parameters = new HashSet<SearchParameter>(); for (String parameter : optionalParameters) { parameters.add(new SearchParameter(parameter)); } searchQuery.optionalParameters = Collections.unmodifiableSet(parameters); return this; } /** * Set the {@code optionalParameters}. * * @param optionalParameters the optional parameters * @return this builder instance */ public Builder withOptionalParameters(SearchParameter... optionalParameters) { if (searchQuery.optionalParameters != null) { throw new IllegalStateException("withOptionalParameters() must not be called twice"); } searchQuery.optionalParameters = Collections.unmodifiableSet(new HashSet<SearchParameter>(Arrays .asList(optionalParameters))); return this; } /** * Builds an instance of {@code SearchQuery}. * * @return a search query instance with properties set through the builder * @should return a search query instance with properties set through the builder * @should assign an empty set to required parameters if not set by the builder * @should assign an empty set to optional parameters if not set by the builder * @should fail if the description is null * @should fail if the description is empty * @should fail if both required and optional parameters are empty */ public SearchQuery build() { if (searchQuery.requiredParameters == null) { searchQuery.requiredParameters = Collections.emptySet(); } if (searchQuery.optionalParameters == null) { searchQuery.optionalParameters = Collections.emptySet(); } Validate.notEmpty(searchQuery.description, "Description must not be empty"); Validate.isTrue(!searchQuery.requiredParameters.isEmpty() || !searchQuery.optionalParameters.isEmpty(), "Either required or optional parameters must not be empty"); return searchQuery; } } /** * Get this {@code requiredParameters}. * * @return this required parameters */ public Set<SearchParameter> getRequiredParameters() { return requiredParameters; } /** * Get this {@code optionalParameters}. * * @return this optional parameters */ public Set<SearchParameter> getOptionalParameters() { return optionalParameters; } /** * Get this {@code description}. * * @return this description */ public String getDescription() { return description; } /** * @see Object#hashCode() * @return the hash code * @should return same hashcode for equal search configs */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((optionalParameters == null) ? 0 : optionalParameters.hashCode()); result = prime * result + ((requiredParameters == null) ? 0 : requiredParameters.hashCode()); return result; } /** * @see Object#equals(Object) * @param obj the object to test for if equal to this * @return true if obj is equal to this otherwise false * @should return true if given this * @should return true if this optional parameters and required parameters are equal to given * search query * @should be symmetric * @should be transitive * @should return false if given null * @should return false if given an object which is not an instanceof this class * @should return false if this optional parameters is not equal to the given search queries * optional parameters * @should return false if this required parameters is not equal to the given search queries * required parameters */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof SearchQuery)) { return false; } SearchQuery other = (SearchQuery) obj; if (optionalParameters == null) { if (other.optionalParameters != null) return false; } else if (!optionalParameters.equals(other.optionalParameters)) return false; if (requiredParameters == null) { if (other.requiredParameters != null) return false; } else if (!requiredParameters.equals(other.requiredParameters)) return false; return true; } }