Skip to content

Commit

Permalink
Add an OrderFrequencyValidator - TRUNK-4192
Browse files Browse the repository at this point in the history
  • Loading branch information
dkayiwa committed Feb 27, 2014
1 parent c8a5026 commit 27d6c00
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 3 deletions.
11 changes: 11 additions & 0 deletions api/src/main/java/org/openmrs/api/OrderService.java
Expand Up @@ -307,6 +307,17 @@ public <Ord extends Order> List<Ord> getActiveOrders(Patient patient, Class<Ord>
@Authorized(PrivilegeConstants.VIEW_ORDER_FREQUENCIES)
public OrderFrequency getOrderFrequencyByUuid(String uuid);

/**
* Gets an OrderFrequency that matches the specified concept
*
* @param concept the concept to match against
* @return OrderFrequency
* @since 1.10
* @should return the order frequency that matches the specified concept
*/
@Authorized(PrivilegeConstants.VIEW_ORDER_FREQUENCIES)

This comment has been minimized.

Copy link
@wluyima

wluyima Feb 28, 2014

Member

Hmmm.... i think this can be private for now until people ask for it

This comment has been minimized.

Copy link
@dkayiwa

dkayiwa Feb 28, 2014

Author Member

How should i call it from OrderFrequencyValidator if private? :)

This comment has been minimized.

Copy link
@wluyima

wluyima Feb 28, 2014

Member

I said it because normally we make such checks in the service impl but i guess this is then fine

public OrderFrequency getOrderFrequencyByConcept(Concept concept);

/**
* Gets all order frequencies
*
Expand Down
5 changes: 5 additions & 0 deletions api/src/main/java/org/openmrs/api/db/OrderDAO.java
Expand Up @@ -154,4 +154,9 @@ public List<OrderFrequency> getOrderFrequencies(String searchPhrase, Locale loca
* @return true if in use, else false
*/
public boolean isOrderFrequencyInUse(OrderFrequency orderFrequency);

/**
* @See OrderService#getOrderFrequencyByConcept
*/
public OrderFrequency getOrderFrequencyByConcept(Concept concept);
}
Expand Up @@ -396,4 +396,14 @@ public boolean isOrderFrequencyInUse(OrderFrequency orderFrequency) {

return false;
}

/**
* @see org.openmrs.api.db.OrderDAO#getOrderFrequencyByConcept(org.openmrs.Concept)
*/
@Override
public OrderFrequency getOrderFrequencyByConcept(Concept concept) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(OrderFrequency.class);
criteria.add(Restrictions.eq("concept", concept));
return (OrderFrequency) criteria.uniqueResult();
}
}
9 changes: 9 additions & 0 deletions api/src/main/java/org/openmrs/api/impl/OrderServiceImpl.java
Expand Up @@ -500,4 +500,13 @@ public void purgeOrderFrequency(OrderFrequency orderFrequency) {

dao.purgeOrderFrequency(orderFrequency);
}

