Skip to content

Commit

Permalink
locking mechanism for encounter_type - TRUNK-4033
Browse files Browse the repository at this point in the history
[TRUNK-4033] made some changes

added a testcase, and made some other changes

[TRUNK-4033] added a disabled attribute if encounterTypesLocked == 'true'

[TRUNK-4033] added a testcase i.e. EncounterService.saveEncounterType_shouldNotSaveEncounterTypeIfEncounterTypesAreLocked()

[TRUNK-4033] added some other testcases and made some changes

Removed or converted throws clauses for EncounterTypeLockedException to APIException - TRUNK-4033

Removed unused import in HibernateEncounterDAO

Follow up to fix compilation issues - TRUNK-4033

Second follow up to fix compilation issues - TRUNK-4033

Third follow up to fix compilation issues - TRUNK-4033

Fourth follow up to fix compilation issues - TRUNK-4033
  • Loading branch information
k-joseph authored and wluyima committed Aug 29, 2013
1 parent 7b9daa8 commit 5018dd5
Show file tree
Hide file tree
Showing 10 changed files with 345 additions and 34 deletions.
13 changes: 12 additions & 1 deletion api/src/main/java/org/openmrs/api/EncounterService.java
Expand Up @@ -223,9 +223,10 @@ public List<Encounter> getEncounters(Patient who, Location loc, Date fromDate, D
* @should not overwrite creator or date created
* @should not overwrite date created
* @should update an existing encounter type name
* @should throw error when trying to save encounter type when encounter types are locked
*/
@Authorized( { PrivilegeConstants.MANAGE_ENCOUNTER_TYPES })
public EncounterType saveEncounterType(EncounterType encounterType);
public EncounterType saveEncounterType(EncounterType encounterType) throws APIException;

/**
* Get encounterType by internal identifier
Expand Down Expand Up @@ -316,6 +317,7 @@ public List<Encounter> getEncounters(Patient who, Location loc, Date fromDate, D
* @throws APIException
* @should retire type and set attributes
* @should throw error if given null reason parameter
* @should should throw error when trying to retire encounter type when encounter types are locked
*/
@Authorized( { PrivilegeConstants.MANAGE_ENCOUNTER_TYPES })
public EncounterType retireEncounterType(EncounterType encounterType, String reason) throws APIException;
Expand All @@ -327,6 +329,7 @@ public List<Encounter> getEncounters(Patient who, Location loc, Date fromDate, D
* @param encounterType the encounter type to unretire
* @throws APIException
* @should unretire type and unmark attributes
* @should should throw error when trying to unretire encounter type when encounter types are locked
*/
@Authorized( { PrivilegeConstants.MANAGE_ENCOUNTER_TYPES })
public EncounterType unretireEncounterType(EncounterType encounterType) throws APIException;
Expand All @@ -337,6 +340,7 @@ public List<Encounter> getEncounters(Patient who, Location loc, Date fromDate, D
* @param encounterType
* @throws APIException
* @should purge type
* @should should throw error when trying to delete encounter type when encounter types are locked
*/
@Authorized( { PrivilegeConstants.PURGE_ENCOUNTER_TYPES })
public void purgeEncounterType(EncounterType encounterType) throws APIException;
Expand Down Expand Up @@ -625,4 +629,11 @@ public List<Encounter> getEncounters(String query, Integer start, Integer length
@Authorized( { PrivilegeConstants.VIEW_ENCOUNTERS })
public Integer getCountOfEncounters(String query, boolean includeVoided);

/**
* Check if the encounter types are locked, and if so, throw exception during manipulation of encounter type
*
* @throws EncounterTypeLockedException
*/
@Transactional(readOnly = true)
public void checkIfEncounterTypesAreLocked() throws EncounterTypeLockedException;
}
@@ -0,0 +1,69 @@
/**
* 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.api;

import org.openmrs.util.OpenmrsConstants;

/**
* This exception is thrown when a encounter types are locked and the user tries to edit an encounter type
* type, this is done by a global property being true/false.
*
* @since 1.10 added to 1.8.5 and 1.9.4
*
* @see OpenmrsConstants#GLOBAL_PROPERTY_ENCOUNTER_TYPES_LOCKED
* @see EncounterService#checkIfLocked()
*/
public class EncounterTypeLockedException extends APIException {

private static final long serialVersionUID = 1223334444L;

/**
* Generic constructor that gives a normal message about editing not being allowed to the user.
*/
public EncounterTypeLockedException() {
this("Editing of encounter types is not allowed at this time since they are currently locked. ");
}

/**
* Convenience constructor to give the user a message other than normal default one
*
* @param message the String to show to the user as to why the encounter types are locked
*/
public EncounterTypeLockedException(String message) {
super(message);
}

/**
* Convenience constructor to give the user a message other than the normal one and to chain
* this exception with a parent exception.
*
* @param message the String to show to the user as to why the encounter types are locked
* @param cause the parent exception
*/
public EncounterTypeLockedException(String message, Throwable cause) {
super(message, cause);
}

/**
* Convenience constructor used to only set the parent exception to chain with. This does not
* set the error message for the user as to why an exception is being thrown. The
* {@link #EncounterTypeLockedException(String, Throwable)} constructor is preferred over this
* one.
*
* @param cause the parent exception
*/
public EncounterTypeLockedException(Throwable cause) {
super(cause);
}
}
24 changes: 24 additions & 0 deletions api/src/main/java/org/openmrs/api/impl/EncounterServiceImpl.java
Expand Up @@ -31,10 +31,12 @@
import org.openmrs.User;
import org.openmrs.api.APIException;
import org.openmrs.api.EncounterService;
import org.openmrs.api.EncounterTypeLockedException;
import org.openmrs.api.ObsService;
import org.openmrs.api.OrderService;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.EncounterDAO;
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.util.OpenmrsUtil;
import org.openmrs.util.PrivilegeConstants;

Expand Down Expand Up @@ -310,6 +312,9 @@ public void purgeEncounter(Encounter encounter, boolean cascade) throws APIExcep
* @see org.openmrs.api.EncounterService#saveEncounterType(org.openmrs.EncounterType)
*/
public EncounterType saveEncounterType(EncounterType encounterType) {
//make sure the user has not turned off encounter types editing
checkIfEncounterTypesAreLocked();

dao.saveEncounterType(encounterType);
return encounterType;
}
Expand Down Expand Up @@ -356,6 +361,9 @@ public EncounterType retireEncounterType(EncounterType encounterType, String rea
if (reason == null)
throw new IllegalArgumentException("The 'reason' argument is required");

//make sure the user has not turned off encounter types editing
checkIfEncounterTypesAreLocked();

encounterType.setRetired(true);
encounterType.setRetireReason(reason);
return saveEncounterType(encounterType);
Expand All @@ -365,6 +373,8 @@ public EncounterType retireEncounterType(EncounterType encounterType, String rea
* @see org.openmrs.api.EncounterService#unretireEncounterType(org.openmrs.EncounterType)
*/
public EncounterType unretireEncounterType(EncounterType encounterType) throws APIException {
checkIfEncounterTypesAreLocked();

encounterType.setRetired(false);
return saveEncounterType(encounterType);
}
Expand All @@ -373,6 +383,9 @@ public EncounterType unretireEncounterType(EncounterType encounterType) throws A
* @see org.openmrs.api.EncounterService#purgeEncounterType(org.openmrs.EncounterType)
*/
public void purgeEncounterType(EncounterType encounterType) throws APIException {
//make sure the user has not turned off encounter types editing
checkIfEncounterTypesAreLocked();

dao.deleteEncounterType(encounterType);
}

Expand Down Expand Up @@ -568,4 +581,15 @@ public List<Encounter> getEncounters(String query, Integer start, Integer length
public Integer getCountOfEncounters(String query, boolean includeVoided) {
return dao.getCountOfEncounters(query, includeVoided);
}

/**
* @see org.openmrs.api.EncounterService#checkIfEncounterTypesAreLocked()
*/
public void checkIfEncounterTypesAreLocked() {
String locked = Context.getAdministrationService().getGlobalProperty(
OpenmrsConstants.GLOBAL_PROPERTY_ENCOUNTER_TYPES_LOCKED, "false");
if (locked.toLowerCase().equals("true")) {
throw new EncounterTypeLockedException();
}
}
}
4 changes: 4 additions & 0 deletions api/src/main/java/org/openmrs/util/OpenmrsConstants.java
Expand Up @@ -830,6 +830,8 @@ public static final Collection<String> AUTO_ROLES() {

public static final String GLOBAL_PROPERTY_REPORT_BUG_URL = "reportProblem.url";

public static final String GLOBAL_PROPERTY_ENCOUNTER_TYPES_LOCKED = "EncounterType.encounterTypes.locked";

/**
* Global property name that allows specification of whether user passwords must contain both
* upper and lower case characters. Allowable values are "true", "false", and null
Expand Down Expand Up @@ -1245,6 +1247,8 @@ public static final List<GlobalProperty> CORE_GLOBAL_PROPERTIES() {

props.add(new GlobalProperty(GLOBAL_PROPERTY_DEFAULT_LOCATION_NAME, "Unknown Location",
"The name of the location to use as a system default"));
props.add(new GlobalProperty(GLOBAL_PROPERTY_ENCOUNTER_TYPES_LOCKED, "false",
"saving, retiring or deleting an Encounter Type is not permitted, if true"));

props
.add(new GlobalProperty(GP_CONCEPT_DRUG_DOSAGE_FORM_CONCEPT_CLASSES, "",
Expand Down
75 changes: 75 additions & 0 deletions api/src/test/java/org/openmrs/api/EncounterServiceTest.java
Expand Up @@ -36,6 +36,7 @@
import org.openmrs.Encounter;
import org.openmrs.EncounterType;
import org.openmrs.Form;
import org.openmrs.GlobalProperty;
import org.openmrs.Location;
import org.openmrs.Obs;
import org.openmrs.Order;
Expand All @@ -45,6 +46,7 @@
import org.openmrs.api.context.Context;
import org.openmrs.test.BaseContextSensitiveTest;
import org.openmrs.test.Verifies;
import org.openmrs.util.OpenmrsConstants;

/**
* Tests all methods in the {@link EncounterService}
Expand Down Expand Up @@ -1427,4 +1429,77 @@ public void getCountOfEncounters_shouldShouldGetTheCorrectCountOfUniqueEncounter
Assert.assertEquals(4, Context.getEncounterService().getCountOfEncounters("qwerty", true).intValue());
}

/**
* @see {@link EncounterService#saveEncounterType(EncounterType)}}
* @see {@link EncounterService#checkIfEncounterTypesAreLocked()}}
*/
@Test(expected = EncounterTypeLockedException.class)
@Verifies(value = "should throw error when trying to save encounter type when encounter types are locked", method = "saveEncounterType(EncounterType)")
public void saveEncounterType_shouldThrowErrorWhenTryingToSaveEncounterTypeWhenEncounterTypesAreLocked()
throws Exception {
GlobalProperty gp = new GlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_ENCOUNTER_TYPES_LOCKED);
gp.setPropertyValue("true");
Context.getAdministrationService().saveGlobalProperty(gp);

EncounterService encounterService = Context.getEncounterService();
EncounterType encounterType = Context.getEncounterService().getEncounterType(1);

Assert.assertNotNull(encounterType);

encounterService.saveEncounterType(encounterType);
}

/**
* @see {@link EncounterService#retireEncounterType(EncounterType, String)}}
*/
@Test(expected = EncounterTypeLockedException.class)
@Verifies(value = "should throw error when trying to retire encounter type when encounter types are locked", method = "retireEncounterType(EncounterType, String)")
public void retireEncounterType_shouldThrowErrorWhenTryingToRetireEncounterTypeWhenEncounterTypesAreLocked()
throws Exception {
GlobalProperty gp = new GlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_ENCOUNTER_TYPES_LOCKED);
gp.setPropertyValue("true");
Context.getAdministrationService().saveGlobalProperty(gp);

EncounterService encounterService = Context.getEncounterService();
EncounterType encounterType = Context.getEncounterService().getEncounterType(1);
Assert.assertNotNull(encounterType);

encounterService.retireEncounterType(encounterType, "reason");
}

/**
* @see {@link EncounterService#unretireEncounterType(EncounterType)}}
*/
@Test(expected = EncounterTypeLockedException.class)
@Verifies(value = "should throw error when trying to unretire encounter type when encounter types are locked", method = "unretireEncounterType(EncounterType)")
public void unretireEncounterType_shouldThrowErrorWhenTryingToUnretireEncounterTypeWhenEncounterTypesAreLocked()
throws Exception {
EncounterService encounterService = Context.getEncounterService();
EncounterType encounterType = Context.getEncounterService().getEncounterType(2);

GlobalProperty gp = new GlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_ENCOUNTER_TYPES_LOCKED);
gp.setPropertyValue("true");
Context.getAdministrationService().saveGlobalProperty(gp);

encounterService.unretireEncounterType(encounterType);
}

/**
* @see {@link EncounterService#purgeEncounterType(EncounterType)}}
*/
@Test(expected = EncounterTypeLockedException.class)
@Verifies(value = "should throw error when trying to delete encounter type when encounter types are locked", method = "purgeEncounterType(EncounterType)")
public void purgeEncounterType_shouldThrowErrorWhenTryingToDeleteEncounterTypeWhenEncounterTypesAreLocked()
throws Exception {
EncounterService encounterService = Context.getEncounterService();
EncounterType encounterType = Context.getEncounterService().getEncounterType(1);

Assert.assertNotNull(encounterType);

GlobalProperty gp = new GlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_ENCOUNTER_TYPES_LOCKED);
gp.setPropertyValue("true");
Context.getAdministrationService().saveGlobalProperty(gp);

encounterService.purgeEncounterType(encounterType);
}
}
Expand Up @@ -23,6 +23,7 @@
import org.openmrs.EncounterType;
import org.openmrs.api.APIException;
import org.openmrs.api.EncounterService;
import org.openmrs.api.EncounterTypeLockedException;
import org.openmrs.api.context.Context;
import org.openmrs.web.WebConstants;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
Expand Down Expand Up @@ -71,44 +72,60 @@ protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse
EncounterType encounterType = (EncounterType) obj;
EncounterService es = Context.getEncounterService();

if (request.getParameter("save") != null) {
es.saveEncounterType(encounterType);
view = getSuccessView();
httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "EncounterType.saved");
}
try {
if (request.getParameter("save") != null) {
es.saveEncounterType(encounterType);
view = getSuccessView();
httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "EncounterType.saved");
}

