Skip to content

Commit

Permalink
TRUNK-5862: Condition and Obs to implement FormRecordable.
Browse files Browse the repository at this point in the history
  • Loading branch information
icrc-loliveira committed Jul 21, 2020
1 parent 9e77396 commit 3c34c43
Show file tree
Hide file tree
Showing 9 changed files with 356 additions and 213 deletions.
100 changes: 100 additions & 0 deletions api/src/main/java/org/openmrs/BaseFormRecordableOpenmrsData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* 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;

import org.apache.commons.lang3.StringUtils;
import org.openmrs.api.APIException;

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;

/**
* This is a super class to make a bridge between an OpenMrsObject and is position in the form.
*
* @since 2.4.0
*/
@MappedSuperclass
public abstract class BaseFormRecordableOpenmrsData extends BaseChangeableOpenmrsData implements FormRecordable {

protected static final String FORM_NAMESPACE_PATH_SEPARATOR = "^";

protected static final int FORM_NAMESPACE_PATH_MAX_LENGTH = 255;

@Column(name = "form_namespace_and_path")
protected String formNamespaceAndPath;

/**
* @see org.openmrs.FormRecordable#getFormFieldNamespace()
*/
@Override
public String getFormFieldNamespace() {
if (StringUtils.isNotBlank(formNamespaceAndPath)) {
//Only the path was specified
if (formNamespaceAndPath.startsWith(FORM_NAMESPACE_PATH_SEPARATOR)) {
return null;
}
return formNamespaceAndPath.substring(0, formNamespaceAndPath.indexOf(FORM_NAMESPACE_PATH_SEPARATOR));
}

return formNamespaceAndPath;
}

/**
* @see org.openmrs.FormRecordable#getFormFieldPath()
*/
@Override
public String getFormFieldPath() {
if (StringUtils.isNotBlank(formNamespaceAndPath)) {
//Only the namespace was specified
if (formNamespaceAndPath.endsWith(FORM_NAMESPACE_PATH_SEPARATOR)) {
return null;
}
return formNamespaceAndPath.substring(formNamespaceAndPath.indexOf(FORM_NAMESPACE_PATH_SEPARATOR) + 1);
}

return formNamespaceAndPath;
}

/**
* @see org.openmrs.FormRecordable#setFormField(String,String)
*/
@Override
public void setFormField(String namespace, String formFieldPath) {
if (namespace == null && formFieldPath == null) {
formNamespaceAndPath = null;
return;
}

String nsAndPathTemp = "";
if (StringUtils.isNotBlank(namespace) && StringUtils.isNotBlank(formFieldPath)) {
nsAndPathTemp = namespace + FORM_NAMESPACE_PATH_SEPARATOR + formFieldPath;
} else if (StringUtils.isNotBlank(namespace)) {
nsAndPathTemp = namespace + FORM_NAMESPACE_PATH_SEPARATOR;
} else if (StringUtils.isNotBlank(formFieldPath)) {
nsAndPathTemp = FORM_NAMESPACE_PATH_SEPARATOR + formFieldPath;
}

if (nsAndPathTemp.length() > FORM_NAMESPACE_PATH_MAX_LENGTH) {
throw new APIException("BaseFormRecordableOpenmrsData.namespaceAndPathTooLong", (Object[]) null);
}
if (StringUtils.countMatches(nsAndPathTemp, FORM_NAMESPACE_PATH_SEPARATOR) > 1) {
throw new APIException("BaseFormRecordableOpenmrsData.namespaceAndPathNotContainSeparator", (Object[]) null);
}

formNamespaceAndPath = nsAndPathTemp;
}

/**
* @return Returns the formNamespaceAndPath.
*/
public String getFormNamespaceAndPath() {
return formNamespaceAndPath;
}
}
3 changes: 2 additions & 1 deletion api/src/main/java/org/openmrs/Condition.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
*/
@Entity
@Table(name = "conditions")
public class Condition extends BaseChangeableOpenmrsData {
public class Condition extends BaseFormRecordableOpenmrsData {

private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -396,4 +396,5 @@ public boolean equals(Object o) {
}
return Objects.equals(endReason, conditionToBeChecked.endReason);
}

}
61 changes: 61 additions & 0 deletions api/src/main/java/org/openmrs/FormRecordable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* 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;

