Package org.openmrs.module.htmlformentry.element

Source Code of org.openmrs.module.htmlformentry.element.ObsSubmissionElement

package org.openmrs.module.htmlformentry.element;

import org.apache.commons.lang.StringUtils;
import org.openmrs.Concept;
import org.openmrs.ConceptAnswer;
import org.openmrs.ConceptClass;
import org.openmrs.ConceptDatatype;
import org.openmrs.ConceptNumeric;
import org.openmrs.Drug;
import org.openmrs.Location;
import org.openmrs.Obs;
import org.openmrs.Person;
import org.openmrs.Role;
import org.openmrs.api.context.Context;
import org.openmrs.module.htmlformentry.FormEntryContext;
import org.openmrs.module.htmlformentry.FormEntryContext.Mode;
import org.openmrs.module.htmlformentry.FormEntrySession;
import org.openmrs.module.htmlformentry.FormSubmissionError;
import org.openmrs.module.htmlformentry.HtmlFormEntryConstants;
import org.openmrs.module.htmlformentry.HtmlFormEntryService;
import org.openmrs.module.htmlformentry.HtmlFormEntryUtil;
import org.openmrs.module.htmlformentry.action.FormSubmissionControllerAction;
import org.openmrs.module.htmlformentry.comparator.OptionComparator;
import org.openmrs.module.htmlformentry.schema.ObsField;
import org.openmrs.module.htmlformentry.schema.ObsFieldAnswer;
import org.openmrs.module.htmlformentry.widget.CheckboxWidget;
import org.openmrs.module.htmlformentry.widget.ConceptSearchAutocompleteWidget;
import org.openmrs.module.htmlformentry.widget.DateTimeWidget;
import org.openmrs.module.htmlformentry.widget.DateWidget;
import org.openmrs.module.htmlformentry.widget.DropdownWidget;
import org.openmrs.module.htmlformentry.widget.DynamicAutocompleteWidget;
import org.openmrs.module.htmlformentry.widget.ErrorWidget;
import org.openmrs.module.htmlformentry.widget.NumberFieldWidget;
import org.openmrs.module.htmlformentry.widget.Option;
import org.openmrs.module.htmlformentry.widget.PersonStubWidget;
import org.openmrs.module.htmlformentry.widget.RadioButtonsWidget;
import org.openmrs.module.htmlformentry.widget.RemoteJsonAutocompleteWidget;
import org.openmrs.module.htmlformentry.widget.SingleOptionWidget;
import org.openmrs.module.htmlformentry.widget.TextFieldWidget;
import org.openmrs.module.htmlformentry.widget.TimeWidget;
import org.openmrs.module.htmlformentry.widget.ToggleWidget;
import org.openmrs.module.htmlformentry.widget.UploadWidget;
import org.openmrs.module.htmlformentry.widget.Widget;
import org.openmrs.obs.ComplexData;
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.util.OpenmrsUtil;
import org.openmrs.web.WebConstants;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;

/**
* Holds the widgets used to represent a specific Observation, and serves as both the
* HtmlGeneratorElement and the FormSubmissionControllerAction for the Observation.
*/
public class ObsSubmissionElement implements HtmlGeneratorElement, FormSubmissionControllerAction {
 
  private String id;

    private String clazz;

  private Concept concept;
 
  private String valueLabel;
 
  private Widget valueWidget;
 
  private String defaultValue;
 
  private boolean showUnits = false;

    private String unitsCode;

    private String unitsCssClass = "units";
 
  private String dateLabel;
 
  private DateWidget dateWidget;
 
  private String accessionNumberLabel;
 
  private TextFieldWidget accessionNumberWidget;

  private String commentFieldLabel;

  private TextFieldWidget commentFieldWidget;

  private ErrorWidget errorWidget;
 
  private boolean allowFutureDates = false;
 
  private Concept answerConcept;
 
  private List<Concept> conceptAnswers = new ArrayList<Concept>();
 
  private List<Number> numericAnswers = new ArrayList<Number>();
 
  private List<String> textAnswers = new ArrayList<String>();
 
  private List<String> answerLabels = new ArrayList<String>();
 
  private String answerLabel;
 
  private Obs existingObs; // in edit mode, this allows submission to check whether the obs has been modified or not
 
  private List<Obs> existingObsList;  // used by the dynamic autocomplete which allows the selection of multiple answers
 
  private boolean required;
 
  //these are for conceptSelects:
  private List<Concept> concepts = null; //possible concepts
 
  private List<String> conceptLabels = null; //the text to show for possible concepts
 
  private String answerSeparator = null;

    // these are for location and provider options

    private List<Option> locationOptions = new ArrayList<Option>();

    private Map<Object, String> whenValueThenDisplaySection = new LinkedHashMap<Object, String>();

    private Map<Object, String> whenValueThenJavascript = new LinkedHashMap<Object, String>();

    private Map<Object, String> whenValueElseJavascript = new LinkedHashMap<Object, String>();

    private Boolean isLocationObs; // determines whether the valueText for this obs should be a location_id;

  public ObsSubmissionElement(FormEntryContext context, Map<String, String> parameters) {
    String conceptId = parameters.get("conceptId");
    String conceptIds = parameters.get("conceptIds");
    defaultValue = parameters.get("defaultValue");
    if (parameters.get("answerSeparator") != null) {
      answerSeparator = parameters.get("answerSeparator");
        }
   
    if (conceptId != null && conceptIds != null)
      throw new RuntimeException("You can't use conceptId and conceptIds in the same tag!");
    else if (conceptId == null && conceptIds == null)
      throw new RuntimeException("You must include either conceptId or conceptIds in an obs tag");
   
    if (conceptId != null) {
      concept = HtmlFormEntryUtil.getConcept(conceptId);
      if (concept == null)
        throw new IllegalArgumentException("Cannot find concept for value " + conceptId
                + " in conceptId attribute value. Parameters: " + parameters);
    } else {
      concepts = new ArrayList<Concept>();
      for (StringTokenizer st = new StringTokenizer(conceptIds, ","); st.hasMoreTokens();) {
        String s = st.nextToken().trim();
        Concept concept = HtmlFormEntryUtil.getConcept(s);
        if (concept == null)
          throw new IllegalArgumentException("Cannot find concept for value " + s
                  + " in conceptIds attribute value. Parameters: " + parameters);
        concepts.add(concept);
      }
      if (concepts.size() == 0)
        throw new IllegalArgumentException(
                "You must provide some valid conceptIds for the conceptIds attribute. Parameters: " + parameters);
    }
   
    // test to make sure the answerConceptId, if it exists, is valid
    String answerConceptId = parameters.get("answerConceptId");
    if (StringUtils.isNotBlank(answerConceptId)) {
      if (HtmlFormEntryUtil.getConcept(answerConceptId) == null)
        throw new IllegalArgumentException("Cannot find concept for value " + answerConceptId
                + " in answerConceptId attribute value. Parameters: " + parameters);
    }
   
    // test to make sure the answerConceptIds, if they exist, are valid
    String answerConceptIds = parameters.get("answerConceptIds");
    if (StringUtils.isNotBlank(answerConceptIds)) {
      for (StringTokenizer st = new StringTokenizer(answerConceptIds, ","); st.hasMoreTokens();) {
        String s = st.nextToken().trim();
        Concept concept = HtmlFormEntryUtil.getConcept(s);
        if (concept == null)
          throw new IllegalArgumentException("Cannot find concept for value " + s
                  + " in answerConceptIds attribute value. Parameters: " + parameters);
      }
    }
   
    if ("true".equals(parameters.get("allowFutureDates")))
      allowFutureDates = true;
    if ("true".equals(parameters.get("required"))) {
      required = true;
    }
    if (parameters.get("id") != null) {
      id = parameters.get("id");
        }
        if (parameters.get("class") !=null) {
            clazz = parameters.get("class");
        }

        isLocationObs = "location".equals(parameters.get("style"));

    prepareWidgets(context, parameters);
  }


