/**
* 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 java.util.Collection;
import java.util.List;
import java.util.Set;
import org.openmrs.Concept;
import org.openmrs.EncounterType;
import org.openmrs.Field;
import org.openmrs.FieldAnswer;
import org.openmrs.FieldType;
import org.openmrs.Form;
import org.openmrs.FormField;
import org.openmrs.annotation.Authorized;
import org.openmrs.util.PrivilegeConstants;
import org.springframework.transaction.annotation.Transactional;
/**
* This service contains methods relating to Form, FormField, and Field. Methods relating to
* FieldType are in AdministrationService
*/
@Transactional
public interface FormService extends OpenmrsService {
/**
* Create or update the given Form in the database
*
* @param form the Form to save
* @return the Form that was saved
* @throws APIException
* @should save given form successfully
* @should update an existing form
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public Form saveForm(Form form) throws APIException;
/**
* @deprecated use {@link #saveForm(Form)}
*/
@Deprecated
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public Form createForm(Form form) throws APIException;
/**
* Get form by internal form identifier
*
* @param formId internal identifier
* @return requested form
* @throws APIException
* @should return null if no form exists with given formId
* @should return the requested form
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public Form getForm(Integer formId) throws APIException;
/**
* Get form by exact name match. If there are multiple forms with this name, then this returns
* the one with the highest version (sorted alphabetically)
*
* @param name exact name of the form to fetch
* @return requested form
* @throws APIException
* @should return null if no form has the exact form name
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public Form getForm(String name) throws APIException;
/**
* Get Form by its UUID
*
* @param uuid
* @return
* @should find object given valid uuid
* @should return null if no object found with given uuid
*/
@Transactional(readOnly = true)
public Form getFormByUuid(String uuid) throws APIException;
/**
* Get form by exact name & version match. If version is null, then this method behaves like
* {@link #getForm(String)}
*
* @param name exact name of the form to fetch
* @param version exact version of the form to fetch
* @return requested form
* @throws APIException
* @should get the specific version of the form with the given name
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public Form getForm(String name, String version) throws APIException;
/**
* Gets all Forms, including retired ones.
*
* @return all Forms, including retired ones
* @throws APIException
* @should return all forms including retired
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> getAllForms() throws APIException;
/**
* Gets all forms, possibly including retired ones
*
* @param includeRetired whether or not to return retired forms
* @return all forms, possibly including retired ones
* @throws APIException
* @should return retired forms if includeRetired is true
* @should not return retired forms if includeRetired is false
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> getAllForms(boolean includeRetired) throws APIException;
/**
* Gets all forms with name similar to the given name. (The precise fuzzy matching algorithm is
* not specified.)
*
* @param fuzzyName approximate name to match
* @param onlyLatestVersion whether or not to return only the latest version of each form (by
* name)
* @return forms with names similar to fuzzyName
* @should match forms with partial match on name
* @should only return one form per name if onlyLatestVersion is true
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> getForms(String fuzzyName, boolean onlyLatestVersion);
/**
* @deprecated use
* {@link #getForms(String, Boolean, Collection, Boolean, Collection, Collection, Collection)}
*/
@Deprecated
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> getForms(String partialNameSearch, Boolean published, Collection<EncounterType> encounterTypes,
Boolean retired, Collection<FormField> containingAnyFormField, Collection<FormField> containingAllFormFields);
/**
* Gets all forms that match all the (nullable) criteria
*
* @param partialNameSearch partial search of name
* @param published whether the form is published
* @param encounterTypes whether the form has any of these encounter types
* @param retired whether the form is retired
* @param containingAnyFormField includes forms that contain any of the specified FormFields
* @param containingAllFormFields includes forms that contain all of the specified FormFields
* @param fields whether the form has any of these fields. If a field is used more than once on
* a form, that form is returning more than once in this list
* @return All forms that match the criteria
* @should get multiple of the same form by field
* @should return duplicate form when given fields included in form multiple times
* @should only return published forms when given published equals true
* @should return both published and unpublished when given published is null
* @should match to forms with fuzzy partialNameSearch
* @should return forms with encounterType in given encounterTypes
* @should return unretired forms when retired equals false
* @should return retired forms when retired equals true
* @should return all forms including retired and unretired when retired is null
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> getForms(String partialNameSearch, Boolean published, Collection<EncounterType> encounterTypes,
Boolean retired, Collection<FormField> containingAnyFormField, Collection<FormField> containingAllFormFields,
Collection<Field> fields);
/**
* Same as
* {@link #getForms(String, Boolean, Collection, Boolean, Collection, Collection, Collection)}
* except that it returns an integer that is the size of the list that would be returned
*
* @see #getForms(String, Boolean, Collection, Boolean, Collection, Collection, Collection)
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public Integer getFormCount(String partialNameSearch, Boolean published, Collection<EncounterType> encounterTypes,
Boolean retired, Collection<FormField> containingAnyFormField, Collection<FormField> containingAllFormFields,
Collection<Field> fields);
/**
* Returns all published forms (not including retired ones)
*
* @return all published non-retired forms
* @throws APIException
* @should only return published forms that are not retired
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> getPublishedForms() throws APIException;
/**
* Get all forms. If publishedOnly is true, a form must be marked as 'published' to be included
* in the list
*
* @param publishedOnly
* @return List of forms
* @throws APIException
* @deprecated use {@link #getAllForms()} or {@link #getPublishedForms()}
*/
@Deprecated
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> getForms(boolean publishedOnly) throws APIException;
/**
* Get all forms. If publishedOnly is true, a form must be marked as 'published' to be included
* in the list. If includeRetired is true 'retired' must be set to false to be include in the
* list
*
* @param publishedOnly
* @param includeRetired
* @return List<Form> object of all matching forms
* @throws APIException
* @deprecated use {@link #getAllForms()} or {@link #getPublishedForms()} or
* {@link #getForms(String, Boolean, Collection, Boolean, Collection, Collection)}
*/
@Deprecated
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> getForms(boolean publishedOnly, boolean includeRetired) throws APIException;
/**
* Audit form, consolidate similar fields
*
* @throws APIException
* @should should merge fields with similar attributes
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public int mergeDuplicateFields() throws APIException;
/**
* Save changes to form
*
* @param form
* @throws APIException
* @deprecated use {@link #saveForm(Form)}
*/
@Deprecated
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void updateForm(Form form) throws APIException;
/**
* Duplicate this form and form_fields associated with this form
*
* @param form
* @return New duplicated form
* @throws APIException
* @should clear changed details and update creation details
* @should give a new uuid to the duplicated form
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public Form duplicateForm(Form form) throws APIException;
/**
* Retires the Form, leaving it in the database, but removing it from data entry screens
*
* @param form the Form to retire
* @param reason the retiredReason to set
* @throws APIException
* @should set the retired bit before saving
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void retireForm(Form form, String reason) throws APIException;
/**
* Unretires a Form that had previous been retired.
*
* @param form the Form to revive
* @throws APIException
* @should unset the retired bit before saving
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void unretireForm(Form form) throws APIException;
/**
* Completely remove a Form from the database. This is not reversible. It will fail if this form
* has already been used to create Encounters
*
* @param form
* @throws APIException
* @should delete given form successfully
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void purgeForm(Form form) throws APIException;
/**
* Completely remove a Form from the database. This is not reversible. !! WARNING: Calling this
* method with cascade=true can be very destructive !!
*
* @param form
* @param cascade whether or not to cascade delete all dependent objects (including encounters!)
* @throws APIException
* @should throw APIException if cascade is true
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void purgeForm(Form form, boolean cascade) throws APIException;
/**
* Delete form from database. This is included for troubleshooting and low-level system
* administration. Ideally, this method should <b>never</b> be called — <code>Forms</code>
* should be <em>retired</em> and not <em>deleted</em> altogether (since many foreign key
* constraints depend on forms, deleting a form would require deleting all traces, and any
* historical trail would be lost). This method only clears form roles and attempts to delete
* the form record. If the form has been included in any other parts of the database (through a
* foreign key), the attempt to delete the form will violate foreign key constraints and fail.
*
* @param form
* @throws APIException
* @deprecated use {@link #purgeForm(Form)}
*/
@Deprecated
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void deleteForm(Form form) throws APIException;
/**
* @deprecated use {@link #getAllFieldTypes()}
*/
@Deprecated
@Authorized(PrivilegeConstants.VIEW_FIELD_TYPES)
@Transactional(readOnly = true)
public List<FieldType> getFieldTypes() throws APIException;
/**
* Get all field types in the database including the retired ones
*
* @return list of all field types
* @throws APIException
* @should also get retired field types
*/
@Authorized(PrivilegeConstants.VIEW_FIELD_TYPES)
@Transactional(readOnly = true)
public List<FieldType> getAllFieldTypes() throws APIException;
/**
* Get all field types in the database with or without retired ones
*
* @param includeRetired true/false whether to include the retired field types
* @return list of all field types
* @throws APIException
* @should get all field types including retired when includeRetired equals true
* @should get all field types excluding retired when includeRetired equals false
*/
@Authorized(PrivilegeConstants.VIEW_FIELD_TYPES)
@Transactional(readOnly = true)
public List<FieldType> getAllFieldTypes(boolean includeRetired) throws APIException;
/**
* Get fieldType by internal identifier
*
* @param fieldTypeId Integer id of FieldType to get
* @return fieldType with given internal identifier
* @throws APIException
* @should return null when no field type matching given id
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FIELD_TYPES)
public FieldType getFieldType(Integer fieldTypeId) throws APIException;
/**
* Get FieldType by its UUID
*
* @param uuid
* @return
* @should find object given valid uuid
* @should return null if no object found with given uuid
*/
@Transactional(readOnly = true)
public FieldType getFieldTypeByUuid(String uuid) throws APIException;
/**
* @deprecated use {@link #getAllForms()}
*/
@Deprecated
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> getForms() throws APIException;
/**
* @deprecated use {@link #getFormsContainingConcept(Concept)}
*/
@Deprecated
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public Set<Form> getForms(Concept c) throws APIException;
/**
* Returns all forms that contain the given concept as a field in their schema. (includes
* retired forms)
*
* @param concept the concept to search for in forms
* @return forms containing the specified concept in their schema
* @throws APIException
* @should get forms with field matching given concept
* @should get all forms for concept
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> getFormsContainingConcept(Concept concept) throws APIException;
/**
* @deprecated use {@link Form#getFormFields()}
*/
@Deprecated
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<FormField> getFormFields(Form form) throws APIException;
/**
* Returns all FormFields in the database
*
* @return all FormFields in the database
* @throws APIException
* @should get all form fields including retired
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<FormField> getAllFormFields() throws APIException;
/**
* @return list of fields in the db matching part of search term
* @throws APIException
* @deprecated use {@link #getFields(String)}
*/
@Deprecated
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Field> findFields(String searchPhrase) throws APIException;
/**
* Find all Fields whose names are similar to or contain the given phrase. (The exact similarity
* algorithm is unspecified.) (includes retired fields)
*
* @param fuzzySearchPhrase
* @return Fields with names similar to or containing the given phrase
* @throws APIException
* @should get fields with name matching fuzzySearchPhrase at beginning
* @should get fields with name matching fuzzySearchPhrase at middle
* @should get fields with name matching fuzzySearchPhrase at end
* @should return fields in alphabetical order by name
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Field> getFields(String fuzzySearchPhrase) throws APIException;
/**
* @deprecated use {@link #getFieldsByConcept(Concept)}
*/
@Deprecated
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Field> findFields(Concept concept) throws APIException;
/**
* Finds all Fields that point to the given concept, including retired ones.
*
* @param concept the concept to search for in the Field table
* @return fields that point to the given concept
* @throws APIException
* @should get fields with concept matching given concept
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Field> getFieldsByConcept(Concept concept) throws APIException;
/**
* Fetches all Fields in the database, including retired ones
*
* @return all Fields
* @throws APIException
* @should get all fields including retired
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Field> getAllFields() throws APIException;
/**
* Fetches all Fields in the database, possibly including retired ones
*
* @param includeRetired whether or not to include retired Fields
* @return all Fields
* @throws APIException
* @should get all fields including retired when includeRetired is true
* @should get all fields excluding retired when includeRetired is false
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Field> getAllFields(boolean includeRetired) throws APIException;
/**
* Returns all Fields that match these (nullable) criteria
*
* @param forms on any of these Forms
* @param fieldTypes having any of these FieldTypes
* @param concepts for any of these Concepts
* @param tableNames for any of these table names
* @param attributeNames for any of these attribute names
* @param selectMultiple whether to return only select-multi fields
* @param containsAllAnswers fields with all the following answers
* @param containsAnyAnswer fields with any of the following answers
* @param retired only retired/unretired fields
* @return all Fields matching the given criteria
* @throws APIException
* @should get fields with form in given forms
* @should get fields with type in given fieldTypes
* @should get fields with concept in given concepts
* @should get fields with tableName in given tableNames
* @should get fields with attributeName in given attributeNames
* @should get fields with selectMultiple equals true when given selectMultiple equals true
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Field> getFields(Collection<Form> forms, Collection<FieldType> fieldTypes, Collection<Concept> concepts,
Collection<String> tableNames, Collection<String> attributeNames, Boolean selectMultiple,
Collection<FieldAnswer> containsAllAnswers, Collection<FieldAnswer> containsAnyAnswer, Boolean retired)
throws APIException;
/**
* @deprecated use {@link #getAllFields()}
*/
@Deprecated
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Field> getFields() throws APIException;
/**
* Gets a Field by internal database id
*
* @param fieldId the id of the Field to fetch
* @return the Field with the given id
* @throws APIException
* @should return null if no field exists with given fieldId
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public Field getField(Integer fieldId) throws APIException;
/**
* Get Field by its UUID
*
* @param uuid
* @return
* @should find object given valid uuid
* @should return null if no object found with given uuid
*/
@Transactional(readOnly = true)
public Field getFieldByUuid(String uuid) throws APIException;
/**
* Get FieldAnswer by its UUID
*
* @param uuid
* @return
* @should find object given valid uuid
* @should return null if no object found with given uuid
*/
@Transactional(readOnly = true)
public FieldAnswer getFieldAnswerByUuid(String uuid) throws APIException;
/**
* Creates or updates the given Field
*
* @param field the Field to save
* @return the Field that was saved
* @throws APIException
* @should save given field successfully
* @should update an existing field
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public Field saveField(Field field) throws APIException;
/**
* @deprecated use {@link #saveField(Field)}
*/
@Deprecated
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void createField(Field field) throws APIException;
/**
* @deprecated use {@link #saveField(Field)}
*/
@Deprecated
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void updateField(Field field) throws APIException;
/**
* Completely removes a Field from the database. Not reversible.
*
* @param field the Field to purge
* @throws APIException
* @should delete given field successfully
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void purgeField(Field field) throws APIException;
/**
* Completely removes a Field from the database. Not reversible. !! WARNING: calling this with
* cascade=true can be very destructive !!
*
* @param field the Field to purge
* @param cascade whether to cascade delete all FormFields pointing to this field
* @throws APIException
* @should throw APIException if cascade is true
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void purgeField(Field field, boolean cascade) throws APIException;
/**
* @deprecated use {@link #purgeField(Field)}
*/
@Deprecated
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void deleteField(Field field) throws APIException;
/**
* Gets a FormField by internal database id
*
* @param formFieldId the internal id to search on
* @return the FormField with the given id
* @throws APIException
* @should return null if no formField exists with given id
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public FormField getFormField(Integer formFieldId) throws APIException;
/**
* Get FormField by its UUID
*
* @param uuid
* @return
* @should find object given valid uuid
* @should return null if no object found with given uuid
*/
@Transactional(readOnly = true)
public FormField getFormFieldByUuid(String uuid) throws APIException;
/**
* Finds the FormField defined for this form/concept combination Calls
* {@link #getFormField(Form, Concept, Collection, boolean)} with an empty ignore list and with
* <code>force</code> set to false
*
* @param form Form that this concept was found on
* @param concept (question) on this form that is being requested
* @return Formfield for this concept on this form
* @throws APIException
* @see #getFormField(Form, Concept, Collection, boolean)
* @should get formField for given form and concept
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public FormField getFormField(Form form, Concept concept) throws APIException;
/**
* Finds the FormField defined for this form/concept combination while discounting any form
* field found in the <code>ignoreFormFields</code> collection This method was added when
* needing to relate observations to form fields during a display. The use case would be that
* you know a Concept for a obs, which was defined on a form (via a formField). You can relate
* the formFields to Concepts easily enough, but if a Form reuses a Concept in two separate
* FormFields you don't want to only associate that first formField with that concept. So, keep
* a running list of formFields you've seen and pass them back in here to rule them out.
*
* @param form Form that this concept was found on
* @param concept Concept (question) on this form that is being requested
* @param ignoreFormFields FormFields to ignore (aka already seen formfields)
* @param force if true and there are zero matches because all formFields were ignored (because
* of ignoreFormFields) than the first result is returned
* @return Formfield for this concept on this form
* @throws APIException
* @should get form fields by form and concept
* @should not fail with null ignoreFormFields argument
* @should simply return null for nonexistent concepts
* @should simply return null for nonexistent forms
* @should ignore formFields passed to ignoreFormFields
*/
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public FormField getFormField(Form form, Concept concept, Collection<FormField> ignoreFormFields, boolean force)
throws APIException;
/**
* Creates or updates the given FormField
*
* @param formField the FormField to save
* @return the formField that was just saved
* @throws APIException
* @should propagate save to the Field property on the given FormField
* @should save given formField successfully
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public FormField saveFormField(FormField formField) throws APIException;
/**
* @deprecated use {@link #saveFormField(FormField)}
*/
@Deprecated
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void createFormField(FormField formField) throws APIException;
/**
* @deprecated use {@link #saveFormField(FormField)}
*/
@Deprecated
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void updateFormField(FormField formField) throws APIException;
/**
* Completely removes the given FormField from the database. This is not reversible
*
* @param formField the FormField to purge
* @throws APIException
* @should delete the given form field successfully
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void purgeFormField(FormField formField) throws APIException;
/**
* @deprecated use {@link #purgeFormField(FormField)}
*/
@Deprecated
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public void deleteFormField(FormField formField) throws APIException;
/**
* @deprecated use
* {@link #getForms(String, Boolean, Collection, Boolean, Collection, Collection)}
* @see #getForms(String, Boolean, Collection, Boolean, Collection, Collection)
*/
@Deprecated
@Transactional(readOnly = true)
@Authorized(PrivilegeConstants.VIEW_FORMS)
public List<Form> findForms(String text, boolean includeUnpublished, boolean includeRetired);
/**
* Retires field
*
* @param field the Field to retire
* @return the Field that was retired
* @throws APIException
* @should set the retired bit before saving
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public Field retireField(Field field) throws APIException;
/**
* Unretires field
*
* @param field the Field to unretire
* @return the Field that was unretired
* @throws APIException
* @should unset the retired bit before saving
*/
@Authorized(PrivilegeConstants.MANAGE_FORMS)
public Field unretireField(Field field) throws APIException;
/**
* Saves the given field type to the database
*
* @param fieldType the field type to save
* @return the saved field type
* @throws APIException
* @should create new field type
* @should update existing field type
*/
@Authorized(PrivilegeConstants.MANAGE_FIELD_TYPES)
public FieldType saveFieldType(FieldType fieldType) throws APIException;
/**
* Deletes the given field type from the database. This should not be done. It is preferred to
* just retired this field type with #retireFieldType(FieldType)
*
* @param fieldType the field type to purge
* @throws APIException
* @should delete the given field type successfully
*/
@Authorized(PrivilegeConstants.PURGE_FIELD_TYPES)
public void purgeFieldType(FieldType fieldType) throws APIException;
}