// if the user is retiring out the EncounterType
else if (request.getParameter("retire") != null) {
String retireReason = request.getParameter("retireReason");
if (encounterType.getEncounterTypeId() != null && !(StringUtils.hasText(retireReason))) {
errors.reject("retireReason", "general.retiredReason.empty");
return showForm(request, response, errors);
// if the user is retiring out the EncounterType
else if (request.getParameter("retire") != null) {
String retireReason = request.getParameter("retireReason");
if (encounterType.getEncounterTypeId() != null && !(StringUtils.hasText(retireReason))) {
errors.reject("retireReason", "general.retiredReason.empty");
return showForm(request, response, errors);
}
es.retireEncounterType(encounterType, retireReason);
httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "EncounterType.retiredSuccessfully");

view = getSuccessView();
}

es.retireEncounterType(encounterType, retireReason);
httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "EncounterType.retiredSuccessfully");

view = getSuccessView();
}

// if the user is purging the encounterType
else if (request.getParameter("purge") != null) {

try {
es.purgeEncounterType(encounterType);
httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "EncounterType.purgedSuccessfully");
// if the user is unretiring the EncounterType
else if (request.getParameter("unretire") != null) {
es.unretireEncounterType(encounterType);
httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "EncounterType.unretiredSuccessfully");

view = getSuccessView();
}
catch (DataIntegrityViolationException e) {
httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "error.object.inuse.cannot.purge");
view = "encounterType.form?encounterTypeId=" + encounterType.getEncounterTypeId();

// if the user is purging the encounterType
else if (request.getParameter("purge") != null) {

try {
es.purgeEncounterType(encounterType);
httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "EncounterType.purgedSuccessfully");
view = getSuccessView();
}
catch (DataIntegrityViolationException e) {
httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "error.object.inuse.cannot.purge");
view = "encounterType.form?encounterTypeId=" + encounterType.getEncounterTypeId();
}
catch (APIException e) {
httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "error.general: "
+ e.getLocalizedMessage());
view = "encounterType.form?encounterTypeId=" + encounterType.getEncounterTypeId();
}
}
catch (APIException e) {
httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "error.general: " + e.getLocalizedMessage());
}
catch (EncounterTypeLockedException e) {
log.error("tried to save, retire, unretire or delete encounter type while encounter types were locked", e);
httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "EncounterType.encounterTypes.locked");
if (encounterType.getEncounterTypeId() != null) {
view = "encounterType.form?encounterTypeId=" + encounterType.getEncounterTypeId();
}
}

}

return new ModelAndView(new RedirectView(view));
Expand Down

0 comments on commit 5018dd5

Please sign in to comment.