    private Widget buildDropdownWidget(Integer size){
        Widget dropdownWidget = new DropdownWidget(size);
        if(size==1 || !required){
            // show an empty option when size =1, even if required =true
            ((DropdownWidget) dropdownWidget).addOption(new Option());
        }
        return dropdownWidget;
    }
  private void prepareWidgets(FormEntryContext context, Map<String, String> parameters) {
    String userLocaleStr = Context.getLocale().toString();
    try {
      if (answerConcept == null)
        answerConcept = HtmlFormEntryUtil.getConcept(parameters.get("answerConceptId"));
    }
    catch (Exception ex) {}
        Integer size = 1;
        try {
            size = Integer.valueOf(parameters.get("size"));
        }catch (Exception ex) {}
    if (context.getCurrentObsGroupConcepts() != null && context.getCurrentObsGroupConcepts().size() > 0) {
      existingObs = context.getObsFromCurrentGroup(concept, answerConcept);
    } else if (concept != null) {
      if (concept.getDatatype().isBoolean() && "checkbox".equals(parameters.get("style"))) {
        // since a checkbox has one value we need to look for an exact
        // match for that value
        if ("false".equals(parameters.get("value"))) {
          existingObs = context.removeExistingObs(concept, false);
        } else {
          // if not 'false' we treat as 'true'
          existingObs = context.removeExistingObs(concept, true);
        }
            // if we use 'checkbox' with numeric values, first find existing obs for each answer
      }else if (concept.getDatatype().isNumeric() && "checkbox".equals(parameters.get("style"))){
                String numericAns = parameters.get("answer");
                existingObs = context.removeExistingObs(concept, numericAns);
                //for dynamicAutocomplete if selectMulti is true
      } else if ("autocomplete".equals(parameters.get("style")) && "true".equals(parameters.get("selectMulti"))) {
        existingObsList = context.removeExistingObs(concept);
      } else {
        existingObs = context.removeExistingObs(concept, answerConcept);
      }
    } else {
      existingObs = context.removeExistingObs(concepts, answerConcept);
    }
   
    errorWidget = new ErrorWidget();
    context.registerWidget(errorWidget);
   
    if (parameters.containsKey("labelNameTag")) {
      if (parameters.get("labelNameTag").equals("default"))
        if (concepts != null)
          valueLabel = answerConcept.getBestName(Context.getLocale()).getName();
        else
          valueLabel = concept.getBestName(Context.getLocale()).getName();
      else
        throw new IllegalArgumentException("Name tags other than 'default' not yet implemented");
    } else if (parameters.containsKey("labelText")) {
      valueLabel = parameters.get("labelText");
    } else if (parameters.containsKey("labelCode")) {
      valueLabel = context.getTranslator().translate(userLocaleStr, parameters.get("labelCode"));
    } else {
      if (concepts != null)
        valueLabel = answerConcept.getBestName(Context.getLocale()).getName();
      else
        valueLabel = "";
    }
    if (parameters.get("answerLabels") != null) {
      answerLabels = Arrays.asList(parameters.get("answerLabels").split(","));
    }
    if (parameters.get("answerCodes") != null) {
      String[] split = parameters.get("answerCodes").split(",");
      for (String s : split) {
        answerLabels.add(context.getTranslator().translate(userLocaleStr, s));
      }
    }
    if (concepts != null) {
      conceptLabels = new ArrayList<String>();
      if (parameters.get("conceptLabels") != null)
        conceptLabels = Arrays.asList(parameters.get("conceptLabels").split(","));
      if (conceptLabels.size() != 0 && (conceptLabels.size() != concepts.size()))
        throw new IllegalArgumentException(
                "If you want to use the conceptLabels attribute, you must to provide the same number of conceptLabels as there are conceptIds.  Parameters: "
                        + parameters);
      if ("radio".equals(parameters.get("style"))) {
        valueWidget = new RadioButtonsWidget();
        if (answerSeparator != null) {
          ((RadioButtonsWidget) valueWidget).setAnswerSeparator(answerSeparator);
                }
      } else { // dropdown
        valueWidget =buildDropdownWidget(size);
      }
      for (int i = 0; i < concepts.size(); ++i) {
        Concept c = concepts.get(i);
        String label = null;
        if (conceptLabels != null && i < conceptLabels.size()) {
          label = conceptLabels.get(i);
        } else {
          label = c.getBestName(Context.getLocale()).getName();
        }
        ((SingleOptionWidget) valueWidget).addOption(new Option(label, c.getConceptId().toString(), false));
      }
      if (existingObs != null) {
        valueWidget.setInitialValue(existingObs.getConcept());
      } else if (defaultValue != null && Mode.ENTER.equals(context.getMode())) {
        Concept initialValue = HtmlFormEntryUtil.getConcept(defaultValue);
        if (initialValue == null) {
          throw new IllegalArgumentException("Invalid default value. Cannot find concept: " + defaultValue);
        }
        valueWidget.setInitialValue(initialValue);
      }
      answerLabel = getValueLabel();
    } else {

      // Obs of datatypes date, time, and datetime support the attributes
      // defaultDatetime. Make sure this date format string matches the
      // format documented at
      // https://wiki.openmrs.org/display/docs/HTML+Form+Entry+Module+HTML+Reference#HTMLFormEntryModuleHTMLReference-%3Cobs%3E
      // See <obs> section, attributes defaultDatetime and
      // defaultObsDatetime
      String defaultDatetimeFormat = "yyyy-MM-dd-HH-mm";

      if (concept.getDatatype().isNumeric()) {
        if (parameters.get("answers") != null) {
          try {
            for (StringTokenizer st = new StringTokenizer(parameters.get("answers"), ", "); st.hasMoreTokens();) {
              Number answer = Double.valueOf(st.nextToken());
              numericAnswers.add(answer);
            }
          }
          catch (Exception ex) {
            throw new RuntimeException("Error in answer list for concept " + concept.getConceptId() + " ("
                    + ex.toString() + "): " + conceptAnswers);
          }
        }
        ConceptNumeric cn;
                if (concept instanceof ConceptNumeric) {
                    cn = (ConceptNumeric) concept;
                } else {
                    cn = Context.getConceptService().getConceptNumeric(concept.getConceptId());
                }
        // added to avoid creating this widget when a checkbox is needed
                if (numericAnswers.size() == 0) {
                    if (!"checkbox".equals(parameters.get("style"))) {
                        valueWidget = new NumberFieldWidget(cn, parameters.get("size"));
                    } else {
                        // render CheckboxWidgets for <obs> tag with numeric datatype;
                        // i.e. <obs conceptId="1234" answer="8" answerLabel="Eight" style="checkbox"/>
                        if (parameters.get("answer") != null) {
                            try {
                                Number number = Double.valueOf(parameters.get("answer"));
                                numericAnswers.add(number);
                                answerLabel = parameters.get("answerLabel");
                                if (number != null) {
                                    valueWidget = new CheckboxWidget(answerLabel, number.toString());
                                }

                            } catch (Exception ex) {
                                throw new RuntimeException("Error in answer for concept " + concept.getConceptId() + " ("
                                        + ex.toString() + "): ");
                            }
                        }
                    }
                } else {
          if ("radio".equals(parameters.get("style"))) {
            valueWidget = new RadioButtonsWidget();
            if (answerSeparator != null) {
              ((RadioButtonsWidget) valueWidget).setAnswerSeparator(answerSeparator);
                        }
          } else { // dropdown
                        valueWidget = buildDropdownWidget(size);
          }
          // need to make sure we have the initialValue too
          Number lookFor = existingObs == null ? null : existingObs.getValueNumeric();
          for (int i = 0; i < numericAnswers.size(); ++i) {
            Number n = numericAnswers.get(i);
            if (lookFor != null && lookFor.equals(n))
              lookFor = null;
            String label = null;
            if (answerLabels != null && i < answerLabels.size()) {
              label = answerLabels.get(i);
            } else {
              label = n.toString();
            }
            ((SingleOptionWidget) valueWidget).addOption(new Option(label, n.toString(), false));
          }
          // if lookFor is still non-null, we need to add it directly as
          // an option:
          if (lookFor != null)
            ((SingleOptionWidget) valueWidget)
                    .addOption(new Option(lookFor.toString(), lookFor.toString(), true));
        }

        if (valueWidget != null) {
          boolean isPrecise = cn != null ? cn.isPrecise() : true; // test data is missing concept numerics
          Number initialValue = null;

          if (existingObs != null && existingObs.getValueNumeric() != null) {
            // for non-precise numeric obs, initial value should be rendered as an integer
            initialValue = isPrecise ? ((Number) existingObs.getValueNumeric()) : existingObs.getValueNumeric().intValue();
          } else if (defaultValue != null && Mode.ENTER.equals(context.getMode())) {
            try {
              initialValue = isPrecise ? ((Number) Double.valueOf(defaultValue)) : Integer.valueOf(defaultValue);
            } catch (NumberFormatException e) {
              throw new IllegalArgumentException("Default value " + defaultValue + " is not a valid " + (isPrecise ? "double" : "integer"), e);
            }
          }
          valueWidget.setInitialValue(initialValue);
        }

      } else if (concept.isComplex()) {
        valueWidget = new UploadWidget();
        String lookFor = existingObs == null ? null : existingObs.getValueComplex();
        Obs initialValue = null;
        if (lookFor != null) {
          initialValue = existingObs;
        }
        valueWidget.setInitialValue(initialValue);
      } else if (concept.getDatatype().isText()) {

        String initialValue = null;
        if (defaultValue != null && Mode.ENTER.equals(context.getMode())) {
          initialValue = defaultValue;
        }
        if (existingObs != null) {
          initialValue = existingObs.getValueText();
        }

        if (parameters.get("answers") != null) {
          try {
            for (StringTokenizer st = new StringTokenizer(parameters.get("answers"), ","); st.hasMoreTokens();) {
              textAnswers.add(st.nextToken());
            }
          }
          catch (Exception ex) {
            throw new RuntimeException("Error in answer list for concept " + concept.getConceptId() + " ("
                    + ex.toString() + "): " + conceptAnswers);
          }
        }

                // configure the special obs type that allows selection of a location (the location_id PK is stored as the valueText)
        if (isLocationObs) {

                    valueWidget = new DropdownWidget();
                    // if "answerLocationTags" attribute is present try to get locations by tags
                    List<Location> locationList = HtmlFormEntryUtil.getLocationsByTags(HtmlFormEntryConstants.ANSWER_LOCATION_TAGS, parameters);
                    if ((locationList == null) ||
                            (locationList != null && locationList.size()<1)){
                        // if no locations by tags are found then get all locations
                        locationList = Context.getLocationService().getAllLocations();
                    }

                    for (Location location : locationList) {
                            String label = HtmlFormEntryUtil.format(location);
                            Option option = new Option(label, location.getId().toString(), location.getId().toString().equals(initialValue));
                            locationOptions.add(option);
                       }
                    Collections.sort(locationOptions, new OptionComparator());

                    // if initialValueIsSet=false, no initial/default location, hence this shows the 'select input' field as first option
                    boolean initialValueIsSet = !(initialValue == null);
                    ((DropdownWidget)valueWidget).addOption(new Option(Context.getMessageSourceService().getMessage("htmlformentry.chooseALocation"),"",!initialValueIsSet));
                    if (!locationOptions.isEmpty()) {
                        for(Option option: locationOptions)
                            ((DropdownWidget)valueWidget).addOption(option);
                    }

        } else if ("person".equals(parameters.get("style"))) {
         
          List<PersonStub> options = new ArrayList<PersonStub>();
                    List<Option> personOptions = new ArrayList<Option>();
         
          // If specific persons are specified, display only those persons in order
          String personsParam = (String) parameters.get("persons");
          if (personsParam != null) {
            for (String s : personsParam.split(",")) {
              Person p = HtmlFormEntryUtil.getPerson(s);
              if (p == null) {
                throw new RuntimeException("Cannot find Person: " + s);
              }
              options.add(new PersonStub(p));
            }
          }
         
          // Only if specific person ids are not passed in do we get by user Role
          if (options.isEmpty()) {
           
            List<PersonStub> users = new ArrayList<PersonStub>();
           
            // If the "role" attribute is passed in, limit to users with this role
            if (parameters.get("role") != null) {
              Role role = Context.getUserService().getRole((String) parameters.get("role"));
              if (role == null) {
                throw new RuntimeException("Cannot find role: " + parameters.get("role"));
              } else {
                users = Context.getService(HtmlFormEntryService.class).getUsersAsPersonStubs(role.getRole());
              }
            }

            // Otherwise, limit to users with the default OpenMRS PROVIDER role,
            else {
              String defaultRole = OpenmrsConstants.PROVIDER_ROLE;
              Role role = Context.getUserService().getRole(defaultRole);
              if (role != null) {
                users = Context.getService(HtmlFormEntryService.class).getUsersAsPersonStubs(role.getRole());
              }
              // If this role isn't used, default to all Users
              if (users.isEmpty()) {
                users = Context.getService(HtmlFormEntryService.class).getUsersAsPersonStubs(null);
              }
            }
            options.addAll(users);
            //              sortOptions = true;
          }

          valueWidget = new PersonStubWidget(options);

        } else {
          if (textAnswers.size() == 0) {
            Integer rows = null;
            Integer cols = null;
            try {
              rows = Integer.valueOf(parameters.get("rows"));
            }
            catch (Exception ex) {}
            try {
              cols = Integer.valueOf(parameters.get("cols"));
            }
            catch (Exception ex) {}
            if (rows != null || cols != null || "textarea".equals(parameters.get("style"))) {
              valueWidget = new TextFieldWidget(rows, cols);
            } else {
              Integer textFieldSize = null;
              try {
                                textFieldSize = Integer.valueOf(parameters.get("size"));
              }
              catch (Exception ex) {}
              valueWidget = new TextFieldWidget(textFieldSize);
            }
                        ((TextFieldWidget) valueWidget).setPlaceholder(parameters.get("placeholder"));
                    } else {
            if ("radio".equals(parameters.get("style"))) {
              valueWidget = new RadioButtonsWidget();
              if (answerSeparator != null) {
                ((RadioButtonsWidget) valueWidget).setAnswerSeparator(answerSeparator);
                            }
            } else { // dropdown
              valueWidget =buildDropdownWidget(size);
            }
            // need to make sure we have the initialValue too
            String lookFor = existingObs == null ? null : existingObs.getValueText();
            for (int i = 0; i < textAnswers.size(); ++i) {
              String s = textAnswers.get(i);
              if (lookFor != null && lookFor.equals(s))
                lookFor = null;
              String label = null;
              if (answerLabels != null && i < answerLabels.size()) {
                label = answerLabels.get(i);
              } else {
                label = s;
              }
              ((SingleOptionWidget) valueWidget).addOption(new Option(label, s, false));
            }
            // if lookFor is still non-null, we need to add it directly
            // as an option:
            if (lookFor != null)
              ((SingleOptionWidget) valueWidget).addOption(new Option(lookFor, lookFor, true));
          }
        }

        if (initialValue != null) {
          if (isLocationObs) {
            Location l = HtmlFormEntryUtil.getLocation(initialValue, context);
            if (l == null) {
              throw new RuntimeException("Cannot find Location: " + initialValue);
            }
            valueWidget.setInitialValue(l);
          } else if ("person".equals(parameters.get("style"))) {
            Person p = HtmlFormEntryUtil.getPerson(initialValue);
            if (p == null) {
              throw new RuntimeException("Cannot find Person: " + initialValue);
            }
            valueWidget.setInitialValue(new PersonStub(p));
          } else {
            valueWidget.setInitialValue(initialValue);
          }
        }
      } else if (concept.getDatatype().isCoded()) {
        if (parameters.get("answerConceptIds") != null) {
          try {
            for (StringTokenizer st = new StringTokenizer(parameters.get("answerConceptIds"), ","); st
                    .hasMoreTokens();) {
              Concept c = HtmlFormEntryUtil.getConcept(st.nextToken());
              if (c == null)
                throw new RuntimeException("Cannot find concept " + st.nextToken());
              conceptAnswers.add(c);
            }
          }
          catch (Exception ex) {
            throw new RuntimeException("Error in answer list for concept " + concept.getConceptId() + " ("
                    + ex.toString() + "): " + conceptAnswers);
          }
        } else if (parameters.get("answerClasses") != null && !"autocomplete".equals(parameters.get("style"))) {
          try {
            for (StringTokenizer st = new StringTokenizer(parameters.get("answerClasses"), ","); st
                    .hasMoreTokens();) {
              String className = st.nextToken().trim();
              ConceptClass cc = Context.getConceptService().getConceptClassByName(className);
              if (cc == null) {
                throw new RuntimeException("Cannot find concept class " + className);
              }
              conceptAnswers.addAll(Context.getConceptService().getConceptsByClass(cc));
            }
            Collections.sort(conceptAnswers, conceptNameComparator);
          }
          catch (Exception ex) {
            throw new RuntimeException("Error in answer class list for concept " + concept.getConceptId() + " ("
                    + ex.toString() + "): " + conceptAnswers);
          }
        }
       
        if (answerConcept != null) {
          // if there's also an answer concept specified, this is a single
          // checkbox
          answerLabel = parameters.get("answerLabel");
          if (answerLabel == null) {
            String answerCode = parameters.get("answerCode");
            if (answerCode != null) {
              answerLabel = context.getTranslator().translate(userLocaleStr, answerCode);
            } else {
              answerLabel = answerConcept.getBestName(Context.getLocale()).getName();
            }
          }
          valueWidget = new CheckboxWidget(answerLabel, answerConcept.getConceptId().toString());
          if (existingObsList != null && !existingObsList.isEmpty()) {
            for (int i = 0; i < existingObsList.size(); i++) {
              ((DynamicAutocompleteWidget)valueWidget).addInitialValue(existingObsList.get(i).getValueCoded());
            }
          } else if (existingObs != null) {
            valueWidget.setInitialValue(existingObs.getValueCoded());
          } else if (defaultValue != null && Mode.ENTER.equals(context.getMode())) {
            Concept initialValue = HtmlFormEntryUtil.getConcept(defaultValue);
            if (initialValue == null) {
              throw new IllegalArgumentException("Invalid default value. Cannot find concept: " + defaultValue);
            }
            if (!answerConcept.equals(initialValue)) {
              throw new IllegalArgumentException("Invalid default value: " + defaultValue
                      + ". The only allowed answer is: " + answerConcept.getId());
            }
            valueWidget.setInitialValue(initialValue);
          }
        } else if ("true".equals(parameters.get("multiple"))) {
          // if this is a select-multi, we need a group of checkboxes
          throw new RuntimeException("Multi-select coded questions are not yet implemented");
        } else {
          // allow selecting one of multiple possible coded values
         
          // if no answers are specified explicitly (by conceptAnswers or conceptClasses), get them from concept.answers.
          if (!parameters.containsKey("answerConceptIds") && !parameters.containsKey("answerClasses") && !parameters.containsKey("answerDrugs")) {
            conceptAnswers = new ArrayList<Concept>();
            for (ConceptAnswer ca : concept.getAnswers(false)) {
              conceptAnswers.add(ca.getAnswerConcept());
            }
            Collections.sort(conceptAnswers, conceptNameComparator);
          }
         
          if ("autocomplete".equals(parameters.get("style"))) {
            List<ConceptClass> cptClasses = new ArrayList<ConceptClass>();
            if (parameters.get("answerClasses") != null) {
              for (StringTokenizer st = new StringTokenizer(parameters.get("answerClasses"), ","); st
                      .hasMoreTokens();) {
                String className = st.nextToken().trim();
                ConceptClass cc = Context.getConceptService().getConceptClassByName(className);
                cptClasses.add(cc);
              }
            }
            if ((conceptAnswers == null || conceptAnswers.isEmpty())
                    && (cptClasses == null || cptClasses.isEmpty())) {
              throw new RuntimeException(
                      "style \"autocomplete\" but there are no possible answers. Looked for answerConcepts and answerClasses attributes, and answers for concept "
                              + concept.getConceptId());
            }
            if ("true".equals(parameters.get("selectMulti"))) {
              valueWidget = new DynamicAutocompleteWidget(conceptAnswers, cptClasses);
                        }
                        else {
                valueWidget = new ConceptSearchAutocompleteWidget(conceptAnswers, cptClasses);
                        }
                    } else if (parameters.get("answerDrugs") != null) {
                        // we support searching through all drugs via AJAX
                        RemoteJsonAutocompleteWidget widget = new RemoteJsonAutocompleteWidget("/" + WebConstants.WEBAPP_NAME + "/module/htmlformentry/drugSearch.form");
                        widget.setValueTemplate("Drug:{{id}}");
                        if (parameters.get("displayTemplate") != null) {
                            widget.setDisplayTemplate(parameters.get("displayTemplate"));
                        } else {
                            widget.setDisplayTemplate("{{name}}");
                        }
                        if (existingObs != null && existingObs.getValueDrug() != null) {
                            widget.setInitialValue(new Option(existingObs.getValueDrug().getName(), existingObs.getValueDrug().getDrugId().toString(), true));
                        }
                        valueWidget = widget;

                    } else {
                  // Show Radio Buttons if specified, otherwise default to Drop
            // Down
            boolean isRadio = "radio".equals(parameters.get("style"));
            if (isRadio) {
              valueWidget = new RadioButtonsWidget();
              if (answerSeparator != null) {
                ((RadioButtonsWidget) valueWidget).setAnswerSeparator(answerSeparator);
                            }
            } else {
              valueWidget = buildDropdownWidget(size);
            }
            for (int i = 0; i < conceptAnswers.size(); ++i) {
              Concept c = conceptAnswers.get(i);
              String label = null;
              if (answerLabels != null && i < answerLabels.size()) {
                label = answerLabels.get(i);
              } else {
                label = c.getBestName(Context.getLocale()).getName();
              }
              ((SingleOptionWidget) valueWidget).addOption(new Option(label, c.getConceptId().toString(),
                      false));
            }
          }
          if (existingObsList != null && !existingObsList.isEmpty()) {
            for (int i = 0; i < existingObsList.size(); i++) {
              ((DynamicAutocompleteWidget)valueWidget).addInitialValue(existingObsList.get(i).getValueCoded());
            }
          }
          if (existingObs != null) {
                        if (existingObs.getValueDrug() != null) {
                            valueWidget.setInitialValue(existingObs.getValueDrug());
                        } else {
                            valueWidget.setInitialValue(existingObs.getValueCoded());
                        }
                    } else if (defaultValue != null && Mode.ENTER.equals(context.getMode())) {
            Concept initialValue = HtmlFormEntryUtil.getConcept(defaultValue);
            if (initialValue == null) {
              throw new IllegalArgumentException("Invalid default value. Cannot find concept: " + defaultValue);
            }
           
            if (!conceptAnswers.contains(initialValue)) {
              String allowedIds = "";
              for (Concept conceptAnswer : conceptAnswers) {
                allowedIds += conceptAnswer.getId() + ", ";
              }
              allowedIds = allowedIds.substring(0, allowedIds.length() - 2);
              throw new IllegalArgumentException("Invalid default value: " + defaultValue
                      + ". The only allowed answers are: " + allowedIds);
            }
            valueWidget.setInitialValue(initialValue);
          }
        }
      } else if (concept.getDatatype().isBoolean()) {
        String noStr = parameters.get("noLabel");
        if (StringUtils.isEmpty(noStr)) {
          noStr = context.getTranslator().translate(userLocaleStr, "general.no");
        }
        String yesStr = parameters.get("yesLabel");
        if (StringUtils.isEmpty(yesStr)) {
          yesStr = context.getTranslator().translate(userLocaleStr, "general.yes");
        }
       
        if ("checkbox".equals(parameters.get("style"))) {
          if (parameters.get("toggle") != null) {
            ToggleWidget toggleWidget = new ToggleWidget(parameters.get("toggle"));
            valueWidget = new CheckboxWidget(valueLabel, parameters.get("value") != null ? parameters.get("value") : "true", toggleWidget.getTargetId(), toggleWidget.isToggleDim());
          } else {
            valueWidget = new CheckboxWidget(valueLabel, parameters.get("value") != null ? parameters.get("value") : "true", parameters.get("toggle"));
          }
          valueLabel = "";
        } else if ("no_yes".equals(parameters.get("style"))) {
          valueWidget = new RadioButtonsWidget();
          ((RadioButtonsWidget) valueWidget).addOption(new Option(noStr, "false", false));
          ((RadioButtonsWidget) valueWidget).addOption(new Option(yesStr, "true", false));
        } else if ("yes_no".equals(parameters.get("style"))) {
          valueWidget = new RadioButtonsWidget();
          ((RadioButtonsWidget) valueWidget).addOption(new Option(yesStr, "true", false));
          ((RadioButtonsWidget) valueWidget).addOption(new Option(noStr, "false", false));
        } else if ("no_yes_dropdown".equals(parameters.get("style"))) {
          valueWidget = new DropdownWidget();
          ((DropdownWidget) valueWidget).addOption(new Option());
          ((DropdownWidget) valueWidget).addOption(new Option(noStr, "false", false));
          ((DropdownWidget) valueWidget).addOption(new Option(yesStr, "true", false));
        } else if ("yes_no_dropdown".equals(parameters.get("style"))) {
          valueWidget = new DropdownWidget();
          ((DropdownWidget) valueWidget).addOption(new Option());
          ((DropdownWidget) valueWidget).addOption(new Option(yesStr, "true", false));
          ((DropdownWidget) valueWidget).addOption(new Option(noStr, "false", false));
        } else {
          throw new RuntimeException("Boolean with style = " + parameters.get("style")
                  + " not yet implemented (concept = " + concept.getConceptId() + ")");
        }
       
        if (existingObs != null) {
          valueWidget.setInitialValue(existingObs.getValueAsBoolean());
        } else if (defaultValue != null && Mode.ENTER.equals(context.getMode())) {
          defaultValue = defaultValue.trim();
         
          //Check the default value. Do not use Boolean.valueOf as it only tests for 'true'.
          Boolean initialValue = null;
          if (defaultValue.equalsIgnoreCase(Boolean.TRUE.toString())) {
            initialValue = true;
          } else if (defaultValue.equalsIgnoreCase(Boolean.FALSE.toString())) {
            initialValue = false;
          } else if (defaultValue.isEmpty()) {
            initialValue = null;
          } else {
            throw new IllegalArgumentException("Invalid default value " + defaultValue
                    + ". Must be 'true', 'false' or ''.");
          }
          valueWidget.setInitialValue(initialValue);
        }
       
        // TODO: in 1.7-compatible version of the module, we can replace the H17 checks
        // used below with the new isDate, isTime, and isDatetime
       
      } else {
        DateWidget dateWidget = null;
        TimeWidget timeWidget = null;
        boolean disableTime = "false".equalsIgnoreCase(parameters.get("allowTime"));
       
        if (ConceptDatatype.DATE.equals(concept.getDatatype().getHl7Abbreviation()) || (ConceptDatatype.DATETIME.equals(concept.getDatatype().getHl7Abbreviation()) && disableTime)) {
          valueWidget = new DateWidget();
        } else if (ConceptDatatype.TIME.equals(concept.getDatatype().getHl7Abbreviation())) {
          valueWidget = new TimeWidget();
        } else if (ConceptDatatype.DATETIME.equals(concept.getDatatype().getHl7Abbreviation())) {
          dateWidget = new DateWidget();
          timeWidget = new TimeWidget();
         
          valueWidget = new DateTimeWidget(dateWidget, timeWidget);
        } else {
          throw new RuntimeException("Cannot handle datatype: " + concept.getDatatype().getName()
                  + " (for concept " + concept.getConceptId() + ")");
        }
       
        if (defaultValue != null && parameters.get("defaultDatetime") != null) {
          throw new IllegalArgumentException("Cannot set defaultDatetime and defaultValue at the same time.");
        } else if (defaultValue == null) {
          defaultValue = parameters.get("defaultDatetime");
        }
       
        if (existingObs != null) {
          valueWidget.setInitialValue(existingObs.getValueDatetime());
        } else if (defaultValue != null && Mode.ENTER.equals(context.getMode())) {
          valueWidget.setInitialValue(HtmlFormEntryUtil
                  .translateDatetimeParam(defaultValue, defaultDatetimeFormat));
        }
       
        if (dateWidget != null) {
          context.registerWidget(dateWidget);
        }
        if (timeWidget != null) {
          context.registerWidget(timeWidget);
        }
      }
    }
    context.registerWidget(valueWidget);
    context.registerErrorWidget(valueWidget, errorWidget);
   
    if (parameters.get("showUnits") != null) {
            if ("true".equalsIgnoreCase(parameters.get("showUnits"))) {
                showUnits = true;
            } else if (!"false".equalsIgnoreCase(parameters.get("showUnits"))) {
                showUnits = true;
                unitsCode = parameters.get("showUnits");
            }
    }

        if (parameters.get("unitsCssClass") != null) {
            unitsCssClass = parameters.get("unitsCssClass");
        }

        // if a date is requested, do that too
    if ("true".equals(parameters.get("showDate")) || parameters.containsKey("dateLabel")) {
      if (parameters.containsKey("dateLabel")){
                dateLabel = parameters.get("dateLabel");
            }
      dateWidget = new DateWidget();
      context.registerWidget(dateWidget);
      context.registerErrorWidget(dateWidget, errorWidget);
      if (existingObs != null) {
        dateWidget.setInitialValue(existingObs.getObsDatetime());
      } else if (parameters.get("defaultObsDatetime") != null) {
        // Make sure this format continues to match
        // the <obs> attribute defaultObsDatetime documentation at
        // https://wiki.openmrs.org/display/docs/HTML+Form+Entry+Module+HTML+Reference#HTMLFormEntryModuleHTMLReference-%3Cobs%3E
        String supportedDateFormat = "yyyy-MM-dd-HH-mm";
        dateWidget.setInitialValue(HtmlFormEntryUtil.translateDatetimeParam(parameters.get("defaultObsDatetime"),
            supportedDateFormat));
      }
    }
   
    // if an accessionNumber is requested, do that too
    if ("true".equals(parameters.get("showAccessionNumber")) || parameters.containsKey("accessionNumberLabel")) {
      if (parameters.containsKey("accessionNumberLabel")) {
               accessionNumberLabel = parameters.get("accessionNumberLabel");
            }
      accessionNumberWidget = new TextFieldWidget();
      context.registerWidget(accessionNumberWidget);
      context.registerErrorWidget(accessionNumberWidget, errorWidget);
      if (existingObs != null) {
        accessionNumberWidget.setInitialValue(existingObs.getAccessionNumber());
      }
    }
   
    // if a comment is requested, do that too
    if ("true".equals(parameters.get("showCommentField"))  || parameters.containsKey("commentFieldLabel")) {
      if(parameters.containsKey("commentFieldLabel")){
                commentFieldLabel = parameters.get("commentFieldLabel");
            }
            commentFieldWidget = new TextFieldWidget();
      context.registerWidget(commentFieldWidget);
      context.registerErrorWidget(commentFieldWidget, errorWidget);
      if (existingObs != null) {
        commentFieldWidget.setInitialValue(existingObs.getComment());
      }
    }

    ObsField field = new ObsField();
    field.setName(valueLabel);
    if (concept != null) {
      field.setQuestion(concept);
    } else if (concepts != null && concepts.size() > 0) { //for concept selects
      for (int i = 0; i < concepts.size(); i++) {
        ObsFieldAnswer ans = new ObsFieldAnswer();
        ans.setConcept(concepts.get(i));
        if (i < conceptLabels.size()) {
          ans.setDisplayName(conceptLabels.get(i));
        }
        field.getQuestions().add(ans);
      }
    }
    if (answerConcept != null) {
      ObsFieldAnswer ans = new ObsFieldAnswer();
      ans.setDisplayName(getAnswerLabel());
      ans.setConcept(answerConcept);
      field.setAnswers(Arrays.asList(ans));
    } else if (conceptAnswers != null) {
      for (int i = 0; i < conceptAnswers.size(); i++) {
        ObsFieldAnswer ans = new ObsFieldAnswer();
        ans.setConcept(conceptAnswers.get(i));
        if (i < answerLabels.size()) {
          ans.setDisplayName(answerLabels.get(i));
        }
        field.getAnswers().add(ans);
      }
    }
    //conceptSelects should be excluded from obsGroup matching, because there's nothing to match on.
    if (concept != null && context.getActiveObsGroup() != null) {
      context.getActiveObsGroup().getChildren().add(field);
    } else {
      context.getSchema().addField(field);
    }
  }

