/** * 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; }