/**
* Defines the methods to make a bridge between an OpenMrsObject and is position in the form.
*
* @since 2.4.0
*/
public interface FormRecordable {

/**
* Gets the namespace for the form field that was used to capture the obs details in the form
*
* @return the namespace
* @since 2.4.0
* <strong>Should</strong> return the namespace for a form field that has no path
* <strong>Should</strong> return the correct namespace for a form field with a path
* <strong>Should</strong> return null if the namespace is not specified
*/
String getFormFieldNamespace();

/**
* Gets the path for the form field that was used to capture the obs details in the form
*
* @return the the form field path
* @since 2.4.0
* <strong>Should</strong> return the path for a form field that has no namespace
* <strong>Should</strong> return the correct path for a form field with a namespace
* <strong>Should</strong> return null if the path is not specified
*/
String getFormFieldPath();

/**
* Sets the namespace and path of the form field that was used to capture the obs details in the
* form.<br>
* <b>Note:</b> Namespace and formFieldPath together must not exceed 254 characters in length,
* form applications can subtract the length of their namespace from 254 to determine the
* maximum length they can use for a form field path.
*
* @param namespace the namespace of the form field
* @param formFieldPath the path of the form field
* @since 2.4.0
* <strong>Should</strong> set the underlying formNamespaceAndPath in the correct pattern
* <strong>Should</strong> reject a namepace containing the separator
* <strong>Should</strong> reject a path containing the separator
* <strong>Should</strong> reject a namepace and path combination longer than the max length
* <strong>Should</strong> not mark the obs as dirty when the value has not been changed
* <strong>Should</strong> mark the obs as dirty when the value has been changed
* <strong>Should</strong> mark the obs as dirty when the value is changed from a null to a non null value
* <strong>Should</strong> mark the obs as dirty when the value is changed from a non null to a null value
*/
void setFormField(String namespace, String formFieldPath);
}
98 changes: 7 additions & 91 deletions api/src/main/java/org/openmrs/Obs.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
*
* @see Encounter
*/
public class Obs extends BaseChangeableOpenmrsData {
public class Obs extends BaseFormRecordableOpenmrsData {

/**
* @since 2.1.0
Expand All @@ -87,10 +87,6 @@ public enum Status {

private static final Logger log = LoggerFactory.getLogger(Obs.class);

private static final String FORM_NAMESPACE_PATH_SEPARATOR = "^";

private static final int FORM_NAMESPACE_PATH_MAX_LENGTH = 255;

protected Integer obsId;

protected Concept concept;
Expand Down Expand Up @@ -149,8 +145,6 @@ public enum Status {

private Obs previousVersion;

private String formNamespaceAndPath;

private Boolean dirty = Boolean.FALSE;

private Interpretation interpretation;
Expand Down Expand Up @@ -1177,91 +1171,13 @@ public void setDateCreated(Date dateCreated) {
}

/**
* Gets the namespace for the form field that was used to capture the obs details in the form
*
* @return the namespace
* @since 1.11
* <strong>Should</strong> return the namespace for a form field that has no path
* <strong>Should</strong> return the correct namespace for a form field with a path
* <strong>Should</strong> return null if the namespace is not specified
*/
public String getFormFieldNamespace() {
if (StringUtils.isNotBlank(formNamespaceAndPath)) {
//Only the path was specified
if (formNamespaceAndPath.startsWith(FORM_NAMESPACE_PATH_SEPARATOR)) {
return null;
}
return formNamespaceAndPath.substring(0, formNamespaceAndPath.indexOf(FORM_NAMESPACE_PATH_SEPARATOR));
}

return formNamespaceAndPath;
}

/**
* Gets the path for the form field that was used to capture the obs details in the form
*
* @return the the form field path
* @since 1.11
* <strong>Should</strong> return the path for a form field that has no namespace
* <strong>Should</strong> return the correct path for a form field with a namespace
* <strong>Should</strong> return null if the path is not specified
*/
public String getFormFieldPath() {
if (StringUtils.isNotBlank(formNamespaceAndPath)) {
//Only the namespace was specified
if (formNamespaceAndPath.endsWith(FORM_NAMESPACE_PATH_SEPARATOR)) {
return null;
}
return formNamespaceAndPath.substring(formNamespaceAndPath.indexOf(FORM_NAMESPACE_PATH_SEPARATOR) + 1);
}

return formNamespaceAndPath;
}

/**
* Sets the namespace and path of the form field that was used to capture the obs details in the
* form.<br>
* <b>Note:</b> Namespace and formFieldPath together must not exceed 254 characters in length,
* form applications can subtract the length of their namespace from 254 to determine the
* maximum length they can use for a form field path.
*
* @param namespace the namespace of the form field
* @param formFieldPath the path of the form field
* @since 1.11
* <strong>Should</strong> set the underlying formNamespaceAndPath in the correct pattern
* <strong>Should</strong> reject a namepace containing the separator
* <strong>Should</strong> reject a path containing the separator
* <strong>Should</strong> reject a namepace and path combination longer than the max length
* <strong>Should</strong> not mark the obs as dirty when the value has not been changed
* <strong>Should</strong> mark the obs as dirty when the value has been changed
* <strong>Should</strong> mark the obs as dirty when the value is changed from a null to a non null value
* <strong>Should</strong> mark the obs as dirty when the value is changed from a non null to a null value
* @see org.openmrs.FormRecordable#setFormField(String,String)
*/
@Override
public void setFormField(String namespace, String formFieldPath) {
if (namespace == null && formFieldPath == null) {
markAsDirty(formNamespaceAndPath, null);
formNamespaceAndPath = null;
return;
}

String nsAndPathTemp = "";
if (StringUtils.isNotBlank(namespace) && StringUtils.isNotBlank(formFieldPath)) {
nsAndPathTemp = namespace + FORM_NAMESPACE_PATH_SEPARATOR + formFieldPath;
} else if (StringUtils.isNotBlank(namespace)) {
nsAndPathTemp = namespace + FORM_NAMESPACE_PATH_SEPARATOR;
} else if (StringUtils.isNotBlank(formFieldPath)) {
nsAndPathTemp = FORM_NAMESPACE_PATH_SEPARATOR + formFieldPath;
}

if (nsAndPathTemp.length() > FORM_NAMESPACE_PATH_MAX_LENGTH) {
throw new APIException("Obs.namespaceAndPathTooLong", (Object[]) null);
}
if (StringUtils.countMatches(nsAndPathTemp, FORM_NAMESPACE_PATH_SEPARATOR) > 1) {
throw new APIException("Obs.namespaceAndPathNotContainSeparator", (Object[]) null);
}

markAsDirty(this.formNamespaceAndPath, nsAndPathTemp);
formNamespaceAndPath = nsAndPathTemp;
String oldValue = formNamespaceAndPath;
super.setFormField(namespace, formFieldPath);
markAsDirty(oldValue, formNamespaceAndPath);
}

/**
Expand All @@ -1281,7 +1197,7 @@ public boolean isDirty() {
return dirty;
}

private void markAsDirty(Object oldValue, Object newValue) {
protected void markAsDirty(Object oldValue, Object newValue) {
//Should we ignore the case for Strings?
if (!isDirty() && obsId != null && !OpenmrsUtil.nullSafeEquals(oldValue, newValue)) {
dirty = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,19 @@
<dropForeignKeyConstraint baseTableName="test_order" constraintName="test_order_order_id_fk"/>
<addForeignKeyConstraint baseColumnNames="order_id" baseTableName="test_order" constraintName="test_order_order_id_fk" deferrable="false" initiallyDeferred="false" onDelete="CASCADE" onUpdate="NO ACTION" referencedColumnNames="order_id" referencedTableName="orders"/>
</changeSet>

<changeSet id="20200714-Trunk-5862" author="loliveira">
<preConditions onFail="MARK_RAN">
<not>
<columnExists tableName="conditions" columnName="form_namespace_and_path"/>
</not>
</preConditions>
<comment>Adding "form_namespace_and_path" column to conditions table</comment>
<addColumn tableName="conditions">
<column name="form_namespace_and_path" type="varchar(255)">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>

</databaseChangeLog>
Loading

0 comments on commit 3c34c43

Please sign in to comment.