  @Override
  public String generateHtml(FormEntryContext context) {
    StringBuilder ret = new StringBuilder();
    if (id != null || clazz != null) {
      ret.append("<span " + (id != null "id=\"" + id + "\" " : "") +
                    "class=\"obs-field"+ (clazz !=null ? " " + clazz : "") + "\">");
      context.registerPropertyAccessorInfo(id + ".value", context.getFieldNameIfRegistered(valueWidget),
          getFieldFunction(valueWidget), getGetterFunction(valueWidget), getSetterFunction(valueWidget));
      context.registerPropertyAccessorInfo(id + ".date", context.getFieldNameIfRegistered(dateWidget),
          "dateFieldGetterFunction", null, "dateSetterFunction");
      context.registerPropertyAccessorInfo(id + ".error", context.getFieldNameIfRegistered(errorWidget), null, null,
          null);
      context.registerPropertyAccessorInfo(id + ".accessionNumber",
          context.getFieldNameIfRegistered(accessionNumberWidget), null, null, null);
      if (commentFieldWidget != null) {
        context.registerPropertyAccessorInfo(id + ".value", context.getFieldNameIfRegistered(commentFieldWidget),
            null, null, null);
      }
    }
    ret.append(valueLabel);
    if (!"".equals(valueLabel))
      ret.append(" ");
    ret.append(valueWidget.generateHtml(context));
    if (showUnits) {
      if (concept == null || !concept.getDatatype().isNumeric()) {
        throw new IllegalArgumentException("Can only show units when the concept is numeric");
      }
      String units;
      if (concept instanceof ConceptNumeric) {
        units = ((ConceptNumeric) concept).getUnits();
      } else {
        ConceptNumeric asConceptNumeric = Context.getConceptService().getConceptNumeric(concept.getConceptId());
        if (asConceptNumeric == null) {
          throw new IllegalStateException("Concept " + concept + " (" + concept.getName().getName() + ") has datatype = Numeric, but no row in concept_numeric");
        }
        units = asConceptNumeric.getUnits();
      }
      ret.append("<span class=\"" + unitsCssClass + "\">");
            if (unitsCode != null) {
                ret.append(context.getTranslator().translate(Context.getLocale().toString(), unitsCode));
            } else if (units != null) {
                ret.append(units);
            }
            ret.append("</span>");
    }
    if (dateWidget != null) {
      ret.append(" ");
      if (dateLabel != null) {
        ret.append(dateLabel);
      }
      ret.append(dateWidget.generateHtml(context));
    }
    if (accessionNumberWidget != null) {
      ret.append(" ");
      if (accessionNumberLabel != null) {
        ret.append("<br/>" + accessionNumberLabel);
      }
      ret.append(accessionNumberWidget.generateHtml(context));
    }
    if (commentFieldWidget != null) {
      ret.append(" ");
            if(commentFieldLabel != null){
               ret.append(commentFieldLabel);
            }else {
               ret.append(Context.getMessageSourceService().getMessage("htmlformentry.comment")+":");
            }
      ret.append(" ");
      ret.append(commentFieldWidget.generateHtml(context));
    }

    if (context.getMode() != Mode.VIEW) {
            // if value is required
            if (required) {
                ret.append("<span class='required'>*</span>");
            }
            ret.append(" ");
      ret.append(errorWidget.generateHtml(context));
    }
    if (id != null || clazz != null) {
      ret.append("</span>");
        }
    return ret.toString();
  }
 