/**
* @see org.openmrs.api.OrderService#getOrderFrequencyByConcept(org.openmrs.Concept)
*/
@Override
@Transactional(readOnly = true)
public OrderFrequency getOrderFrequencyByConcept(Concept concept) {
return dao.getOrderFrequencyByConcept(concept);
}
}
@@ -0,0 +1,81 @@
/**
* 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.validator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.Concept;
import org.openmrs.OrderFrequency;
import org.openmrs.annotation.Handler;
import org.openmrs.api.context.Context;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;

/**
* Validates the {@link OrderFrequency} class.
*
* @since 1.10
*/
@Handler(supports = { OrderFrequency.class })
public class OrderFrequencyValidator {

/** Log for this class and subclasses */
protected final Log log = LogFactory.getLog(getClass());

/**
* Determines if the command object being submitted is a valid type
*
* @see org.springframework.validation.Validator#supports(java.lang.Class)
*/
@SuppressWarnings("unchecked")
public boolean supports(Class c) {
return OrderFrequency.class.isAssignableFrom(c);
}

/**
* Checks the order frequency object for any inconsistencies/errors
*
* @see org.springframework.validation.Validator#validate(java.lang.Object,
* org.springframework.validation.Errors)
* @should fail if orderFrequency is null
* @should fail if concept is null
* @should fail if the concept is not of class frequency
* @should fail if concept is used by another frequency
* @should pass if all fields are correct
*/
public void validate(Object obj, Errors errors) {
OrderFrequency orderFrequency = (OrderFrequency) obj;
if (orderFrequency == null) {
errors.reject("error.general");
} else {
ValidationUtils.rejectIfEmpty(errors, "concept", "Concept.noConceptSelected");

Concept concept = orderFrequency.getConcept();
if (concept != null) {
if (concept.getConceptClass() == null) {
errors.rejectValue("concept", "OrderFrequency.concept.shouldBeClassFrequency");

This comment has been minimized.

Copy link
@wluyima

wluyima Feb 28, 2014

Member

This message needs to differ from the one below so that the user knows that the concept class is null, infact i wouldn't make this check because concept class is required on concept, so let the concept validator worry about that, either way we will get a NPE which would halt the validation.

} else {
if (!"Frequency".equals(concept.getConceptClass().getName())) {

This comment has been minimized.

Copy link
@wluyima

wluyima Feb 28, 2014

Member

Am not sure if the name of this concept class will be Frequency but am sure its going to be added as a standard concept class with uuid 8e071bfe-520c-44c0-a89b-538e9129b42a

errors.rejectValue("concept", "OrderFrequency.concept.shouldBeClassFrequency");
}
}

OrderFrequency of = Context.getOrderService().getOrderFrequencyByConcept(concept);
if (of != null && !of.equals(orderFrequency)) {
errors.rejectValue("concept", "OrderFrequency.concept.shouldNotBeShared");
}
}
}
}
}
@@ -0,0 +1,101 @@
/**
* 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.validator;

import org.junit.Assert;
import org.junit.Test;
import org.openmrs.Concept;
import org.openmrs.OrderFrequency;
import org.openmrs.api.context.Context;
import org.openmrs.test.BaseContextSensitiveTest;
import org.openmrs.test.Verifies;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;

/**
* Tests methods on the {@link OrderFrequencyValidator} class.
*/
public class OrderFrequencyValidatorTest extends BaseContextSensitiveTest {

/**
* @see {@link OrderFrequencyValidator#validate(Object,Errors)}
*/
@Test
@Verifies(value = "should fail if orderFrequency is null", method = "validate(Object,Errors)")
public void validate_shouldFailIfOrderFrequencyIsNull() throws Exception {
Errors errors = new BindException(new OrderFrequency(), "orderFrequency");
new OrderFrequencyValidator().validate(null, errors);

Assert.assertTrue(errors.hasErrors());
}

/**
* @see {@link OrderFrequencyValidator#validate(Object,Errors)}
*/
@Test
@Verifies(value = "should fail if concept is null", method = "validate(Object,Errors)")
public void validate_shouldFailIfConceptIsNull() throws Exception {
OrderFrequency orderFrequency = new OrderFrequency();

Errors errors = new BindException(orderFrequency, "orderFrequency");
new OrderFrequencyValidator().validate(orderFrequency, errors);

Assert.assertTrue(errors.hasFieldErrors("concept"));
}

/**
* @see {@link OrderFrequencyValidator#validate(Object,Errors)}
*/
@Test
@Verifies(value = "should fail if the concept is not of class frequency", method = "validate(Object,Errors)")
public void validate_shouldFailIfConceptIsNotOfClassFrequency() throws Exception {
OrderFrequency orderFrequency = new OrderFrequency();
orderFrequency.setConcept(Context.getConceptService().getConcept(88));
Errors errors = new BindException(orderFrequency, "orderFrequency");
new OrderFrequencyValidator().validate(orderFrequency, errors);

Assert.assertTrue(errors.hasFieldErrors("concept"));
}

/**
* @see {@link OrderFrequencyValidator#validate(Object,Errors)}
*/
@Test
@Verifies(value = "should fail if concept is used by another frequency", method = "validate(Object,Errors)")
public void validate_shouldFailIfConceptIsUsedByAnotherFrequency() throws Exception {
OrderFrequency orderFrequency = new OrderFrequency();
orderFrequency.setConcept(Context.getConceptService().getConcept(113));
Errors errors = new BindException(orderFrequency, "orderFrequency");
new OrderFrequencyValidator().validate(orderFrequency, errors);

Assert.assertTrue(errors.hasFieldErrors("concept"));
}

/**
* @see {@link OrderFrequencyValidator#validate(Object,Errors)}
*/
@Test
@Verifies(value = "should pass if all fields are correct", method = "validate(Object,Errors)")
public void validate_shouldPassIfAllFieldsAreCorrect() throws Exception {
Concept concept = new Concept(1);
concept.setConceptClass(Context.getConceptService().getConceptClass(19));

OrderFrequency orderFrequency = new OrderFrequency();
orderFrequency.setConcept(concept);
Errors errors = new BindException(orderFrequency, "orderFrequency");
new OrderFrequencyValidator().validate(orderFrequency, errors);

Assert.assertFalse(errors.hasErrors());
}
}
Expand Up @@ -51,6 +51,7 @@
<concept_class concept_class_id="16" name="Program" description="A treatment program" creator="1" date_created="2008-08-15 13:55:59.0" retired="false" uuid="2a3738f5-26f0-4f97-ae7a-f99e42fa6d44"/>
<concept_class concept_class_id="17" name="Workflow" description="A workflow within a treatment program" creator="1" date_created="2008-08-15 13:56:30.0" retired="false" uuid="dbdf1b12-dbcb-4d41-a8eb-39a551f56e6d"/>
<concept_class concept_class_id="18" name="State" description="A state within a workflow" creator="1" date_created="2008-08-15 13:56:55.0" retired="false" uuid="ac3feb09-e120-4d8c-97ee-f7544720efb8"/>
<concept_class concept_class_id="19" name="Frequency" description="A class for order frequencies" creator="1" date_created="2008-08-15 13:56:55.0" retired="false" uuid="cd9emn09-e120-4d8c-97ee-f7544720efb8"/>

This comment has been minimized.

