private void convertJSONField(JSONObject nodeJSON, List<String> dateFieldNames) { JSONObject properties = nodeJSON.optJSONObject(PEDIGREE_PROPERTIES_STRING); if (properties != null) { for (String fieldName : dateFieldNames) { JSONObject dateObject = properties.optJSONObject(fieldName); if (dateObject != null) { PhenoTipsDate date = new PhenoTipsDate(dateObject); properties.put(fieldName, date.toJSON()); } } nodeJSON.put(PEDIGREE_PROPERTIES_STRING, properties); } } }
private Integer getNumericValueFromJSON(JSONObject json, String key, Integer validRangeMin, Integer validRangeMax) { if (!json.has(key)) { return null; } // check if the key is an integer int intValue = json.optInt(key, Integer.MIN_VALUE); if (intValue != Integer.MIN_VALUE) { if (valueInRange(intValue, validRangeMin, validRangeMax)) { return intValue; } return null; } // check if the key is a string and try to parse the value from it return stringToIntegerInRange(json.optString(key, ""), validRangeMin, validRangeMax); }
@Override public String toString() { return toJSON().toString(); }
/** * Saves the {@code date} data for some {@code property} into the object containing patient {@code data}. * * @param data the {@link BaseObject} where new data will be saved * @param date the updated {@link PhenoTipsDate date} data for {@code property} * @param property the patient document property of interest */ private void saveDateData( @Nonnull final BaseObject data, @Nullable final PhenoTipsDate date, @Nonnull final String property) { // note: `date` may be null if data is missing if (CORRESPONDING_ASENTERED_FIELDNAMES.containsKey(property)) { final String dateStr = date == null ? StringUtils.EMPTY : date.toString(); data.setStringValue(CORRESPONDING_ASENTERED_FIELDNAMES.get(property), dateStr); } // if date is not a valid/complete date, toEarliestPossibleISODate() will return null // and date will be effectively "unset" final Date dateObj = date == null ? null : date.toEarliestPossibleISODate(); data.setDateValue(property, dateObj); }
private void updatePatientDates(BaseObject patientData, String documentName) { for (Map.Entry<String, String> entry : ASENTERED_FIELDNAMES.entrySet()) { String asEnteredField = entry.getKey(); String dateAsEntered = patientData.getStringValue(asEnteredField); if (!StringUtils.isEmpty(dateAsEntered)) { // if "date as entered" is present, use it and disregard the date field itself. try { JSONObject dateAsEnteredJSON = new JSONObject(dateAsEntered); PhenoTipsDate asEnteredDate = new PhenoTipsDate(dateAsEnteredJSON); // PhenoTipsDate can read data in the old format, and can spit out date in the new format patientData.setStringValue(asEnteredField, asEnteredDate.toString()); } catch (Exception ex) { this.logger.error("Could not process date-as-entered field {} for patient {}: [{}]", asEnteredField, documentName, ex.getMessage()); } } else { // otherwise use the date field (if present) to populate the date as entered String dateField = entry.getValue(); Date date = patientData.getDateValue(dateField); if (date != null) { this.logger.debug("Using the value from the {} field to populate {} field for patient {}", dateField, asEnteredField, documentName); PhenoTipsDate phenotipsDate = new PhenoTipsDate(date); patientData.setStringValue(asEnteredField, phenotipsDate.toString()); } } } }
@Override public void writeJSON(Patient patient, JSONObject json, Collection<String> selectedFieldNames) { // this controller is only activated if a deprecated field is explicitly requested if (selectedFieldNames == null) { return; } DateFormat dateFormat = new SimpleDateFormat(this.configurationManager.getActiveConfiguration().getISODateFormat()); PatientData<PhenoTipsDate> datesData = patient.getData(DATA_NAME); boolean noData = (datesData == null || !datesData.isNamed()); for (String propertyName : this.getPatientDocumentProperties()) { // only a subset of fields was explicitly requested, and this field is not included if (!selectedFieldNames.contains(getControllingFieldName(propertyName))) { continue; } PhenoTipsDate data = noData ? null : datesData.get(propertyName); json.put(getJSONFieldName(propertyName), ((data == null || !data.isSet()) ? "" : dateFormat.format(data.toEarliestPossibleISODate()))); } }
result.put(property, new PhenoTipsDate(dateAsObject)); } else { result.put(property, new PhenoTipsDate(json.optString(jsonFieldName, null)));
useFuzzyDate.put(JSON_RANGE_FIELDNAME, range); Integer firstYearOfDecade = stringToIntegerInRange(m.group(1), null, null); useFuzzyDate.put(JSON_YEAR_FIELDNAME, firstYearOfDecade); Integer inputYear = getNumericValueFromJSON(useFuzzyDate, JSON_YEAR_FIELDNAME, null, null); if (inputYear == null) { this.rangeYears = null; this.month = getNumericValueFromJSON(useFuzzyDate, JSON_MONTH_FIELDNAME, MIN_MONTH, MAX_MONTH); this.day = getNumericValueFromJSON(useFuzzyDate, JSON_DAY_FIELDNAME, MIN_DAY, MAX_DAY);
PhenoTipsDate dob = patient.<PhenoTipsDate>getData("dates").get("date_of_birth"); DataCell cell; if (dob != null && dob.toEarliestPossibleISODate() != null) { SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd"); cell = new DataCell(format.format(dob.toEarliestPossibleISODate()), x, 0); } else { cell = new DataCell("", x, 0);
private Integer stringToIntegerInRange(String str, Integer validRangeMin, Integer validRangeMax) { try { Integer value = Integer.parseInt(str); if (!valueInRange(value, validRangeMin, validRangeMax)) { return null; } return value; } catch (Exception ex) { return null; } }
/** * Initialize from a string, which may either be an ISO date in the "yyyy-mm-dd" format, or a modified ISO string * where the year is followed by an "s" to indicade that decade only is known. Also supported: "yyyy[s]-mm" and * "yyyy[s]". Formally, the format is: "yyyy[s][-mm[-dd]]". * * @param phenoTipsDateString a date string. */ public PhenoTipsDate(String phenoTipsDateString) { // treat null input as empty input String useDateString = (phenoTipsDateString == null) ? "" : phenoTipsDateString; // string: "1920s" or "1990" or "1990-05" or "1990-01-21" or "1990s-01-01" Matcher m = DATE_STRING_REGEXP.matcher(useDateString); if (m.find()) { // note: month (#4) and day (#6) groups may be null, that is supported this.year = stringToIntegerInRange(m.group(1), null, null); this.month = stringToIntegerInRange(m.group(4), MIN_MONTH, MAX_MONTH); this.day = stringToIntegerInRange(m.group(6), MIN_DAY, MAX_DAY); if (m.group(2) != null) { this.rangeYears = 10; } else { this.rangeYears = null; } } else { this.rangeYears = null; this.year = null; this.month = null; this.day = null; } }
@Override public String toString() { return toJSON().toString(); }
@Override public void save(Patient patient, DocumentModelBridge doc) { BaseObject data = ((XWikiDocument) doc).getXObject(Patient.CLASS_REFERENCE); if (data == null) { throw new NullPointerException(ERROR_MESSAGE_NO_PATIENT_CLASS); } PatientData<PhenoTipsDate> dates = patient.getData(DATA_NAME); if (!dates.isNamed()) { throw new IllegalArgumentException(ERROR_MESSAGE_DATA_IN_MEMORY_IN_WRONG_FORMAT); } for (String propertyName : this.getPatientDocumentProperties()) { if (dates.containsKey(propertyName)) { PhenoTipsDate date = dates.get(propertyName); // note: `date` may be null if data is missing if (CORRESPONDING_ASENTERED_FIELDNAMES.containsKey(propertyName)) { data.setStringValue(CORRESPONDING_ASENTERED_FIELDNAMES.get(propertyName), (date == null ? "" : date.toString())); } // if date is not a valid/complete date, toEarliestPossibleISODate() will return null // and date will be effectively "unset" data.setDateValue(propertyName, (date == null ? null : date.toEarliestPossibleISODate())); } } }
private void updatePatientDates(BaseObject patientData, String documentName) { for (Map.Entry<String, String> entry : ASENTERED_FIELDNAMES.entrySet()) { String asEnteredField = entry.getKey(); String dateAsEntered = patientData.getStringValue(asEnteredField); if (!StringUtils.isEmpty(dateAsEntered)) { // if "date as entered" is present, use it and disregard the date field itself. try { JSONObject dateAsEnteredJSON = new JSONObject(dateAsEntered); PhenoTipsDate asEnteredDate = new PhenoTipsDate(dateAsEnteredJSON); // PhenoTipsDate can read data in the old format, and can spit out date in the new format patientData.setStringValue(asEnteredField, asEnteredDate.toString()); } catch (Exception ex) { this.logger.error("Could not process date-as-entered field {} for patient {}: [{}]", asEnteredField, documentName, ex.getMessage()); } } else { // otherwise use the date field (if present) to populate the date as entered String dateField = entry.getValue(); Date date = patientData.getDateValue(dateField); if (date != null) { this.logger.debug("Using the value from the {} field to populate {} field for patient {}", dateField, asEnteredField, documentName); PhenoTipsDate phenotipsDate = new PhenoTipsDate(date); patientData.setStringValue(asEnteredField, phenotipsDate.toString()); } } } }
@Override public void writeJSON(Patient patient, JSONObject json, Collection<String> selectedFieldNames) { // this controller is only activated if a deprecated field is explicitly requested if (selectedFieldNames == null) { return; } DateFormat dateFormat = new SimpleDateFormat(this.configurationManager.getActiveConfiguration().getISODateFormat()); PatientData<PhenoTipsDate> datesData = patient.getData(DATA_NAME); boolean noData = (datesData == null || !datesData.isNamed()); for (String propertyName : this.getPatientDocumentProperties()) { // only a subset of fields was explicitly requested, and this field is not included if (!selectedFieldNames.contains(getControllingFieldName(propertyName))) { continue; } PhenoTipsDate data = noData ? null : datesData.get(propertyName); json.put(getJSONFieldName(propertyName), ((data == null || !data.isSet()) ? "" : dateFormat.format(data.toEarliestPossibleISODate()))); } }
result.put(property, new PhenoTipsDate(dateAsObject)); } else { result.put(property, new PhenoTipsDate(json.optString(jsonFieldName, null)));
useFuzzyDate.put(JSON_RANGE_FIELDNAME, range); Integer firstYearOfDecade = stringToIntegerInRange(m.group(1), null, null); useFuzzyDate.put(JSON_YEAR_FIELDNAME, firstYearOfDecade); Integer inputYear = getNumericValueFromJSON(useFuzzyDate, JSON_YEAR_FIELDNAME, null, null); if (inputYear == null) { this.rangeYears = null; this.month = getNumericValueFromJSON(useFuzzyDate, JSON_MONTH_FIELDNAME, MIN_MONTH, MAX_MONTH); this.day = getNumericValueFromJSON(useFuzzyDate, JSON_DAY_FIELDNAME, MIN_DAY, MAX_DAY);
PhenoTipsDate dob = patient.<PhenoTipsDate>getData("dates").get("date_of_birth"); DataCell cell; if (dob != null && dob.toEarliestPossibleISODate() != null) { SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd"); cell = new DataCell(format.format(dob.toEarliestPossibleISODate()), x, 0); } else { cell = new DataCell("", x, 0);
private Integer stringToIntegerInRange(String str, Integer validRangeMin, Integer validRangeMax) { try { Integer value = Integer.parseInt(str); if (!valueInRange(value, validRangeMin, validRangeMax)) { return null; } return value; } catch (Exception ex) { return null; } }
/** * Initialize from a string, which may either be an ISO date in the "yyyy-mm-dd" format, or a modified ISO string * where the year is followed by an "s" to indicade that decade only is known. Also supported: "yyyy[s]-mm" and * "yyyy[s]". Formally, the format is: "yyyy[s][-mm[-dd]]". * * @param phenoTipsDateString a date string. */ public PhenoTipsDate(String phenoTipsDateString) { // treat null input as empty input String useDateString = (phenoTipsDateString == null) ? "" : phenoTipsDateString; // string: "1920s" or "1990" or "1990-05" or "1990-01-21" or "1990s-01-01" Matcher m = DATE_STRING_REGEXP.matcher(useDateString); if (m.find()) { // note: month (#4) and day (#6) groups may be null, that is supported this.year = stringToIntegerInRange(m.group(1), null, null); this.month = stringToIntegerInRange(m.group(4), MIN_MONTH, MAX_MONTH); this.day = stringToIntegerInRange(m.group(6), MIN_DAY, MAX_DAY); if (m.group(2) != null) { this.rangeYears = 10; } else { this.rangeYears = null; } } else { this.rangeYears = null; this.year = null; this.month = null; this.day = null; } }