  /**
   * TODO implement for all non-standard widgets
   *
   * @param widget
   * @return
   */
  private String getSetterFunction(Widget widget) {
    if (widget == null)
      return null;
    if (widget instanceof CheckboxWidget)
      return "checkboxSetterFunction";
    if (widget instanceof DateWidget)
      return "dateSetterFunction";
    return null;
  }
 
  /**
   * TODO implement for all non-standard widgets
   *
   * @param widget
   * @return
   */
  private String getGetterFunction(Widget widget) {
    if (widget == null)
      return null;
    if (widget instanceof CheckboxWidget)
      return "checkboxGetterFunction";
    return null;
  }
 
  /**
   * TODO implement for all non-standard widgets TODO figure out how to return multiple elements,
   * e.g. for date+time widget
   *
   * @param widget
   * @return
   */
  private String getFieldFunction(Widget widget) {
    if (widget == null)
      return null;
    if (widget instanceof DateWidget)
      return "dateFieldGetterFunction";
    return null;
  }
 
  @Override
  public Collection<FormSubmissionError> validateSubmission(FormEntryContext context, HttpServletRequest submission) {
    List<FormSubmissionError> ret = new ArrayList<FormSubmissionError>();
    Object value = null;
    Object date = null;
   
    try {
      value = valueWidget.getValue(context, submission);
    }
    catch (Exception ex) {
      ret.add(new FormSubmissionError(valueWidget, ex.getMessage()));
    }
   
    try {
      if (dateWidget != null)
        date = dateWidget.getValue(context, submission);
    }
    catch (Exception ex) {
      ret.add(new FormSubmissionError(dateWidget, ex.getMessage()));
    }
   
    if (value == null && date != null)
      ret.add(new FormSubmissionError(valueWidget, Context.getMessageSourceService().getMessage(
          "htmlformentry.error.dateWithoutValue")));
   
    if (date != null && OpenmrsUtil.compare((Date) date, new Date()) > 0)
      ret.add(new FormSubmissionError(dateWidget, Context.getMessageSourceService().getMessage(
          "htmlformentry.error.cannotBeInFuture")));
   
    if (value instanceof Date && !allowFutureDates && OpenmrsUtil.compare((Date) value, new Date()) > 0) {
      ret.add(new FormSubmissionError(valueWidget, Context.getMessageSourceService().getMessage(
          "htmlformentry.error.cannotBeInFuture")));
    }
   
    if (required) {
      if (value == null) {
        ret.add(new FormSubmissionError(valueWidget, Context.getMessageSourceService().getMessage(
            "htmlformentry.error.required")));
      } else if (value instanceof String) {
        String valueStr = (String) value;
        if (StringUtils.isEmpty(valueStr)) {
          ret.add(new FormSubmissionError(valueWidget, Context.getMessageSourceService().getMessage(
              "htmlformentry.error.required")));
        }
      }
    }
   
    return ret;
  }
 