Copy link
@wluyima

wluyima Feb 28, 2014

Member

This UUID should be e30d8601-07f8-413a-9d11-cdfbb28196ec

<concept_datatype concept_datatype_id="1" name="Numeric" hl7_abbreviation="NM" description="Numeric value, including integer or float (e.g., creatinine, weight)" creator="1" date_created="2004-02-02 00:00:00.0" retired="false" uuid="8d4a4488-c2cc-11de-8d13-0010c6dffd0f"/>
<concept_datatype concept_datatype_id="2" name="Coded" hl7_abbreviation="CWE" description="Value determined by term dictionary lookup (i.e., term identifier)" creator="1" date_created="2004-02-02 00:00:00.0" retired="false" uuid="8d4a48b6-c2cc-11de-8d13-0010c6dffd0f"/>
<concept_datatype concept_datatype_id="3" name="Text" hl7_abbreviation="ST" description="Free text" creator="1" date_created="2004-02-02 00:00:00.0" retired="false" uuid="8d4a4ab4-c2cc-11de-8d13-0010c6dffd0f"/>
Expand Down Expand Up @@ -175,11 +176,11 @@
<drug drug_id="2" concept_id="792" name="Triomune-30" combination="true" dose_strength="1.0" units="tab(s)" creator="1" date_created="2005-02-24 00:00:00.0" retired="false" uuid="3cfcf118-931c-46f7-8ff6-7b876f0d4202"/>
<drug drug_id="3" concept_id="88" name="Aspirin" combination="false" dose_strength="325.0" units="mg" creator="1" date_created="2005-02-24 00:00:00.0" retired="false" uuid="05ec820a-d297-44e3-be6e-698531d9dd3f"/>
<drug drug_id="11" concept_id="3" name="NYQUIL" combination="true" units="" creator="1" date_created="2008-08-15 15:34:03.0" retired="true" uuid="7e2323fa-0fa0-461f-9b59-6765997d849e"/>
<concept concept_id="113" retired="true" datatype_id="1" class_id="1" is_set="false" creator="1" date_created="2004-08-12 00:00:00.0" version="" uuid="7e02d1a0-7869-11e3-981f-0800200c9a66"/>
<concept concept_id="113" retired="true" datatype_id="1" class_id="19" is_set="false" creator="1" date_created="2004-08-12 00:00:00.0" version="" uuid="7e02d1a0-7869-11e3-981f-0800200c9a66"/>
<concept_name concept_id="113" name="1/day x 7 days/week" concept_name_id="1131" locale="en" creator="1" date_created="2008-08-15 13:52:53.0" concept_name_type="FULLY_SPECIFIED" locale_preferred="1" voided="false" uuid="83f24a00-7869-11e3-981f-0800200c9a66"/>
<order_frequency order_frequency_id="1" concept_id="113" creator="1" date_created="2008-08-15 13:52:53.0" retired="false" uuid="28090760-7c38-11e3-baa7-0800200c9a66" />
<order_frequency order_frequency_id="2" concept_id="113" creator="1" date_created="2008-08-15 13:52:53.0" retired="false" uuid="38090760-7c38-11e3-baa7-0800200c9a66" />
<order_frequency order_frequency_id="3" concept_id="113" creator="1" date_created="2008-08-15 13:52:53.0" retired="true" retire_reason="Some Retire Reason" retired_by="1" date_retired="2009-08-15 13:52:53.0" uuid="48090760-7c38-11e3-baa7-0800200c9a66" />
<order_frequency order_frequency_id="2" concept_id="3" creator="1" date_created="2008-08-15 13:52:53.0" retired="false" uuid="38090760-7c38-11e3-baa7-0800200c9a66" />
<order_frequency order_frequency_id="3" concept_id="4" creator="1" date_created="2008-08-15 13:52:53.0" retired="true" retire_reason="Some Retire Reason" retired_by="1" date_retired="2009-08-15 13:52:53.0" uuid="48090760-7c38-11e3-baa7-0800200c9a66" />
<drug_order order_id="1" drug_inventory_id="3" dose="325.0" dose_units="50" as_needed="false" frequency="1" dosing_type="SIMPLE"/>
<drug_order order_id="2" drug_inventory_id="2" dose="1.0" dose_units="51" as_needed="false" frequency="1" dosing_type="SIMPLE"/>
<drug_order order_id="3" drug_inventory_id="2" dose="2.0" dose_units="51" as_needed="false" frequency="1" dosing_type="SIMPLE"/>
Expand Down
3 changes: 3 additions & 0 deletions webapp/src/main/webapp/WEB-INF/messages.properties
Expand Up @@ -2733,3 +2733,6 @@ Provider.notLinkedToPerson=Provider not linked to person
Provider.linkToPerson=Link to person
Provider.unLinkFromPerson=Unlink from person
Provider.error.duplicateIdentifier=Another provider already has the identifier {0}

OrderFrequency.concept.shouldBeClassFrequency=Concept should be of class Frequency
OrderFrequency.concept.shouldNotBeShared=Only one OrderFrequency should be mapped to a particular concept

0 comments on commit 27d6c00

Please sign in to comment.