Skip to content

Commit

Permalink
Merge pull request #16 from jembi/api-refactor
Browse files Browse the repository at this point in the history
Major refactoring of API
  • Loading branch information
rcrichton committed Sep 16, 2014
2 parents de801d9 + 5f91336 commit 26d79e8
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 589 deletions.
2 changes: 1 addition & 1 deletion api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.openmrs.module</groupId>
<artifactId>shr-contenthandler</artifactId>
<version>1.2.0</version>
<version>2.0.0</version>
</parent>

<artifactId>shr-contenthandler-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@
*/
package org.openmrs.module.shr.contenthandler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
Expand Down Expand Up @@ -53,31 +50,8 @@ public class UnstructuredDataHandler implements ContentHandler {
protected static final String UNSTRUCTURED_ATTACHMENT_CONCEPT_BASE_NAME = "Unstructured Attachment";
protected static final String UNSTRUCTURED_DATA_HANDLER_GLOBAL_PROP = "shr.contenthandler.unstructureddatahandler.key";

protected final String contentType;
protected final CodedValue typeCode;
protected final CodedValue formatCode;


/**
* Construct a new unstructured data handler that references content via content type
*/
public UnstructuredDataHandler(String contentType) {
this.contentType = contentType;
typeCode = formatCode = null;
}

/**
* Construct a new unstructured data handler that references content via type and format code
*/
public UnstructuredDataHandler(CodedValue typeCode, CodedValue formatCode) {
this.typeCode = typeCode;
this.formatCode = formatCode;
this.contentType = null;
}


/**
* @see ContentHandler#saveContent(Patient, Provider, EncounterRole, EncounterType, Content)
* @see ContentHandler#saveContent(String, Patient, Provider, EncounterRole, EncounterType, Content)
* @should create a new encounter object using the current time
* @should contain a complex obs containing the content
*/
Expand Down Expand Up @@ -115,11 +89,12 @@ private Encounter createEncounter(Patient patient, Map<EncounterRole, Set<Provid

private Obs createUnstructuredDataObs(Content content) {
Obs res = new Obs();
ComplexData cd = new ComplexData(buildTitle(), content);
ComplexData cd = new ComplexData(content.getContentId(), content);

res.setConcept(getUnstructuredAttachmentConcept(content.getFormatCode()));
res.setComplexData(cd);
res.setObsDatetime(new Date());
res.setAccessionNumber(content.getContentId());

return res;
}
Expand Down Expand Up @@ -156,8 +131,6 @@ private Concept buildUnstructuredAttachmentConcept(String name) {

return c;
}



/**
* @see ContentHandler#fetchContent(String)
Expand All @@ -166,123 +139,38 @@ private Concept buildUnstructuredAttachmentConcept(String name) {
* @should return null if the encounter isn't found
*/
@Override
public Content fetchContent(String encounterUuid) {
Encounter enc = Context.getEncounterService().getEncounterByUuid(encounterUuid);
if (enc==null)
return null;

List<Content> res = new LinkedList<Content>();
getContentFromEncounter(res, enc);
if (res.isEmpty())
return null;
return res.get(0);
}

/**
* @see ContentHandler#fetchContent(int)
* @should return a Content object for the encounter if found
* @should return null if the encounter doesn't contain an unstructured data obs
* @should return null if the encounter isn't found
*/
@Override
public Content fetchContent(int encounterId) {
Encounter enc = Context.getEncounterService().getEncounter(encounterId);
if (enc==null)
return null;

List<Content> res = new LinkedList<Content>();
getContentFromEncounter(res, enc);
if (res.isEmpty())
return null;
return res.get(0);
}


/**
* @see ContentHandler#queryEncounters(Patient, Date, Date)
* @should return a list of Content objects for all matching encounters
* @should only return Content objects that match the handler's content type
* @should return an empty list if no encounters with unstructured data obs are found
* @should handle null values for date from and to
*/
@Override
public List<Content> queryEncounters(Patient patient, Date from, Date to) {
return queryEncounters(patient, null, from, to);
}

/**
* @see ContentHandler#queryEncounters(Patient, EncounterType, Date, Date)
* @should return a list of Content objects for all matching encounters
* @should only return Content objects that match the handler's content type
* @should return an empty list if no encounters with unstructured data obs are found
* @should handle null values for date from and to
*/
@Override
public List<Content> queryEncounters(Patient patient, List<EncounterType> encounterTypes, Date from, Date to) {
List<Encounter> encs = Context.getEncounterService().getEncounters(
patient, null, from, to, null, encounterTypes, null, null, null, false
);
if (encs==null || encs.isEmpty())
return Collections.emptyList();

List<Content> res = new ArrayList<Content>(encs.size());

for (Encounter enc : encs) {
getContentFromEncounter(res, enc);
}

return res;
}

private void getContentFromEncounter(List<Content> dst, Encounter enc) {
public Content fetchContent(String contentId) {
ObsService os = Context.getObsService();
// TODO update this to search by accession number, this can be done from OpenMRS 1.12
List<Obs> obsList = os.getObservations(null, null, null, null, null, null, null, null, null, null, null, false);

for (Obs obs : enc.getAllObs()) {
if (obs.isComplex() && isConceptAnUnstructuredDataType(obs.getConcept())) {
for (Obs obs : obsList) {
if (obs.getAccessionNumber() != null && obs.getAccessionNumber().equals(contentId) && obs.isComplex() && isConceptAnUnstructuredDataType(obs.getConcept())) {
Obs complexObs = os.getComplexObs(obs.getObsId(), OpenmrsConstants.RAW_VIEW);
Object data = complexObs.getComplexData()!=null ? complexObs.getComplexData().getData() : null;

if (data==null || !(data instanceof Content)) {
log.warn("Unprocessable content found in unstructured data obs (obsId = " + obs.getId() + ")");
continue;
}

String contentTitle = contentType!=null ? (((Content)data).getContentType()) :
buildTypeFormatCodeTitle(((Content)data).getTypeCode(), ((Content)data).getFormatCode());

if (contentTitle.equals(buildTitle())) {
dst.add((Content)data);
} else {
return (Content) data;
}
}
}

return null;
}

private boolean isConceptAnUnstructuredDataType(Concept c) {
return c.getName().getName().startsWith(UNSTRUCTURED_ATTACHMENT_CONCEPT_BASE_NAME);
}

/**
* Build a title that's suitable for referencing the complex obs
*/
private String buildTitle() {
return contentType!=null ? contentType : buildTypeFormatCodeTitle(typeCode, formatCode);
}

protected static String buildTypeFormatCodeTitle(CodedValue typeCode, CodedValue formatCode) {
//Use the formatCode code as the title
return formatCode.getCode();
}

/**
* @see ContentHandler#cloneHandler()
* @should return an UnstructuredDataHandler instance with the same content type
*/
@Override
public UnstructuredDataHandler cloneHandler() {
if (contentType!=null) {
return new UnstructuredDataHandler(contentType);
} else {
return new UnstructuredDataHandler(typeCode, formatCode);
}
return new UnstructuredDataHandler();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public static enum CompressionFormat {
Z
}

private final String contentId;
private final CodedValue typeCode;
private final CodedValue formatCode;
private final String contentType;
Expand All @@ -88,14 +89,14 @@ public static enum CompressionFormat {
private final boolean payloadIsUrl;
private final String payload;


/**
* Creates a new Content object with a simple text payload. Good if the payload is an XML document for example.
*
* @see #Content(String, boolean, String, String, String, String, Representation, CompressionFormat, Locale)
* @see #Content(String, String, boolean, CodedValue, CodedValue, String, String, Representation, CompressionFormat, Locale)
*/
public Content(String payload, CodedValue typeCode, CodedValue formatCode, String contentType) {
this(payload, false, typeCode, formatCode, contentType, null, Representation.TXT, null, null);
public Content(String contentId, String payload, CodedValue typeCode, CodedValue formatCode, String contentType) {
this(contentId, payload, false, typeCode, formatCode, contentType, null, Representation.TXT, null, null);
}

/**
Expand All @@ -112,7 +113,8 @@ public Content(String payload, CodedValue typeCode, CodedValue formatCode, Strin
* @param compressionFormat (Nullable) The compression algorithm used by the content
* @param language (Nullable) The content language
*/
public Content(String payload, boolean payloadIsUrl, CodedValue typeCode, CodedValue formatCode, String contentType, String encoding, Representation representation, CompressionFormat compressionFormat, Locale language) {
public Content(String contentId, String payload, boolean payloadIsUrl, CodedValue typeCode, CodedValue formatCode, String contentType, String encoding, Representation representation, CompressionFormat compressionFormat, Locale language) {
this.contentId = contentId;
this.payload = payload;
this.typeCode = typeCode;
this.formatCode = formatCode;
Expand All @@ -130,6 +132,9 @@ public Content(String payload, boolean payloadIsUrl, CodedValue typeCode, CodedV
throw new InvalidRepresentationException("Binary payload must be Base64 encoded.");
}

public String getContentId() {
return contentId;
}

public CodedValue getTypeCode() {
return typeCode;
Expand Down Expand Up @@ -217,15 +222,15 @@ public byte[] getRawData() throws IOException {


/**
* Two Content objects are considered equal if their payloads are equal.
* Two Content objects are considered equal if their IDs are equal.
*/
@Override
public int compareTo(Content o) {
return payload.compareTo(o.payload);
return contentId.compareTo(o.contentId);
}

/**
* Two Content objects are considered equal if their payloads are equal.
* Two Content objects are considered equal if their IDs are equal.
*/
@Override
public boolean equals(Object obj) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
*/
package org.openmrs.module.shr.contenthandler.api;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

Expand Down Expand Up @@ -52,39 +50,10 @@ public interface ContentHandler {
/**
* Retrieve the content associated with the specified encounter uuid.
*
* @param encounterUuid The encounter identifier
* @param contentId The unique content identifier that was used to save the content
* @return The content in the content handler's format
*/
Content fetchContent(String encounterUuid);

/**
* Retrieve the content associated with the specified encounter id.
*
* @param encounterId The encounter identifier
* @return The content in the content handler's format
*/
Content fetchContent(int encounterId);

/**
* Retrieve a list of formatted encounters for a specified patient.
*
* @param patient The patient associated with the content
* @param from (nullable) The earliest encounter time to search for (inclusive)
* @param to (nullable) The latest encounter time to search for (exclusive)
* @return A list of encounters in the content handler's format
*/
List<Content> queryEncounters(Patient patient, Date from, Date to);

/**
* Retrieve a list of formatted encounters for a specified patient.
*
* @param patient The patient associated with the content
* @param encounterTypes A list of encounter types to search for
* @param from (nullable) The earliest encounter time to search for (inclusive)
* @param to (nullable) The latest encounter time to search for (exclusive)
* @return A list of encounters in the content handler's format
*/
List<Content> queryEncounters(Patient patient, List<EncounterType> encounterTypes, Date from, Date to);
Content fetchContent(String contentId);

/**
* Create a clone of this handler.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,23 @@ public interface ContentHandlerService extends OpenmrsService {
* @return The default unstructured data handler
* @should Return the default handler (UnstructuredDataHandler)
*/
ContentHandler getDefaultUnstructuredHandler(String contentType);
ContentHandler getDefaultUnstructuredHandler();

/**
* Get an instance of the default unstructured data handler for a specific type and format code.
* Set the default unstructured content handler
*
* @return The default unstructured data handler
* @should Return the default handler (UnstructuredDataHandler)
* @param defaultHandler The default unstructured content handler to set
*/
void setDefaultUnstructuredHandler(ContentHandler defaultHandler);

/**
* Fetches a registered content handler that is of the given class type.
*
* @param documentHandlerClass
* @return
* @should return a content handler for the given class
* @should return the null if no content handler was found
*/
ContentHandler getDefaultUnstructuredHandler(CodedValue typeCode, CodedValue formatCode);
ContentHandler getContentHandlerByClass(Class<? extends ContentHandler> documentHandlerClass);

}
Loading

0 comments on commit 26d79e8

Please sign in to comment.