  @Override
  public void handleSubmission(FormEntrySession session, HttpServletRequest submission) {
    Object value = valueWidget.getValue(session.getContext(), submission);
        if (value instanceof String && ((String) value).startsWith("Drug:")) {
            String drugId = ((String) value).substring("Drug:".length());
            value = HtmlFormEntryUtil.convertToType(drugId, Drug.class);
        }
    if (concepts != null) {
      try {
        if (value instanceof Concept)
          concept = (Concept) value;
        else
          concept = (Concept) HtmlFormEntryUtil.convertToType(value.toString(), Concept.class);
      }
      catch (Exception ex) {
        throw new RuntimeException("Unable to convert response to a concept!");
      }
    }
    Date obsDatetime = null;
    String accessionNumberValue = null;
    if (dateWidget != null)
      obsDatetime = (Date) dateWidget.getValue(session.getContext(), submission);
    if (accessionNumberWidget != null)
      accessionNumberValue = (String) accessionNumberWidget.getValue(session.getContext(), submission);

    String comment = null;
    if (commentFieldWidget != null)
      comment = commentFieldWidget.getValue(session.getContext(), submission);

        // note that for the remote use case where showCommentField=true and style=location won't work, as "org.openmrs.Location"
        // will override any user-entered comment
        if (isLocationObs) {
            comment = "org.openmrs.Location";
        }

    if (existingObsList != null && session.getContext().getMode() == Mode.EDIT) {

        // trying to break this up a little bit by factoring specific functionality for specific widgets into separate methods at least
            handleDynamicAutocompleteSubmissionInEditMode(session, submission, value, obsDatetime, accessionNumberValue);

      } else if (existingObs != null && session.getContext().getMode() == Mode.EDIT) {
        // For complex obs: if value is to be retained, get the value from existingObs
      if (valueWidget instanceof UploadWidget && value == null) {
        if (!((UploadWidget) valueWidget).shouldDelete(session.getContext(), submission)) {
          value = new ComplexData(existingObs.getValueComplex(), null);
        }
      }
             
      // call this regardless of whether the new value is null -- the
      // modifyObs method is smart
      if (concepts != null)
        session.getSubmissionActions().modifyObs(existingObs, concept, answerConcept, obsDatetime,
            accessionNumberValue, comment);
      else
        session.getSubmissionActions().modifyObs(existingObs, concept, value, obsDatetime, accessionNumberValue, comment);
    } else {
      if (concepts != null && value != null && !"".equals(value) && concept != null) {
        session.getSubmissionActions().createObs(concept, answerConcept, obsDatetime, accessionNumberValue, comment);
      } else if (value != null && !"".equals(value)) {
        if (valueWidget instanceof DynamicAutocompleteWidget) {

                    // trying to break this up a little bit by factoring specific functionality for specific widgets into separate methods at least
            handleDynamicAutocompleteSubmissionInEnterMode(session, submission, value, obsDatetime, accessionNumberValue);

                } else {
            session.getSubmissionActions().createObs(concept, value, obsDatetime, accessionNumberValue, comment);
          }
            }
    }
  }

