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() + ")");
}