    private void handleDynamicAutocompleteSubmissionInEnterMode(FormEntrySession session, HttpServletRequest submission, Object value, Date obsDatetime, String accessionNumberValue) {

        List values = (List) value;

        // create an obs for each value
        for (Object val : values) {
            int conceptId = Integer.valueOf((String) val);
            ((DynamicAutocompleteWidget)valueWidget).addInitialValue(Context.getConceptService().getConcept(conceptId));
            session.getSubmissionActions().createObs(concept, conceptId, obsDatetime, accessionNumberValue);
        }

    }

    private void handleDynamicAutocompleteSubmissionInEditMode(FormEntrySession session, HttpServletRequest submission, Object value, Date obsDatetime, String accessionNumberValue) {

        List values = (List) value;

        List<Concept> newConceptList = new Vector<Concept>();
        List<Concept> existingConceptList = ((DynamicAutocompleteWidget) valueWidget).getInitialValueList();

        // get the list of concepts entered on the form
        for (Object val : values) {
            if (StringUtils.isNotBlank((String) val)) {
                int conceptId = Integer.valueOf((String) val);
                newConceptList.add(Context.getConceptService().getConcept(conceptId));
            }
        }

        // figure out what obs we need to create and what ones we need to remove
        for (Concept c : existingConceptList) {
            if (newConceptList.contains(c))
                newConceptList.remove(c);
            else {
                for (Obs o : existingObsList) {
                    if (o.getValueCoded().equals(c))
                        session.getSubmissionActions().modifyObs(o, concept, null, obsDatetime, accessionNumberValue);
                }
            }
        }
        if (!newConceptList.isEmpty()) {
            for (Concept c : newConceptList) {
                session.getSubmissionActions().createObs(concept, c, obsDatetime, accessionNumberValue);
            }
        }
    }

  private Comparator<Concept> conceptNameComparator = new Comparator<Concept>() {
   
    @Override
    public int compare(Concept c1, Concept c2) {
      String n1 = c1.getBestName(Context.getLocale()).getName();
      String n2 = c2.getBestName(Context.getLocale()).getName();
      return n1.compareTo(n2);
    }
  };
 
  /**
   * Returns the concept associated with this Observation
   */
  public Concept getConcept() {
    return concept;
  }
 
  /**
   * Returns the concept associated with the answer to this Observation
   */
  public Concept getAnswerConcept() {
    return answerConcept;
  }
 
  /**
   * Returns the concepts that are potential answers to this Observation
   */
  public List<Concept> getConceptAnswers() {
    return conceptAnswers;
  }
 
  /**
   * Returns the Numbers that are potential answers for this Observation
   */
  public List<Number> getNumericAnswers() {
    return numericAnswers;
  }
 
  /**
   * Returns the potential text answers for this Observation
   */
  public List<String> getTextAnswers() {
    return textAnswers;
  }
 
  /**
   * Returns the labels to use for the answers to this Observation
   */
  public List<String> getAnswerLabels() {
    return answerLabels;
  }
 
  /**
   * Returns the label to use for the answer to this Observation
   */
  public String getAnswerLabel() {
    return answerLabel;
  }
 
  public String getValueLabel() {
    return valueLabel;
  }
 
  public Obs getExistingObs() {
    return existingObs;
  }

    public void whenValueThenDisplaySection(Object value, String thenSection) {
        whenValueThenDisplaySection.put(value, thenSection);
    }

    public Map<Object, String> getWhenValueThenDisplaySection() {
        return whenValueThenDisplaySection;
    }

    public void whenValueThenJavaScript(Object value, String thenJavaScript) {
        whenValueThenJavascript.put(value, thenJavaScript);
    }

    public Map<Object, String> getWhenValueThenJavascript() {
        return whenValueThenJavascript;
    }

    public void whenValueElseJavaScript(Object value, String elseJavaScript) {
        whenValueElseJavascript.put(value, elseJavaScript);
    }

    public Map<Object, String> getWhenValueElseJavascript() {
        return whenValueElseJavascript;
    }

    public boolean hasWhenValueThen() {
        return whenValueThenDisplaySection.size() > 0
                || whenValueThenJavascript.size() > 0
                || whenValueElseJavascript.size() > 0;
    }

    public String getId() {
        return id;
    }

}
TOP

Related Classes of org.openmrs.module.htmlformentry.element.ObsSubmissionElement

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.