diff --git a/pom.xml b/pom.xml index 5afd69b..d54ac7f 100644 --- a/pom.xml +++ b/pom.xml @@ -69,45 +69,45 @@ packaging-utility 0.2.2 - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.security - spring-security-test - test - - - - - - - - - - - - + + + + + + + + + + + org.apache.commons commons-lang3 3.14.0 - - - - - + + + + + net.sf.saxon Saxon-HE 12.4 + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + diff --git a/src/main/java/gov/cms/madie/hqmf/ConstantMessages.java b/src/main/java/gov/cms/madie/hqmf/ConstantMessages.java index eea0182..0aa24a1 100644 --- a/src/main/java/gov/cms/madie/hqmf/ConstantMessages.java +++ b/src/main/java/gov/cms/madie/hqmf/ConstantMessages.java @@ -1,205 +1,175 @@ package gov.cms.madie.hqmf; -/** - * The Class ConstantMessages. - */ -public class ConstantMessages { +/** The Class ConstantMessages. */ +public interface ConstantMessages { - public static final int DB_LOG = 1; + String CONTINUOUS_VARIABLE_SCORING = "Continuous Variable"; - public static final int ID_NOT_UNIQUE = 1; + String PROPORTION_SCORING = "Proportion"; - public static final int REACHED_MAXIMUM_VERSION = 2; + String RATIO_SCORING = "Ratio"; - public static final int REACHED_MAXIMUM_MAJOR_VERSION = 3; + String COHORT_SCORING = "Cohort"; - public static final int REACHED_MAXIMUM_MINOR_VERSION = 4; + String POPULATION_CONTEXT_ID = "initialPopulation"; - public static final int INVALID_VALUE_SET_DATE = 5; + String NUMERATOR_CONTEXT_ID = "numerator"; - public static final int INVALID_DATA = 6; + String NUMERATOR_EXCLUSIONS_CONTEXT_ID = "numeratorExclusions"; - public static final int INVALID_CQL_DATA = 7; + String DENOMINATOR_CONTEXT_ID = "denominator"; - public static final int INVALID_CQL_LIBRARIES = 8; + String DENOMINATOR_EXCLUSIONS_CONTEXT_ID = "denominatorExclusions"; - public static final int DESCRIPTION_REQUIRED = 14; + String DENOMINATOR_EXCEPTIONS_CONTEXT_ID = "denominatorExceptions"; - public static final int PUBLISHER_REQUIRED = 15; + String MEASURE_POPULATION_CONTEXT_ID = "measurePopulation"; - public static final int MEASURE_NAME_INVALID = 16; + String MEASURE_OBSERVATION_CONTEXT_ID = "measureObservation"; - public static final String INCOMPLETE_ROW_ERROR = "Import failed. One or more rows is missing a Code or a Descriptor."; + String USER_DEFINED_CONTEXT_DESC = "User-defined"; - public static final String CONTINUOUS_VARIABLE_SCORING = "Continuous Variable"; + String POP_TAB = "Pop"; - public static final String PROPORTION_SCORING = "Proportion"; + String POP_TAB_EXPANDED = "Population"; - public static final String RATIO_SCORING = "Ratio"; + String NUM_TAB = "Num"; - public static final String COHORT_SCORING = "Cohort"; + String NUM_TAB_EXPANDED = "Numerator"; - public static final String POPULATION_CONTEXT_ID = "initialPopulation"; + String NUM_EX_TAB = "N Excl"; - public static final String NUMERATOR_CONTEXT_ID = "numerator"; + String NUM_EX_TAB_EXPANDED = "Numerator Exclusions"; - public static final String NUMERATOR_EXCLUSIONS_CONTEXT_ID = "numeratorExclusions"; + String DEN_TAB = "Den"; - public static final String DENOMINATOR_CONTEXT_ID = "denominator"; + String DEN_TAB_EXPANDED = "Denominator"; - public static final String DENOMINATOR_EXCLUSIONS_CONTEXT_ID = "denominatorExclusions"; + String EXCL_TAB = "D Excl"; - public static final String DENOMINATOR_EXCEPTIONS_CONTEXT_ID = "denominatorExceptions"; + String EXCL_TAB_EXPANDED = "Denominator Exclusions"; - public static final String MEASURE_POPULATION_CONTEXT_ID = "measurePopulation"; + String EXCEP_TAB = "D Excep"; - public static final String MEASURE_OBSERVATION_CONTEXT_ID = "measureObservation"; + String EXCEP_TAB_EXPANDED = "Denominator Exceptions"; - public static final String USER_DEFINED_CONTEXT_DESC = "User-defined"; + String MEASURE_POP_TAB = "Meas Pop"; - public static final String POP_TAB = "Pop"; + String MEASURE_POP_TAB_EXPANDED = "Measure Population"; - public static final String POP_TAB_EXPANDED = "Population"; + String MEASURE_OBS_TAB = "Meas Obs"; - public static final String NUM_TAB = "Num"; + String MEASURE_OBS_TAB_EXPANDED = "Measure Observation"; - public static final String NUM_TAB_EXPANDED = "Numerator"; + String STRAT_TAB = "Strat"; - public static final String NUM_EX_TAB = "N Excl"; + String STRAT_TAB_EXPANDED = "Stratification"; - public static final String NUM_EX_TAB_EXPANDED = "Numerator Exclusions"; + String USER_DEFINED_TAB = "User-Defined"; - public static final String DEN_TAB = "Den"; + String USER_DEFINED_TAB_EXPANDED = "User-Defined"; - public static final String DEN_TAB_EXPANDED = "Denominator"; + String MEASURE_PHRASE_TAB = "Measure Phrase"; - public static final String EXCL_TAB = "D Excl"; + String MEASURE_PHRASE_TAB_EXPANDED = "Measure Phrase"; - public static final String EXCL_TAB_EXPANDED = "Denominator Exclusions"; + String ATTRIBUTE = "Attribute"; - public static final String EXCEP_TAB = "D Excep"; + String TIMING_ELEMENT = "Timing Element"; - public static final String EXCEP_TAB_EXPANDED = "Denominator Exceptions"; + String PATIENT_CHARACTERISTIC_RACE = "Patient Characteristic Race"; - public static final String MEASURE_POP_TAB = "Meas Pop"; + String PATIENT_CHARACTERISTIC_ETHNICITY = "Patient Characteristic Ethnicity"; - public static final String MEASURE_POP_TAB_EXPANDED = "Measure Population"; + String PATIENT_CHARACTERISTIC_PAYER = "Patient Characteristic Payer"; - public static final String MEASURE_OBS_TAB = "Meas Obs"; + String PATIENT_CHARACTERISTIC_GENDER = "Patient Characteristic Sex"; - public static final String MEASURE_OBS_TAB_EXPANDED = "Measure Observation"; + String GROUPING_CODE_SYSTEM = "Grouping"; - public static final String STRAT_TAB = "Strat"; + String HL7_ADMINGENDER_CODE_SYSTEM = "Administrative Sex"; - public static final String STRAT_TAB_EXPANDED = "Stratification"; + String CDC_CODE_SYSTEM = "CDC"; - public static final String USER_DEFINED_TAB = "User-Defined"; + String SOURCE_OF_PAYMENT = "Source of Payment Typology"; - public static final String USER_DEFINED_TAB_EXPANDED = "User-Defined"; + String MAT_MODULE = "MAT"; - public static final String MEASURE_PHRASE_TAB = "Measure Phrase"; + String LOGIN_MODULE = "LOGIN"; - public static final String MEASURE_PHRASE_TAB_EXPANDED = "Measure Phrase"; + String HARP_SUPPORT_MODULE = "HARP SUPPORT"; - public static final String ATTRIBUTE = "Attribute"; + String PASSWORD = "password"; - public static final String TIMING_ELEMENT = "Timing Element"; + String PASSWORD_EXPIRE_DATE = "passwordExpireDate"; - public static final String PATIENT_CHARACTERISTIC_RACE = "Patient Characteristic Race"; + String LOGINID = "loginId"; - public static final String PATIENT_CHARACTERISTIC_ETHNICITY = "Patient Characteristic Ethnicity"; + String HARPID = "harpId"; - public static final String PATIENT_CHARACTERISTIC_PAYER = "Patient Characteristic Payer"; + String USER_EMAIL = "userEmail"; - public static final String PATIENT_CHARACTERISTIC_GENDER = "Patient Characteristic Sex"; + String URL = "url"; - public static final String GROUPING_CODE_SYSTEM = "Grouping"; + String INSERT = "Insert"; - public static final String HL7_ADMINGENDER_CODE_SYSTEM = "Administrative Sex"; + String UPDATE = "Update"; - public static final String CDC_CODE_SYSTEM = "CDC"; + String DELETE = "Delete"; - public static final String SOURCE_OF_PAYMENT = "Source of Payment Typology"; + String USER_NOT_FOUND = "User Not Found"; - public static final String MAT_MODULE = "MAT"; + String EMAIL_NOT_FOUND = "Email Not Found"; - public static final String LOGIN_MODULE = "LOGIN"; + String TOOLTIP_FOR_OCCURRENCE = + "Select Specific Occurrence if you need to reference a specific occurrence of your element."; - public static final String HARP_SUPPORT_MODULE = "HARP SUPPORT"; + String DEFAULT_SELECT = "--Select--"; - public static final String PASSWORD = "password"; + String CREATE_NEW_MEASURE = "New Measure"; - public static final String PASSWORD_EXPIRE_DATE = "passwordExpireDate"; + String CREATE_NEW_CQL = "New Library"; - public static final String LOGINID = "loginId"; + String MAXIMUM_ALLOWED_VERSION = "999.999"; - public static final String HARPID = "harpId"; + String MAXIMUM_ALLOWED_MAJOR_VERSION = "999"; - public static final String USER_EMAIL = "userEmail"; + String MAXIMUM_ALLOWED_MINOR_VERSION = "999"; - public static final String URL = "url"; + String GENDER_OID = "2.16.840.1.113762.1.4.1"; - public static final String INSERT = "Insert"; + String RACE_OID = "2.16.840.1.114222.4.11.836"; - public static final String UPDATE = "Update"; + String ETHNICITY_OID = "2.16.840.1.114222.4.11.837"; - public static final String DELETE = "Delete"; + String PAYER_OID = "2.16.840.1.114222.4.11.3591"; - public static final String USER_NOT_FOUND = "User Not Found"; + String MAIN_TAB_LAYOUT_ID = "mainTab"; - public static final String EMAIL_NOT_FOUND = "Email Not Found"; + String MEASURE_COMPOSER_TAB = "measureTab"; - public static final String TOOLTIP_FOR_OCCURRENCE = "Select Specific Occurrence if you need to reference a specific occurrence of your element."; + String CQL_COMPOSER_TAB = "cqlTab"; - public static final String DEFAULT_SELECT = "--Select--"; + String USER_DEFINED_QDM_OID = "1.1.1.1"; - public static final String CREATE_NEW_MEASURE = "New Measure"; + String USER_DEFINED_QDM_NAME = "User Defined QDM"; - public static final String CREATE_NEW_CQL = "New Library"; + String PATIENT_CHARACTERISTIC_BIRTHDATE = "Patient Characteristic Birthdate"; - public static final String MAXIMUM_ALLOWED_VERSION = "999.999"; + String PATIENT_CHARACTERISTIC_EXPIRED = "Patient Characteristic Expired"; - public static final String MAXIMUM_ALLOWED_MAJOR_VERSION = "999"; + String DEAD = "Dead"; - public static final String MAXIMUM_ALLOWED_MINOR_VERSION = "999"; + String BIRTHDATE = "Birthdate"; - public static final String GENDER_OID = "2.16.840.1.113762.1.4.1"; + String DEAD_OID = "419099009"; - public static final String RACE_OID = "2.16.840.1.114222.4.11.836"; + String BIRTHDATE_OID = "21112-8"; - public static final String ETHNICITY_OID = "2.16.840.1.114222.4.11.837"; + String BIRTHDATE_CODE_SYSTEM_OID = "2.16.840.1.113883.6.1"; - public static final String PAYER_OID = "2.16.840.1.114222.4.11.3591"; + String DEAD_CODE_SYSTEM_OID = "2.16.840.1.113883.6.96"; - public static final String MAIN_TAB_LAYOUT_ID = "mainTab"; + String SUPPORT_EMAIL = "supportEmailAddress"; - public static final String MEASURE_COMPOSER_TAB = "measureTab"; - - public static final String CQL_COMPOSER_TAB = "cqlTab"; - - public static final String USER_DEFINED_QDM_OID = "1.1.1.1"; - - public static final String USER_DEFINED_QDM_NAME = "User Defined QDM"; - - public static final String PATIENT_CHARACTERISTIC_BIRTHDATE = "Patient Characteristic Birthdate"; - - public static final String PATIENT_CHARACTERISTIC_EXPIRED = "Patient Characteristic Expired"; - - public static final String DEAD = "Dead"; - - public static final String BIRTHDATE = "Birthdate"; - - public static final String DEAD_OID = "419099009"; - - public static final String BIRTHDATE_OID = "21112-8"; - - public static final String BIRTHDATE_CODE_SYSTEM_OID = "2.16.840.1.113883.6.1"; - - public static final String DEAD_CODE_SYSTEM_OID = "2.16.840.1.113883.6.96"; - - public static final String SUPPORT_EMAIL = "supportEmailAddress"; - - private ConstantMessages() { - // Utility class - } } diff --git a/src/main/java/gov/cms/madie/hqmf/Generator.java b/src/main/java/gov/cms/madie/hqmf/Generator.java index 1cf1d92..7e3c925 100644 --- a/src/main/java/gov/cms/madie/hqmf/Generator.java +++ b/src/main/java/gov/cms/madie/hqmf/Generator.java @@ -1,181 +1,182 @@ package gov.cms.madie.hqmf; - import gov.cms.madie.hqmf.dto.MeasureExport; public interface Generator extends MatConstants { - - public static final String HIGH = "high"; - - public static final String STOP_DATETIME = "stop datetime"; - - public static final String START_DATETIME = "start datetime"; - - public static final String FLAVOR_ID = "flavorId"; - - public static final String LOW = "low"; - - public static final String EFFECTIVE_TIME = "effectiveTime"; - - public static final String ATTRIBUTE_UUID = "attributeUUID"; - - public static final String RELATED_TO = "related to"; - - public static final String CHECK_IF_PRESENT = "Check if Present"; - - public static final String TYPE = "type"; - - public static final String GROUPING_CHECK = "isInGrouping"; - - public static final String MOOD = "mood"; - - public static final String CLASS = "class"; - - public static final String XSI_TYPE = "xsi:type"; - - public static final String VALUE = "value"; - - public static final String TITLE = "title"; - - public static final String DISPLAY_NAME = "displayName"; - - public static final String CODE_SYSTEM = "codeSystem"; - - public static final String CODE_SYSTEM_NAME = "codeSystemName"; - - public static final String CODE_SYSTEM_DISPLAY_NAME = "codeDisplayName"; - - public static final String ID = "id"; - - public static final String ROOT = "root"; - - public static final String ITEM = "item"; - - public static final String TEMPLATE_ID = "templateId"; - - public static final String MOOD_CODE = "moodCode"; - - public static final String CLASS_CODE = "classCode"; - - public static final String TYPE_CODE = "typeCode"; - - public static final String RAV = "riskAdjVar"; - - public static final String OBSERVATION_CRITERIA = "observationCriteria"; - - public static final String OUTBOUND_RELATIONSHIP = "outboundRelationship"; - - public static final String UUID = "uuid"; - - public static final String TAXONOMY = "taxonomy"; - - public static final String OID = "oid"; - - public static final String NAME = "name"; - - public static final String CODE = "code"; - - public static final String VERSION_5_0_ID = "2017-05-01"; - - public static final String VERSION_4_1_2_ID = "2014-11-24"; - - public static final String VERSION_4_3_ID = "2015-09-30"; - - public static final String POPULATION_CRITERIA_EXTENSION = "2015-12-01"; - - public static final String POPULATION_CRITERIA_EXTENSION_CQL = "2017-08-01"; - - public static final String VALUE_SET = "Value Set"; - - public static final String ANATOMICAL_LOCATION_SITE = "Anatomical Location Site"; - - public static final String ANATOMICAL_APPROACH_SITE = "Anatomical Approach Site"; - - public static final String ORDINALITY = "Ordinality"; - - public static final String LATERALITY = "Laterality"; - - public static final String ROUTE = "route"; - - public static final String FACILITY_LOCATION = "facility location"; - - public static final String FACILITY_LOCATION_ARRIVAL_DATETIME = "facility location arrival datetime"; - - public static final String FACILITY_LOCATION_DEPARTURE_DATETIME = "facility location departure datetime"; - - public static final String REFILLS = "refills"; - - public static final String CUMULATIVE_MEDICATION_DURATION = "cumulative medication duration"; - - public static final String FREQUENCY = "frequency"; - - public static final String ADMISSION_DATETIME = "admission datetime"; - - public static final String DISCHARGE_STATUS ="discharge status"; - - public static final String DISCHARGE_DATETIME = "discharge datetime"; - - public static final String REMOVAL_DATETIME = "removal datetime"; - - public static final String INCISION_DATETIME = "incision datetime"; - - public static final String SIGNED_DATETIME = "signed datetime"; - - public static final String ACTIVE_DATETIME = "active datetime"; - - public static final String TIME = "time"; - - public static final String DATE = "date"; - - public static final String ATTRIBUTE_MODE = "attributeMode"; - - public static final String ATTRIBUTE_NAME = "attributeName"; - - public static final String NEGATION_RATIONALE = "negation rationale"; - - public static final String ATTRIBUTE_DATE = "attrDate"; - - public final String nameSpace = "http://www.w3.org/2001/XMLSchema-instance"; - - public static final String LESS_THAN = "Less Than"; - - public static final String GREATER_THAN = "Greater Than"; - - public static final String EQUAL_TO = "Equal To"; - - public static final String DOSE = "dose"; - - public static final String LENGTH_OF_STAY = "length of stay"; - - public static final String TRANSLATION = "translation"; - - public static final String NULL_FLAVOR ="nullFlavor"; - - public static final String RADIATION_DURATION = "radiation duration"; - - public static final String RADIATION_DOSAGE = "radiation dosage"; - - public static final String STATUS_CODE = "statusCode"; - - public static final String ONSET_DATETIME = "onset datetime"; - - public static final String ABATEMENT_DATETIME = "abatement datetime"; - - public static final String RECORDED_DATETIME = "recorded datetime"; - - public static final String REPEAT_NUMBER = "repeatNumber"; - - public static final String ONSET_AGE = "Onset Age"; - - public static final String REFERENCE = "reference"; - - public static final String RELATIONSHIP = "relationship"; - - public static final String DIAGNOSIS = "diagnosis"; - - public static final String PRINCIPAL_DIAGNOSIS = "principal diagnosis"; - - public static final String ACTION_NEGATION_IND = "actionNegationInd"; - - public String generate(MeasureExport me) throws Exception; -} \ No newline at end of file + + public static final String HIGH = "high"; + + public static final String STOP_DATETIME = "stop datetime"; + + public static final String START_DATETIME = "start datetime"; + + public static final String FLAVOR_ID = "flavorId"; + + public static final String LOW = "low"; + + public static final String EFFECTIVE_TIME = "effectiveTime"; + + public static final String ATTRIBUTE_UUID = "attributeUUID"; + + public static final String RELATED_TO = "related to"; + + public static final String CHECK_IF_PRESENT = "Check if Present"; + + public static final String TYPE = "type"; + + public static final String GROUPING_CHECK = "isInGrouping"; + + public static final String MOOD = "mood"; + + public static final String CLASS = "class"; + + public static final String XSI_TYPE = "xsi:type"; + + public static final String VALUE = "value"; + + public static final String TITLE = "title"; + + public static final String DISPLAY_NAME = "displayName"; + + public static final String CODE_SYSTEM = "codeSystem"; + + public static final String CODE_SYSTEM_NAME = "codeSystemName"; + + public static final String CODE_SYSTEM_DISPLAY_NAME = "codeDisplayName"; + + public static final String ID = "id"; + + public static final String ROOT = "root"; + + public static final String ITEM = "item"; + + public static final String TEMPLATE_ID = "templateId"; + + public static final String MOOD_CODE = "moodCode"; + + public static final String CLASS_CODE = "classCode"; + + public static final String TYPE_CODE = "typeCode"; + + public static final String RAV = "riskAdjVar"; + + public static final String OBSERVATION_CRITERIA = "observationCriteria"; + + public static final String OUTBOUND_RELATIONSHIP = "outboundRelationship"; + + public static final String UUID = "uuid"; + + public static final String TAXONOMY = "taxonomy"; + + public static final String OID = "oid"; + + public static final String NAME = "name"; + + public static final String CODE = "code"; + + public static final String VERSION_5_0_ID = "2017-05-01"; + + public static final String VERSION_4_1_2_ID = "2014-11-24"; + + public static final String VERSION_4_3_ID = "2015-09-30"; + + public static final String POPULATION_CRITERIA_EXTENSION = "2015-12-01"; + + public static final String POPULATION_CRITERIA_EXTENSION_CQL = "2017-08-01"; + + public static final String VALUE_SET = "Value Set"; + + public static final String ANATOMICAL_LOCATION_SITE = "Anatomical Location Site"; + + public static final String ANATOMICAL_APPROACH_SITE = "Anatomical Approach Site"; + + public static final String ORDINALITY = "Ordinality"; + + public static final String LATERALITY = "Laterality"; + + public static final String ROUTE = "route"; + + public static final String FACILITY_LOCATION = "facility location"; + + public static final String FACILITY_LOCATION_ARRIVAL_DATETIME = + "facility location arrival datetime"; + + public static final String FACILITY_LOCATION_DEPARTURE_DATETIME = + "facility location departure datetime"; + + public static final String REFILLS = "refills"; + + public static final String CUMULATIVE_MEDICATION_DURATION = "cumulative medication duration"; + + public static final String FREQUENCY = "frequency"; + + public static final String ADMISSION_DATETIME = "admission datetime"; + + public static final String DISCHARGE_STATUS = "discharge status"; + + public static final String DISCHARGE_DATETIME = "discharge datetime"; + + public static final String REMOVAL_DATETIME = "removal datetime"; + + public static final String INCISION_DATETIME = "incision datetime"; + + public static final String SIGNED_DATETIME = "signed datetime"; + + public static final String ACTIVE_DATETIME = "active datetime"; + + public static final String TIME = "time"; + + public static final String DATE = "date"; + + public static final String ATTRIBUTE_MODE = "attributeMode"; + + public static final String ATTRIBUTE_NAME = "attributeName"; + + public static final String NEGATION_RATIONALE = "negation rationale"; + + public static final String ATTRIBUTE_DATE = "attrDate"; + + public final String nameSpace = "http://www.w3.org/2001/XMLSchema-instance"; + + public static final String LESS_THAN = "Less Than"; + + public static final String GREATER_THAN = "Greater Than"; + + public static final String EQUAL_TO = "Equal To"; + + public static final String DOSE = "dose"; + + public static final String LENGTH_OF_STAY = "length of stay"; + + public static final String TRANSLATION = "translation"; + + public static final String NULL_FLAVOR = "nullFlavor"; + + public static final String RADIATION_DURATION = "radiation duration"; + + public static final String RADIATION_DOSAGE = "radiation dosage"; + + public static final String STATUS_CODE = "statusCode"; + + public static final String ONSET_DATETIME = "onset datetime"; + + public static final String ABATEMENT_DATETIME = "abatement datetime"; + + public static final String RECORDED_DATETIME = "recorded datetime"; + + public static final String REPEAT_NUMBER = "repeatNumber"; + + public static final String ONSET_AGE = "Onset Age"; + + public static final String REFERENCE = "reference"; + + public static final String RELATIONSHIP = "relationship"; + + public static final String DIAGNOSIS = "diagnosis"; + + public static final String PRINCIPAL_DIAGNOSIS = "principal diagnosis"; + + public static final String ACTION_NEGATION_IND = "actionNegationInd"; + + public String generate(MeasureExport me) throws Exception; +} diff --git a/src/main/java/gov/cms/madie/hqmf/HQMFAttributeGenerator.java b/src/main/java/gov/cms/madie/hqmf/HQMFAttributeGenerator.java index 2be1b72..82028d1 100644 --- a/src/main/java/gov/cms/madie/hqmf/HQMFAttributeGenerator.java +++ b/src/main/java/gov/cms/madie/hqmf/HQMFAttributeGenerator.java @@ -2,24 +2,24 @@ import gov.cms.madie.hqmf.dto.MeasureExport; - /** - * @deprecated this class is deprecated since it is an old version of QDM. It should not be modified. + * @deprecated this class is deprecated since it is an old version of QDM. It should not be + * modified. */ public class HQMFAttributeGenerator extends HQMFDataCriteriaElementGenerator { - private MeasureExport measureExport; - - @Override - public String generate(MeasureExport me) throws Exception { - return null; - } - - public MeasureExport getMeasureExport() { - return measureExport; - } - - public void setMeasureExport(MeasureExport measureExport) { - this.measureExport = measureExport; - } + private MeasureExport measureExport; + + @Override + public String generate(MeasureExport me) throws Exception { + return null; + } + + public MeasureExport getMeasureExport() { + return measureExport; + } + + public void setMeasureExport(MeasureExport measureExport) { + this.measureExport = measureExport; + } } diff --git a/src/main/java/gov/cms/madie/hqmf/HQMFDataCriteriaElementGenerator.java b/src/main/java/gov/cms/madie/hqmf/HQMFDataCriteriaElementGenerator.java index 45fbd46..4c444fc 100644 --- a/src/main/java/gov/cms/madie/hqmf/HQMFDataCriteriaElementGenerator.java +++ b/src/main/java/gov/cms/madie/hqmf/HQMFDataCriteriaElementGenerator.java @@ -19,3098 +19,3533 @@ import java.util.Map; /** - * @deprecated this class is deprecated since it is an old version of QDM. It should not be modified. + * @deprecated this class is deprecated since it is an old version of QDM. It should not be + * modified. */ public class HQMFDataCriteriaElementGenerator implements Generator { - /** The occurrence map. */ - private Map occurrenceMap = new HashMap(); - - protected String extensionValue = null; - - /** The Constant logger. */ - private static final Logger logger = LoggerFactory.getLogger(HQMFDataCriteriaElementGenerator.class); - - /** - * Generate hqm for measure. - * - * @param me - * the me - * @return the string - * @throws Exception - * the exception - */ - @Override - public String generate(MeasureExport me) throws Exception { - String dataCriteria = ""; - getExtensionValueBasedOnVersion(me); - dataCriteria = getHQMFXmlString(me); - return dataCriteria; - } - - public void generateAttributeTagForFunctionalOp(MeasureExport measureExport, Node qdmNode, Element excerptElement, - Node attributeQDMNode) throws XPathExpressionException { - getExtensionValueBasedOnVersion(measureExport); - createDataCriteriaForAttributes(qdmNode, excerptElement, measureExport.getHqmfXmlProcessor(), - measureExport.getSimpleXmlProcessor(), attributeQDMNode, true); - } - - /** - * Gets the HQMF xml string. - * - * @param me - * the me - * @return the HQMF xml string - */ - private String getHQMFXmlString(MeasureExport me) { - XmlProcessor dataCriteriaXMLProcessor = createDateCriteriaTemplate(me); - me.setHqmfXmlProcessor(dataCriteriaXMLProcessor); - - String simpleXMLStr = me.getSimpleXml(); - XmlProcessor simpleXmlprocessor = new XmlProcessor(simpleXMLStr); - me.setSimpleXmlProcessor(simpleXmlprocessor); - - prepHQMF(me); - - createDataCriteriaForQDMELements(me, dataCriteriaXMLProcessor, simpleXmlprocessor); - addDataCriteriaComment(dataCriteriaXMLProcessor); - return dataCriteriaXMLProcessor.transform(dataCriteriaXMLProcessor.getOriginalDoc(), true); - } - - /** - * Creates the date criteria template. - * - * @param me - * the me - * @return the string - */ - private XmlProcessor createDateCriteriaTemplate(MeasureExport me) { - XmlProcessor outputProcessor = new XmlProcessor( - ""); - - Node dataCriteriaElem = outputProcessor.getOriginalDoc().getElementsByTagName("dataCriteriaSection").item(0); - Element templateId = outputProcessor.getOriginalDoc().createElement(TEMPLATE_ID); - dataCriteriaElem.appendChild(templateId); - Element itemChild = outputProcessor.getOriginalDoc().createElement(ITEM); - itemChild.setAttribute(ROOT, "2.16.840.1.113883.10.20.28.2.2"); - itemChild.setAttribute("extension", extensionValue); - templateId.appendChild(itemChild); - // creating Code Element for DataCriteria - Element codeElem = outputProcessor.getOriginalDoc().createElement(CODE); - codeElem.setAttribute(CODE, "57025-9"); - codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.6.1"); - dataCriteriaElem.appendChild(codeElem); - // creating title for DataCriteria - Element titleElem = outputProcessor.getOriginalDoc().createElement(TITLE); - titleElem.setAttribute(VALUE, "Data Criteria Section"); - dataCriteriaElem.appendChild(titleElem); - // creating text for DataCriteria - Element textElem = outputProcessor.getOriginalDoc().createElement("text"); - dataCriteriaElem.appendChild(textElem); - - return outputProcessor; - } - - /** - * Creates the data criteria for qdm elements. - * - * @param me - * the me - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @return the string - */ - private void createDataCriteriaForQDMELements(MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor simpleXmlprocessor) { - // XPath String for only QDM's. - String xPathForOccurQDMNoAttribs = "/measure/elementLookUp/qdm[@datatype != 'attribute'][@instance]"; - String xPathForQDMNoAttribs = "/measure/elementLookUp/qdm[@datatype != 'attribute']"; - String xPathForQDMAttributes = "/measure/elementLookUp/qdm[@datatype = 'attribute']"; - String xpathForSupplementalQDMs = "/measure/elementLookUp/qdm[@suppDataElement = 'true']"; - String xpathForOtherSupplementalQDMs = "/measure/supplementalDataElements/elementRef/@id"; - String xpathForMeasureGroupingItemCount = "/measure//itemCount/elementRef/@id"; - - try { - - NodeList occurQdmNoAttributeNodeList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xPathForOccurQDMNoAttribs); - generateOccurrenceQDMEntries(simpleXmlprocessor, dataCriteriaXMLProcessor, occurQdmNoAttributeNodeList); - - NodeList qdmNoAttributeNodeList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xPathForQDMNoAttribs); - generateQDMEntries(dataCriteriaXMLProcessor, simpleXmlprocessor, qdmNoAttributeNodeList); - - NodeList qdmAttributeNodeList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xPathForQDMAttributes); - generateQDMAttributeEntries(dataCriteriaXMLProcessor, simpleXmlprocessor, qdmAttributeNodeList); - // generating QDM Entries for default Supplemental Data Elements - NodeList supplementalQDMNodeList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xpathForSupplementalQDMs); - generateSupplementalDataQDMEntries(simpleXmlprocessor, dataCriteriaXMLProcessor, supplementalQDMNodeList); - - // generating QDM Entries for other Supplemental Data Elements - NodeList supplementalDataElements = me.getSimpleXmlProcessor() - .findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), xpathForOtherSupplementalQDMs); - generateOtherSupplementalDataQDMEntries(me, dataCriteriaXMLProcessor, supplementalDataElements); - - // generating QDM entries for measureGrouping ItemCountlist - NodeList measureGroupingItemCountList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xpathForMeasureGroupingItemCount); - generateMeasureGrpnItemCountQDMEntries(me, dataCriteriaXMLProcessor, measureGroupingItemCountList); - - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - - protected void getExtensionValueBasedOnVersion(MeasureExport me) { - extensionValue = VERSION_4_3_ID; - } - - /** - * Generate measure grp item count qdm entries. - * - * @param me - * the me - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param measureGroupingItemCountList - * the measure grouping item count list - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateMeasureGrpnItemCountQDMEntries(MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, - NodeList measureGroupingItemCountList) throws XPathExpressionException { - - if ((measureGroupingItemCountList == null) || (measureGroupingItemCountList.getLength() < 1)) { - return; - } - List itemCountIDList = new ArrayList(); - for (int i = 0; i < measureGroupingItemCountList.getLength(); i++) { - if (!itemCountIDList.contains(measureGroupingItemCountList.item(i).getNodeValue())) { - itemCountIDList.add(measureGroupingItemCountList.item(i).getNodeValue()); - } - } - String xpathforElementLookUpElements = "/measure/elementLookUp/qdm[" + getUUIDString(itemCountIDList) + "]"; - - NodeList measureGroupingElementRefNodeList = me.getSimpleXmlProcessor() - .findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), xpathforElementLookUpElements); - generateItemCountQDMEntries(me, dataCriteriaXMLProcessor, measureGroupingElementRefNodeList); - } - - /** - * Generate supplemental data qdm entries. - * - * @param me - * the me - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param supplementalDataElements - * the supplemental data elements - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateOtherSupplementalDataQDMEntries(MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, - NodeList supplementalDataElements) throws XPathExpressionException { - if ((supplementalDataElements == null) || (supplementalDataElements.getLength() < 1)) { - return; - } - List supplementalElemenRefIds = new ArrayList(); - for (int i = 0; i < supplementalDataElements.getLength(); i++) { - supplementalElemenRefIds.add(supplementalDataElements.item(i).getNodeValue()); - } - - String xpathforOtherSupplementalDataElements = "/measure/elementLookUp/qdm[" - + getUUIDString(supplementalElemenRefIds) + "][@suppDataElement != 'true']"; - NodeList otherSupplementalQDMNodeList = me.getSimpleXmlProcessor() - .findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), xpathforOtherSupplementalDataElements); - - generateSupplementalDataQDMEntries(me, dataCriteriaXMLProcessor, otherSupplementalQDMNodeList); - - } - - /** - * Generate supplemental data qdm entries. - * - * @param me - * the me - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param qdmNodeList - * the qdm node list - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateSupplementalDataQDMEntries(MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, - NodeList qdmNodeList) throws XPathExpressionException { - for (int j = 0; j < qdmNodeList.getLength(); j++) { - Node qdmNode = qdmNodeList.item(j); - String qdmName = qdmNode.getAttributes().getNamedItem("name").getNodeValue(); - String qdmDatatype = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String qdmUUID = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); - String qdmExtension = qdmName.replaceAll("\\s", "") + "_" + qdmDatatype.replaceAll("\\s", ""); - String xpathForQDMEntry = "/root/component/dataCriteriaSection/entry/*/id[@root='" + qdmUUID - + "'][@extension=\"" + qdmExtension + "\"]"; - Node qmdEntryIDNode = dataCriteriaXMLProcessor.findNode(dataCriteriaXMLProcessor.getOriginalDoc(), - xpathForQDMEntry); - if (qmdEntryIDNode == null) { - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, me.getSimpleXmlProcessor(), null); - } - } - } - - /** - * Generate Item Count qdm entries. - * - * @param me - * the me - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param qdmNodeList - * the qdm node list - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateItemCountQDMEntries(MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, - NodeList qdmNodeList) throws XPathExpressionException { - for (int j = 0; j < qdmNodeList.getLength(); j++) { - Node qdmNode = qdmNodeList.item(j); - String qdmName = qdmNode.getAttributes().getNamedItem("name").getNodeValue(); - String qdmDatatype = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String qdmUUID = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); - String qdmExtension = qdmName.replaceAll("\\s", "") + "_" + qdmDatatype.replaceAll("\\s", ""); - if (qdmNode.getAttributes().getNamedItem("instance") != null) { - String instanceOfValue = qdmNode.getAttributes().getNamedItem("instance").getNodeValue(); - String newExtension = instanceOfValue.replaceAll("\\s", "") + "_" + qdmExtension; - qdmExtension = newExtension; - } - String xpathForQDMEntry = "/root/component/dataCriteriaSection/entry/*/id[@root='" + qdmUUID - + "'][@extension=\"" + qdmExtension + "\"]"; - Node qmdEntryIDNode = dataCriteriaXMLProcessor.findNode(dataCriteriaXMLProcessor.getOriginalDoc(), - xpathForQDMEntry); - if (qmdEntryIDNode == null) { - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, me.getSimpleXmlProcessor(), null); - } - } - } - - /** - * Generate default supplemental data qdm entries. - * - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param supplementalQDMNodeList - * the supplemental qdm node list - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateSupplementalDataQDMEntries(XmlProcessor simpleXmlprocessor, - XmlProcessor dataCriteriaXMLProcessor, NodeList supplementalQDMNodeList) throws XPathExpressionException { - - if (supplementalQDMNodeList == null) { - return; - } - - for (int i = 0; i < supplementalQDMNodeList.getLength(); i++) { - Node qdmNode = supplementalQDMNodeList.item(i); - // generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, qdmNode); - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, null); - } - } - - /** - * Gets the UUID string. - * - * @param uuidList - * the uuid list - * @return the UUID string - */ - private String getUUIDString(List uuidList) { - String uuidXPathString = ""; - for (String uuidString : uuidList) { - uuidXPathString += "@uuid = '" + uuidString + "' or"; - } - - uuidXPathString = uuidXPathString.substring(0, uuidXPathString.lastIndexOf(" or")); - return uuidXPathString; - } - - /** - * This method will populate a map of all reference elements for the Occurrence - * elements. - * - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param occurQdmNoAttributeNodeList - * the occur qdm no attribute node list - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateOccurrenceQDMEntries(XmlProcessor simpleXmlprocessor, XmlProcessor dataCriteriaXMLProcessor, - NodeList occurQdmNoAttributeNodeList) throws XPathExpressionException { - - Map map = new HashMap(); - - for (int i = 0; i < occurQdmNoAttributeNodeList.getLength(); i++) { - Node occurQdmNode = occurQdmNoAttributeNodeList.item(i); - String datatype = occurQdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String oid = occurQdmNode.getAttributes().getNamedItem(OID).getNodeValue(); - - if (!map.containsKey(datatype + "-" + oid)) { - map.put(datatype + "-" + oid, occurQdmNode); - } - } - - for (Node occurNode : map.values()) { - String datatype = occurNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String oid = occurNode.getAttributes().getNamedItem(OID).getNodeValue(); - - String xpath = "/measure/elementLookUp/qdm[@datatype != 'attribute'][not(@instance)][@oid = '" + oid - + "'][@datatype = \"" + datatype + "\"]"; - Node nodeToUse = simpleXmlprocessor.findNode(simpleXmlprocessor.getOriginalDoc(), xpath); - boolean forceGenerate = true; - if (nodeToUse == null) { - nodeToUse = occurNode.cloneNode(true); - nodeToUse.getAttributes().removeNamedItem("instance"); - forceGenerate = false; - } - - generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, nodeToUse, forceGenerate); - occurrenceMap.put(datatype + "-" + oid, nodeToUse); - } - } - - /** - * Generate qdm entries. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param qdmNoAttributeNodeList - * the qdm no attribute node list - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateQDMEntries(XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, - NodeList qdmNoAttributeNodeList) throws XPathExpressionException { - - if (qdmNoAttributeNodeList == null) { - return; - } - - for (int i = 0; i < qdmNoAttributeNodeList.getLength(); i++) { - Node qdmNode = qdmNoAttributeNodeList.item(i); - generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, qdmNode); - } - } - - /** - * Generate qdm entry. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param qdmNode - * the qdm node - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateQDMEntry(XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node qdmNode) - throws XPathExpressionException { - generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, qdmNode, false); - } - - /** - * Generate qdm entry. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param qdmNode - * the qdm node - * @param forceGenerate - * the force generate - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateQDMEntry(XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node qdmNode, - boolean forceGenerate) throws XPathExpressionException { - String qdmUUID = qdmNode.getAttributes().getNamedItem(UUID).getNodeValue(); - - String xPathForIndividualElementRefs = "/measure/subTreeLookUp//elementRef[@id='" + qdmUUID - + "'][not(attribute)]"; - NodeList elementRefList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xPathForIndividualElementRefs); - if (forceGenerate || (elementRefList.getLength() > 0)) { - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, null); - } - } - - /** - * Generate qdm attribute entries. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param qdmAttributeNodeList - * the qdm attribute node list - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateQDMAttributeEntries(XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, - NodeList qdmAttributeNodeList) throws XPathExpressionException { - if (qdmAttributeNodeList != null) { - for (int i = 0; i < qdmAttributeNodeList.getLength(); i++) { - Node attributeQDMNode = qdmAttributeNodeList.item(i); - String qdmUUID = attributeQDMNode.getAttributes().getNamedItem(UUID).getNodeValue(); - - // Generate entries for Negation Rationale - generateNegationRationaleEntries(dataCriteriaXMLProcessor, simpleXmlprocessor, attributeQDMNode, - qdmUUID); - - // Generate entries for "Value Set" attributes - generateValueSetAttribEntries(dataCriteriaXMLProcessor, simpleXmlprocessor, attributeQDMNode, qdmUUID, - "Value Set"); - } - } - // Generate entries for "Check if Present", attributes - generateNonValuesetAttribEntries(dataCriteriaXMLProcessor, simpleXmlprocessor); - generateDateTimeAttributeEntries(dataCriteriaXMLProcessor, simpleXmlprocessor); - } - - /** - * Generate negation rationale entries. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - * @param qdmUUID - * the qdm uuid - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateNegationRationaleEntries(XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor simpleXmlprocessor, Node attributeQDMNode, String qdmUUID) throws XPathExpressionException { - String xPathForAttributeUse = "/measure/subTreeLookUp/subTree//elementRef/attribute[@qdmUUID='" + qdmUUID - + "'][@name='negation rationale']"; - NodeList usedAttributeNodeList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xPathForAttributeUse); - if (usedAttributeNodeList == null) { - return; - } - - for (int j = 0; j < usedAttributeNodeList.getLength(); j++) { - Node attributeNode = usedAttributeNodeList.item(j); - Node parentElementRefNode = attributeNode.getParentNode(); - String qdmNodeUUID = parentElementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - - String xPathForQDM = "/measure/elementLookUp/qdm[@uuid='" + qdmNodeUUID + "']"; - Node qdmNode = simpleXmlprocessor.findNode(simpleXmlprocessor.getOriginalDoc(), xPathForQDM); - - if (qdmNode == null) { - continue; - } - - // We need some way of letting the methods downstream know that this is a - // "negation rationale" attribute w/o sending the tag node. - Node clonedAttributeQDMNode = attributeQDMNode.cloneNode(false); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_NAME, NEGATION_RATIONALE, null); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_MODE, VALUE_SET, null); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_UUID, - attributeNode.getAttributes().getNamedItem("attrUUID").getNodeValue(), null); - - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, clonedAttributeQDMNode); - - } - } - - /** - * Generate value set attrib entries. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - * @param qdmUUID - * the qdm uuid - * @param modeValue - * the mode value - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateValueSetAttribEntries(XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, - Node attributeQDMNode, String qdmUUID, String modeValue) throws XPathExpressionException { - String xPathForAttributeUse = "/measure/subTreeLookUp/subTree//elementRef/attribute[@qdmUUID='" + qdmUUID - + "'][@name != 'negation rationale'][@mode = '" + modeValue + "']"; - NodeList usedAttributeNodeList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xPathForAttributeUse); - - if (usedAttributeNodeList == null) { - return; - } - - for (int j = 0; j < usedAttributeNodeList.getLength(); j++) { - Node attributeNode = usedAttributeNodeList.item(j); - Node parentElementRefNode = attributeNode.getParentNode(); - String qdmNodeUUID = parentElementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - - String xPathForQDM = "/measure/elementLookUp/qdm[@uuid='" + qdmNodeUUID + "']"; - Node qdmNode = simpleXmlprocessor.findNode(simpleXmlprocessor.getOriginalDoc(), xPathForQDM); - - if (qdmNode == null) { - continue; - } - - // We need some way of letting the methods downstream know the name of this - // attribute w/o sending the tag node. - Node clonedAttributeQDMNode = attributeQDMNode.cloneNode(false); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_NAME, - attributeNode.getAttributes().getNamedItem(NAME).getNodeValue(), null); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_MODE, - attributeNode.getAttributes().getNamedItem("mode").getNodeValue(), null); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_UUID, - attributeNode.getAttributes().getNamedItem("attrUUID").getNodeValue(), null); - - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, clonedAttributeQDMNode); - } - } - - /** - * This method will look for attributes of mode = 'Check if Present', 'Equal - * To', 'Less Than (or Equal)', Greater than (or Equal). - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateNonValuesetAttribEntries(XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor simpleXmlprocessor) throws XPathExpressionException { - String xPathForAttributeUse = "/measure/subTreeLookUp/subTree//elementRef/attribute[@mode = 'Check if Present' or @mode='Equal To' or starts-with(@mode,'Less Than') or starts-with(@mode, 'Greater Than')]" - + "[@name != 'negation rationale' and @name != '" + START_DATETIME + "' and @name !='" + STOP_DATETIME - + "' " + "" + "and @name != '" + FACILITY_LOCATION_ARRIVAL_DATETIME + "' and @name != '" - + FACILITY_LOCATION_DEPARTURE_DATETIME + "' and @name != '" + FACILITY_LOCATION + "' and @name != '" - + ADMISSION_DATETIME + "' and @name != '" + DISCHARGE_DATETIME + "' and @name != '" + ACTIVE_DATETIME - + "' and @name != '" + INCISION_DATETIME + "' and @name != '" + DATE + "' and @name != '" + TIME - + "' and @name != '" + REMOVAL_DATETIME + "' and @name != '" + SIGNED_DATETIME + "' and @name != '" - + ABATEMENT_DATETIME + "'" + "and @name != '" + RECORDED_DATETIME + "' and @name != '" + ONSET_DATETIME - + "']"; - NodeList usedAttributeNodeList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xPathForAttributeUse); - - if (usedAttributeNodeList == null) { - return; - } - - for (int j = 0; j < usedAttributeNodeList.getLength(); j++) { - Node attributeNode = usedAttributeNodeList.item(j); - Node parentElementRefNode = attributeNode.getParentNode(); - String qdmNodeUUID = parentElementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - - String xPathForQDM = "/measure/elementLookUp/qdm[@uuid='" + qdmNodeUUID + "']"; - Node qdmNode = simpleXmlprocessor.findNode(simpleXmlprocessor.getOriginalDoc(), xPathForQDM); - - if (qdmNode == null) { - continue; - } - - // We need some way of letting the methods downstream know the name of this - // attribute w/o sending the tag node. - Node clonedAttributeQDMNode = attributeNode.cloneNode(false); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_NAME, - attributeNode.getAttributes().getNamedItem(NAME).getNodeValue(), null); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_MODE, - attributeNode.getAttributes().getNamedItem("mode").getNodeValue(), null); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_UUID, - attributeNode.getAttributes().getNamedItem("attrUUID").getNodeValue(), null); - - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, clonedAttributeQDMNode); - } - } - - /** - * Generate date time attribute entries. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateDateTimeAttributeEntries(XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor simpleXmlprocessor) throws XPathExpressionException { - - String xPathForAttributeUse = "/measure/subTreeLookUp/subTree//elementRef/attribute" + "[@name = '" - + START_DATETIME + "' or @name='" + STOP_DATETIME + "' or @name = '" - + FACILITY_LOCATION_ARRIVAL_DATETIME + "' or @name = '" + FACILITY_LOCATION_DEPARTURE_DATETIME - + "' or @name = '" + FACILITY_LOCATION + "' or @name ='" + ADMISSION_DATETIME + "' or @name ='" - + DISCHARGE_DATETIME + "'" + "or @name ='" + ACTIVE_DATETIME + "' or @name ='" + INCISION_DATETIME - + "' or @name ='" + DATE + "' or @name ='" + TIME + "'" + "or @name ='" + REMOVAL_DATETIME - + "' or @name ='" + SIGNED_DATETIME + "' or @name ='" + ONSET_DATETIME + "' or @name ='" - + ABATEMENT_DATETIME + "' " + "or @name ='" + RECORDED_DATETIME + "']" - + "[@mode='Equal To' or starts-with(@mode,'Less Than') or starts-with(@mode, 'Greater Than') or @mode='Check if Present']"; - - NodeList usedAttributeNodeList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xPathForAttributeUse); - - if (usedAttributeNodeList == null) { - return; - } - - for (int j = 0; j < usedAttributeNodeList.getLength(); j++) { - Node attributeNode = usedAttributeNodeList.item(j); - Node parentElementRefNode = attributeNode.getParentNode(); - String qdmNodeUUID = parentElementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - - String xPathForQDM = "/measure/elementLookUp/qdm[@uuid='" + qdmNodeUUID + "']"; - Node qdmNode = simpleXmlprocessor.findNode(simpleXmlprocessor.getOriginalDoc(), xPathForQDM); - - if (qdmNode == null) { - continue; - } - - // We need some way of letting the methods downstream know the name of this - // attribute w/o sending the tag node. - Node clonedAttributeQDMNode = attributeNode.cloneNode(false); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_NAME, - attributeNode.getAttributes().getNamedItem(NAME).getNodeValue(), null); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_MODE, - attributeNode.getAttributes().getNamedItem("mode").getNodeValue(), null); - clonedAttributeQDMNode.setUserData(ATTRIBUTE_UUID, - attributeNode.getAttributes().getNamedItem("attrUUID").getNodeValue(), null); - String attrDate = ""; - if (attributeNode.getAttributes().getNamedItem("attrDate") != null) { - attrDate = attributeNode.getAttributes().getNamedItem("attrDate").getNodeValue(); - } - clonedAttributeQDMNode.setUserData(ATTRIBUTE_DATE, attrDate, null); - - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, clonedAttributeQDMNode); - } - } - - /** - * Create xml for data criteria. - * - * @param qdmNode - * the qdm node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - * @return void - */ - private void createXmlForDataCriteria(Node qdmNode, XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor simpleXmlprocessor, Node attributeQDMNode) { - String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); - String xPathForTemplate = "/templates/template[text()='" + dataType.toLowerCase() + "']"; - String actNodeStr = ""; - try { - - Node templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xPathForTemplate); - if (templateNode != null) { - String attrClass = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); - String xpathForAct = "/templates/acts/act[@a_id='" + attrClass + "']"; - Node actNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xpathForAct); - if (actNode != null) { - actNodeStr = actNode.getTextContent(); - } - - createDataCriteriaElementTag(actNodeStr, templateNode, qdmNode, dataCriteriaXMLProcessor, - simpleXmlprocessor, templateXMLProcessor, attributeQDMNode); - } - - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - - /** - * Gets the creates the data create element tag. - * - * @param actNodeStr - * the act node str - * @param templateNode - * the template node - * @param qdmNode - * the qdm node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param templateXMLProcessor - * - templateXmlProcessor - * @param attributeQDMNode - * - Attribute QDM Node. - * @throws XPathExpressionException - * the x path expression exception - */ - private void createDataCriteriaElementTag(String actNodeStr, Node templateNode, Node qdmNode, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, XmlProcessor templateXMLProcessor, - Node attributeQDMNode) throws XPathExpressionException { - String oidValue = templateNode.getAttributes().getNamedItem(OID).getNodeValue(); - String classCodeValue = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); - String moodValue = templateNode.getAttributes().getNamedItem(MOOD).getNodeValue(); - String statusValue = templateNode.getAttributes().getNamedItem("status").getNodeValue(); - String rootValue = qdmNode.getAttributes().getNamedItem(ID).getNodeValue(); - String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); - - String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); - String qdmTaxonomy = qdmNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); - String entryCommentText = dataType; - // Local variable changes. - String qdmLocalVariableName = qdmName + "_" + dataType; - String localVariableName = qdmLocalVariableName; - if (qdmNode.getAttributes().getNamedItem("instance") != null) { - qdmLocalVariableName = qdmNode.getAttributes().getNamedItem("instance").getNodeValue() + "_" - + qdmLocalVariableName; - localVariableName = qdmNode.getAttributes().getNamedItem("instance").getNodeValue() + "of" - + localVariableName; - } - qdmLocalVariableName = StringUtils.deleteWhitespace(qdmLocalVariableName); - if (attributeQDMNode != null) { - if (attributeQDMNode.getUserData(ATTRIBUTE_UUID) != null) { - qdmLocalVariableName = (String) attributeQDMNode.getUserData(ATTRIBUTE_UUID); - } - if (attributeQDMNode.getUserData(ATTRIBUTE_NAME) != null) { - entryCommentText = entryCommentText + " - " + attributeQDMNode.getUserData(ATTRIBUTE_NAME); - localVariableName = localVariableName + "_" + attributeQDMNode.getUserData(ATTRIBUTE_NAME); - } - if (attributeQDMNode.getUserData(ATTRIBUTE_MODE) != null) { - entryCommentText = entryCommentText + " With " + attributeQDMNode.getUserData(ATTRIBUTE_MODE); - localVariableName = localVariableName + "_" + attributeQDMNode.getUserData(ATTRIBUTE_MODE); - } - } - localVariableName = StringUtils.deleteWhitespace(localVariableName); - - Element dataCriteriaSectionElem = (Element) dataCriteriaXMLProcessor.getOriginalDoc() - .getElementsByTagName("dataCriteriaSection").item(0); - Element componentElem = (Element) dataCriteriaXMLProcessor.getOriginalDoc().getElementsByTagName("component") - .item(0); - Attr nameSpaceAttr = dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:xsi"); - nameSpaceAttr.setNodeValue(nameSpace); - componentElem.setAttributeNodeNS(nameSpaceAttr); - Attr qdmNameSpaceAttr = dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:qdm"); - qdmNameSpaceAttr.setNodeValue("urn:hhs-qdm:hqmf-r2-extensions:v1"); - componentElem.setAttributeNodeNS(qdmNameSpaceAttr); - // creating Entry Tag - Element entryElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("entry"); - entryElem.setAttribute(TYPE_CODE, "DRIV"); - // Local Variable Name Tag - Inside Entry tag. - Element localVarElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("localVariableName"); - localVarElem.setAttribute(VALUE, localVariableName + "_" + UUIDUtilClient.uuid(5)); - entryElem.appendChild(localVarElem); - Element dataCriteriaElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(actNodeStr); - entryElem.appendChild(dataCriteriaElem); - dataCriteriaElem.setAttribute(CLASS_CODE, classCodeValue); - dataCriteriaElem.setAttribute(MOOD_CODE, moodValue); - Element templateId = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TEMPLATE_ID); - dataCriteriaElem.appendChild(templateId); - Element itemChild = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); - itemChild.setAttribute(ROOT, oidValue); - if (templateNode.getAttributes().getNamedItem("addExtensionInTemplate") == null) { - - itemChild.setAttribute("extension", extensionValue); - } - templateId.appendChild(itemChild); - Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); - idElem.setAttribute(ROOT, rootValue); - idElem.setAttribute("extension", qdmLocalVariableName); - dataCriteriaElem.appendChild(idElem); - - boolean appendEntryElem = false; - String occurString = dataType + "-" + qdmOidValue; - - if (qdmNode.getAttributes().getNamedItem("instance") != null) { - generateOutboundForOccur(templateNode, qdmNode, dataCriteriaElem, occurString, dataCriteriaXMLProcessor, - simpleXmlprocessor); - entryCommentText = qdmNode.getAttributes().getNamedItem("instance").getNodeValue() + " " + entryCommentText; - appendEntryElem = true; - } else if (!occurrenceMap.containsKey(occurString) || (attributeQDMNode != null)) { - - String isAddCodeTag = templateNode.getAttributes().getNamedItem("addCodeTag").getNodeValue(); - if ("true".equalsIgnoreCase(isAddCodeTag)) { // Add Code Element to DataCriteria Element. - addCodeElementToDataCriteriaElement(templateNode, dataCriteriaXMLProcessor, qdmNode, dataCriteriaElem); - } - Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); - titleElem.setAttribute(VALUE, dataType); - dataCriteriaElem.appendChild(titleElem); - Element statusCodeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("statusCode"); - statusCodeElem.setAttribute(CODE, statusValue); - dataCriteriaElem.appendChild(statusCodeElem); - // Add value tag in entry element. - String addValueSetElement = templateNode.getAttributes().getNamedItem("addValueTag").getNodeValue(); - if ("true".equalsIgnoreCase(addValueSetElement)) { - Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(VALUE); - Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); - if (valueTypeAttr != null) { - valueElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); - } - - Node valueCodeSystem = templateNode.getAttributes().getNamedItem("valueCodeSystem"); - Node valueCode = templateNode.getAttributes().getNamedItem("valueCode"); - Node valueDisplayName = templateNode.getAttributes().getNamedItem("valueDisplayName"); - Node valueCodeSystemName = templateNode.getAttributes().getNamedItem("valueCodeSystemName"); - - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - if ((valueCode != null) && (valueCodeSystem != null)) { - valueElem.setAttribute("code", valueCode.getNodeValue()); - valueElem.setAttribute("codeSystem", valueCodeSystem.getNodeValue()); - if (valueCodeSystemName != null) { - valueElem.setAttribute("codeSystemName", valueCodeSystemName.getNodeValue()); - } - if (valueDisplayName != null) { - displayNameElem.setAttribute(VALUE, valueDisplayName.getNodeValue()); - } - } else { - valueElem.setAttribute("valueSet", qdmOidValue); - addValueSetVersion(qdmNode, valueElem); - displayNameElem.setAttribute(VALUE, HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) - + " " + qdmTaxonomy + " Value Set"); - } - if (displayNameElem.hasAttribute(VALUE)) { - valueElem.appendChild(displayNameElem); - } - - dataCriteriaElem.appendChild(valueElem); - } - if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { - appendSubTemplateNode(templateNode, dataCriteriaXMLProcessor, templateXMLProcessor, dataCriteriaElem, - qdmNode, attributeQDMNode); - } - - appendEntryElem = true; - } - if (appendEntryElem) { - if (attributeQDMNode != null) { - createDataCriteriaForAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, - attributeQDMNode, false); - } - dataCriteriaSectionElem.appendChild(entryElem); - } - - } - - /** - * Method to add valueSetVersion attribute in value element tag. - * - * @param qdmNode - * the qdm node - * @param valueElem - * the value elem - */ - protected void addValueSetVersion(Node qdmNode, Element valueElem) { - String valueSetVersion = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); - boolean addVersionToValueTag = false; - if ("1.0".equals(valueSetVersion) || "1".equals(valueSetVersion) || StringUtils.isBlank(valueSetVersion)) { - if (qdmNode.getAttributes().getNamedItem("expansionIdentifier") != null) { - valueSetVersion = "mat.vsac:profile:" - + qdmNode.getAttributes().getNamedItem("expansionIdentifier").getNodeValue(); - addVersionToValueTag = true; - } else { - addVersionToValueTag = false; - } - } else { - valueSetVersion = "mat.vsac:version:" + qdmNode.getAttributes().getNamedItem("version").getNodeValue(); - addVersionToValueTag = true; - } - if (addVersionToValueTag) { - valueElem.setAttribute("valueSetVersion", valueSetVersion); - } - } - - /** - * Generate outbound for occur. - * - * @param templateNode - * the template node - * @param qdmNode - * the qdm node - * @param dataCriteriaElem - * the data criteria elem - * @param occurString - * the occur string - */ - private void generateOutboundForOccur(Node templateNode, Node qdmNode, Element dataCriteriaElem, String occurString, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor) { - Node refNode = occurrenceMap.get(occurString); - - logger.debug("In generateOutboundForOccur()..refNode:" + refNode); - logger.debug("----------Occurance map:" + occurrenceMap); - - if (refNode != null) { - - try { - Node cloneRefNode = refNode.cloneNode(true); - String name = cloneRefNode.getAttributes().getNamedItem("name").getNodeValue(); - String occName = qdmNode.getAttributes().getNamedItem("instance").getNodeValue(); - cloneRefNode.getAttributes().getNamedItem("name").setNodeValue(occName + "_" + name); - - if (!occurrenceMap.containsKey(occName + occurString)) { - occurrenceMap.remove(occurString); - generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, cloneRefNode, true); - occurrenceMap.put(occurString, refNode); - occurrenceMap.put(occName + occurString, cloneRefNode); - } - - String refRootValue = cloneRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - - String refDatatype = cloneRefNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String refQdmName = cloneRefNode.getAttributes().getNamedItem("name").getNodeValue(); - String reExt = StringUtils.deleteWhitespace(refQdmName + "_" + refDatatype); - - Element outboundRelElem = dataCriteriaElem.getOwnerDocument().createElement("outboundRelationship"); - outboundRelElem.setAttribute("typeCode", "OCCR"); - - Element criteriaRefElem = dataCriteriaElem.getOwnerDocument().createElement("criteriaReference"); - String refClassCodeValue = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); - String refMoodValue = templateNode.getAttributes().getNamedItem(MOOD).getNodeValue(); - criteriaRefElem.setAttribute(CLASS_CODE, refClassCodeValue); - criteriaRefElem.setAttribute(MOOD_CODE, refMoodValue); - - Element idRelElem = dataCriteriaElem.getOwnerDocument().createElement(ID); - idRelElem.setAttribute(ROOT, refRootValue); - idRelElem.setAttribute("extension", reExt); - - criteriaRefElem.appendChild(idRelElem); - outboundRelElem.appendChild(criteriaRefElem); - dataCriteriaElem.appendChild(outboundRelElem); - Node templateIdNode = dataCriteriaElem.getElementsByTagName("templateId").item(0); - dataCriteriaElem.removeChild(templateIdNode); - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - } - - /** - * Add Code Element To data Criteria Element based on condition. - * - * @param templateNode - * - Node - * @param dataCriteriaXMLProcessor - * - XmlProcessor - * @param qdmNode - * the qdm node - * @param dataCriteriaElem - * - Element - */ - private void addCodeElementToDataCriteriaElement(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, - Node qdmNode, Element dataCriteriaElem) { - String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); - - String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); - String qdmTaxonomy = qdmNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); - - // Patient Characteristic data type - contains code tag with valueSetId - // attribute and no title and value set tag. - boolean isPatientChar = templateNode.getAttributes().getNamedItem("valueSetId") != null; - boolean isAddValueSetInCodeTrue = templateNode.getAttributes().getNamedItem("addValueSetInCode") != null; - boolean isIntervention = ("Intervention, Order".equals(dataType) || "Intervention, Performed".equals(dataType) - || "Intervention, Recommended".equals(dataType)); - if (isAddValueSetInCodeTrue) { - Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); - if (valueTypeAttr != null) { - codeElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); - } - codeElem.setAttribute("valueSet", qdmOidValue); - addValueSetVersion(qdmNode, codeElem); - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - String displayName = ""; - displayName = HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + " " + qdmTaxonomy - + " Value Set"; - displayNameElem.setAttribute(VALUE, displayName); - codeElem.appendChild(displayNameElem); - dataCriteriaElem.appendChild(codeElem); - - } else if (isPatientChar) { - Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - codeElem.setAttribute(templateNode.getAttributes().getNamedItem("valueSetId").getNodeValue(), qdmOidValue); - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - displayNameElem.setAttribute(VALUE, - HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + " " + qdmTaxonomy + " Value Set"); - codeElem.appendChild(displayNameElem); - dataCriteriaElem.appendChild(codeElem); - } else if (isIntervention) { - Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - codeElem.setAttribute("valueSet", qdmOidValue); - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - displayNameElem.setAttribute(VALUE, - HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + " " + qdmTaxonomy + " Value Set"); - codeElem.appendChild(displayNameElem); - dataCriteriaElem.appendChild(codeElem); - } else { - Element codeElement = createCodeForDatatype(templateNode, dataCriteriaXMLProcessor); - if (codeElement != null) { - dataCriteriaElem.appendChild(codeElement); - } - } - } - - /** - * This method is called for populating version/expansion Identifier of value - * set when value set attribute mode is applied. If version is most recent, 1.0 - * or 1 is returned. - * - * @param qdmNode - * @return version - */ - private String valueSetVersionStringValue(Node qdmNode) { - String version = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); - if ("1.0".equals(version) || "1".equals(version) || StringUtils.isBlank(version)) { - if (qdmNode.getAttributes().getNamedItem("expansionIdentifier") != null) { - version = "mat.vsac:profile:" + qdmNode.getAttributes().getNamedItem("expansionIdentifier").getNodeValue(); - } - } else { - version = "mat.vsac:version:" + qdmNode.getAttributes().getNamedItem("version").getNodeValue(); - } - return version; - } - - /** - * Add SubTemplate defined in Template.xml to data criteria Element. - * - * @param templateNode - * - Node - * @param dataCriteriaXMLProcessor - * - XmlProcessor for Data Criteria - * @param templateXMLProcessor - * -XmlProcessor for Template Xml. - * @param dataCriteriaElem - * - Element - * @param qdmNode - * the qdm node - * @param attributeQDMNode - * the attribute qdm node - * @throws XPathExpressionException - * the x path expression exception - */ - private void appendSubTemplateNode(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor templateXMLProcessor, Element dataCriteriaElem, Node qdmNode, Node attributeQDMNode) - throws XPathExpressionException { - String subTemplateName = templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); - Node subTemplateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName); - NodeList subTemplateNodeChilds = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "/child::node()"); - String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); - String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); - String qdmNameDataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String qdmTaxonomy = qdmNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); - if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { - String[] attributeToBeModified = subTemplateNode.getAttributes().getNamedItem("changeAttribute") - .getNodeValue().split(","); - for (String changeAttribute : attributeToBeModified) { - NodeList attributedToBeChangedInNode = null; - attributedToBeChangedInNode = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); - if (changeAttribute.equalsIgnoreCase(ID)) { - String rootId = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("root").setNodeValue(rootId); - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("extension") - .setNodeValue(UUIDUtilClient.uuid()); - } else if (changeAttribute.equalsIgnoreCase(CODE)) { - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("valueSet") - .setNodeValue(qdmOidValue); - String valueSetVersion = valueSetVersionStringValue(qdmNode); - if (valueSetVersion.contains("mat/vsacmodel")) { - Attr attrNode = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createAttribute("valueSetVersion"); - attrNode.setNodeValue(valueSetVersion); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attrNode); - } else { - if (attributedToBeChangedInNode.item(0).getAttributes() - .getNamedItem("valueSetVersion") != null) { - attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("valueSetVersion"); - } - } - - } else if (changeAttribute.equalsIgnoreCase(DISPLAY_NAME)) { - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("value") - .setNodeValue(HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + " " - + qdmTaxonomy + " value set"); - } else if (changeAttribute.equalsIgnoreCase(TITLE)) { - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("value") - .setNodeValue(qdmNameDataType); - } else if (changeAttribute.equalsIgnoreCase(ITEM)) { - for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { - Node itemNode = attributedToBeChangedInNode.item(count); - itemNode.getAttributes().getNamedItem("extension").setNodeValue(extensionValue); - } - - } - } - } - for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { - Node childNode = subTemplateNodeChilds.item(i); - Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); - XmlProcessor.clean(nodeToAttach); - dataCriteriaElem.appendChild(nodeToAttach); - } - } - - /** - * Method to append Facility Location attribute template to data type. This - * attribute can only have value ser and Check If present mode's and these are - * added to code tag. - * - * @param templateNode - * the template node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param templateXMLProcessor - * the template xml processor - * @param dataCriteriaElem - * the data criteria elem - * @param attrNode - * the attr node - * @throws XPathExpressionException - * the x path expression exception - */ - private void appendSubTemplateInFacilityAttribute(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor templateXMLProcessor, Element dataCriteriaElem, Node attrNode) - throws XPathExpressionException { - String subTemplateName = templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); - Node subTemplateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName); - NodeList subTemplateNodeChilds = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "/child::node()"); - if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { - NodeList attributedToBeChangedInNode = null; - String[] tagToBeModified = subTemplateNode.getAttributes().getNamedItem("changeAttribute").getNodeValue() - .split(","); - for (String changeAttribute : tagToBeModified) { - attributedToBeChangedInNode = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); - if (changeAttribute.equalsIgnoreCase(ID)) { - Node childNodes = attributedToBeChangedInNode.item(0).getFirstChild().getNextSibling(); - String rootId = (String) attrNode.getUserData(ATTRIBUTE_UUID); - childNodes.getAttributes().getNamedItem("root").setNodeValue(rootId); - childNodes.getAttributes().getNamedItem("extension") - .setNodeValue(StringUtils.deleteWhitespace((String) attrNode.getUserData(ATTRIBUTE_NAME))); - } else if (changeAttribute.equalsIgnoreCase(CODE)) { - String attrMode = (String) attrNode.getUserData(ATTRIBUTE_MODE); - if (VALUE_SET.equals(attrMode)) { - if (attributedToBeChangedInNode.item(0).hasAttributes()) { - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("flavorId"); - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("xsi:type"); - } - if (attributedToBeChangedInNode.item(0).hasChildNodes()) { - ((Element) attributedToBeChangedInNode.item(0)) - .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); - } - checkIfSelectedModeIsValueSet(templateXMLProcessor, attrNode, subTemplateNode, - (Element) attributedToBeChangedInNode.item(0)); - } else if (CHECK_IF_PRESENT.equals(attrMode)) { - if (attributedToBeChangedInNode.item(0).hasAttributes()) { - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("valueSet"); - } - if (attributedToBeChangedInNode.item(0).hasChildNodes()) { - ((Element) attributedToBeChangedInNode.item(0)) - .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); - } - checkIfSelectedModeIsPresent(templateXMLProcessor, attrNode, subTemplateNode, - (Element) attributedToBeChangedInNode.item(0)); - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("xsi:type"); - } - } else if (changeAttribute.equalsIgnoreCase(ITEM)) { - for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { - Node itemNode = attributedToBeChangedInNode.item(count); - itemNode.getAttributes().getNamedItem("extension").setNodeValue(extensionValue); - } - - } - } - } - for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { - Node childNode = subTemplateNodeChilds.item(i); - Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); - XmlProcessor.clean(nodeToAttach); - checkIfOutBoundOcc(dataCriteriaElem, nodeToAttach); - } - } - - /** - * Append sub template with order attribute. - * - * @param templateNode - * the template node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param templateXMLProcessor - * the template xml processor - * @param dataCriteriaElem - * the data criteria elem - * @param qdmNode - * the qdm node - * @param attrNode - * the attr node - * @throws XPathExpressionException - * the x path expression exception - */ - private void appendSubTemplateWithOrderAttribute(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor templateXMLProcessor, Element dataCriteriaElem, Node qdmNode, Node attrNode) - throws XPathExpressionException { - String subTemplateName = templateNode.getAttributes().getNamedItem("includeOtherSubTemplate").getNodeValue(); - Node subTemplateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName); - NodeList subTemplateNodeChilds = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "/child::node()"); - boolean isOrder = templateNode.getAttributes().getNamedItem("typeOrder").getNodeValue() != null; - if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { - NodeList attributedToBeChangedInNode = null; - String[] tagToBeModified = subTemplateNode.getAttributes().getNamedItem("changeAttribute").getNodeValue() - .split(","); - for (String changeAttribute : tagToBeModified) { - attributedToBeChangedInNode = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); - if (changeAttribute.equalsIgnoreCase(ID)) { - Node childNodes = attributedToBeChangedInNode.item(0).getFirstChild().getNextSibling(); - String rootId = (String) attrNode.getUserData(ATTRIBUTE_UUID); - childNodes.getAttributes().getNamedItem("root").setNodeValue(rootId); - childNodes.getAttributes().getNamedItem("extension") - .setNodeValue(StringUtils.deleteWhitespace((String) attrNode.getUserData(ATTRIBUTE_NAME))); - } else if (changeAttribute.equalsIgnoreCase(ITEM)) { - for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { - Node itemNode = attributedToBeChangedInNode.item(count); - itemNode.getAttributes().getNamedItem("extension").setNodeValue(extensionValue); - } - } - } - } - - for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { - Node childNode = subTemplateNodeChilds.item(i); - Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); - XmlProcessor.clean(nodeToAttach); - checkIfOutBoundOcc(dataCriteriaElem, nodeToAttach); - } - Element timeNode = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TIME); - generateDateTimeAttributesTag(timeNode, attrNode, dataCriteriaElem, dataCriteriaXMLProcessor, isOrder); - } - - /** - * Append sub template and add value tag based on mode. - * - * @param templateNode - * the template node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param templateXMLProcessor - * the template xml processor - * @param dataCriteriaElem - * the data criteria elem - * @param attrNode - * the attr node - * @throws XPathExpressionException - * the x path expression exception - */ - protected void appendSubTemplateAndAddValueTagBasedOnMode(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor templateXMLProcessor, Element dataCriteriaElem, Node attrNode) - throws XPathExpressionException { - - String subTemplateName = templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); - Node subTemplateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName); - - if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { - NodeList attributedToBeChangedInNode = null; - String[] tagToBeModified = subTemplateNode.getAttributes().getNamedItem("changeAttribute").getNodeValue() - .split(","); - for (String changeAttribute : tagToBeModified) { - attributedToBeChangedInNode = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); - if (changeAttribute.equalsIgnoreCase(ID)) { - String rootId = (String) attrNode.getUserData(ATTRIBUTE_UUID); - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("root").setNodeValue(rootId); - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("extension") - .setNodeValue(UUIDUtilClient.uuid()); - } else if (changeAttribute.equalsIgnoreCase(ITEM)) { - for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { - Node itemNode = attributedToBeChangedInNode.item(count); - itemNode.getAttributes().getNamedItem("extension").setNodeValue(UUIDUtilClient.uuid()); - String rootId = (String) attrNode.getUserData(ATTRIBUTE_UUID); - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("root").setNodeValue(rootId); - } - - } else if (changeAttribute.equalsIgnoreCase(VALUE)) { - String attrMode = (String) attrNode.getUserData(ATTRIBUTE_MODE); - if (CHECK_IF_PRESENT.equals(attrMode)) { - if (attributedToBeChangedInNode.item(0).hasAttributes()) { - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("valueSet"); - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("flavorId"); - } - String elementName = templateNode.getAttributes().getNamedItem("addTagInValueSet") - .getNodeValue(); - NodeList el = attributedToBeChangedInNode.item(0).getChildNodes(); - Element childElement = null; - if (el.getLength() == 0) { - childElement = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createElement(elementName); - } else { - childElement = (Element) el; - if (childElement.hasChildNodes()) { - for (int j = childElement.getChildNodes().getLength(); j > 0; j--) { - Node ChildNode = childElement.getChildNodes().item(j - 1); - childElement.removeChild(ChildNode); - } - - } - childElement = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createElement(elementName); - } - childElement.setAttribute(FLAVOR_ID, "ANY.NONNULL"); - attributedToBeChangedInNode.item(0).appendChild(childElement); - } else if (attrMode.startsWith(Generator.LESS_THAN) || attrMode.startsWith(Generator.GREATER_THAN) - || attrMode.equals(Generator.EQUAL_TO)) { - - String elementName = templateNode.getAttributes().getNamedItem("addTagInValueSet") - .getNodeValue(); - NodeList el = attributedToBeChangedInNode.item(0).getChildNodes(); - Element childElement = null; - if (el.getLength() == 0) { - childElement = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createElement(elementName); - } else { - childElement = (Element) el; - if (childElement.hasChildNodes()) { - for (int j = childElement.getChildNodes().getLength(); j > 0; j--) { - Node ChildNode = childElement.getChildNodes().item(j - 1); - childElement.removeChild(ChildNode); - } - - } - childElement = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createElement(elementName); - } - Node unitAttrib = attrNode.getAttributes().getNamedItem("unit"); - if (attrMode.equals(Generator.EQUAL_TO)) { - childElement.setAttribute("value", - attrNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - childElement.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); - } - attributedToBeChangedInNode.item(0).appendChild(childElement); - } else if (attrMode.startsWith(Generator.LESS_THAN)) { - Element uncertainRangeNode = childElement.getOwnerDocument() - .createElement("uncertainRange"); - if (attrMode.equals(Generator.LESS_THAN)) { - uncertainRangeNode.setAttribute("highClosed", "false"); - } - Element lowNode = childElement.getOwnerDocument().createElement(LOW); - lowNode.setAttribute(XSI_TYPE, "PQ"); - lowNode.setAttribute("nullFlavor", "NINF"); - - Element highNode = childElement.getOwnerDocument().createElement(HIGH); - highNode.setAttribute(XSI_TYPE, "PQ"); - highNode.setAttribute("value", - attrNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - highNode.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); - } - uncertainRangeNode.appendChild(lowNode); - uncertainRangeNode.appendChild(highNode); - childElement.appendChild(uncertainRangeNode); - attributedToBeChangedInNode.item(0).appendChild(childElement); - } else if (attrMode.startsWith(Generator.GREATER_THAN)) { - Element uncertainRangeNode = childElement.getOwnerDocument() - .createElement("uncertainRange"); - if (attrMode.equals(Generator.GREATER_THAN)) { - uncertainRangeNode.setAttribute("lowClosed", "false"); - } - Element lowNode = childElement.getOwnerDocument().createElement(LOW); - lowNode.setAttribute(XSI_TYPE, "PQ"); - lowNode.setAttribute("value", - attrNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - lowNode.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); - } - Element highNode = childElement.getOwnerDocument().createElement(HIGH); - highNode.setAttribute(XSI_TYPE, "PQ"); - highNode.setAttribute("nullFlavor", "PINF"); - uncertainRangeNode.appendChild(lowNode); - uncertainRangeNode.appendChild(highNode); - childElement.appendChild(uncertainRangeNode); - attributedToBeChangedInNode.item(0).appendChild(childElement); - } - } - } else if (changeAttribute.equalsIgnoreCase(CODE)) { - String attrMode = (String) attrNode.getUserData(ATTRIBUTE_MODE); - if (CHECK_IF_PRESENT.equals(attrMode)) { - if (attributedToBeChangedInNode.item(0).hasAttributes()) { - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("valueSet"); - } - if (attributedToBeChangedInNode.item(0).hasChildNodes()) { - attributedToBeChangedInNode.item(0) - .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); - } - Attr attribute = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createAttribute("flavorId"); - attribute.setNodeValue("ANY.NONNULL"); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attribute); - } else if (VALUE_SET.equalsIgnoreCase(attrMode)) { - - String valueSetVersion = valueSetVersionStringValue(attrNode); - if (valueSetVersion.contains("mat/vsacmodel")) { - Attr valuesetVersionAttr = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createAttribute("valueSetVersion"); - valuesetVersionAttr.setNodeValue(valueSetVersion); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(valuesetVersionAttr); - } else { - if (attributedToBeChangedInNode.item(0).getAttributes() - .getNamedItem("valueSetVersion") != null) { - attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("valueSetVersion"); - } - } - if (attributedToBeChangedInNode.item(0).hasAttributes()) { - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("flavorId"); - } - if (attributedToBeChangedInNode.item(0).hasChildNodes()) { - ((Element) attributedToBeChangedInNode.item(0)) - .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); - } - String attributeValueSetName = attrNode.getAttributes().getNamedItem(NAME).getNodeValue(); - String attributeOID = attrNode.getAttributes().getNamedItem(OID).getNodeValue(); - String attributeTaxonomy = attrNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); - Attr attribute = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createAttribute("valueSet"); - attribute.setNodeValue(attributeOID); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attribute); - Element valueDisplayNameElem = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createElement(DISPLAY_NAME); - valueDisplayNameElem.setAttribute(VALUE, - HQMFDataCriteriaGenerator.removeOccurrenceFromName(attributeValueSetName) + " " - + attributeTaxonomy + " Value Set"); - attributedToBeChangedInNode.item(0).appendChild(valueDisplayNameElem); - - } - } - } - } - for (int i = 0; i < subTemplateNode.getChildNodes().getLength(); i++) { - Node childNode = subTemplateNode.getChildNodes().item(i); - Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); - XmlProcessor.clean(nodeToAttach); - checkIfOutBoundOcc(dataCriteriaElem, nodeToAttach); - } - } - - /** - * This method will look for attributes used in the subTree logic and then - * generate appropriate data criteria entries. - * - * @param qdmNode - * the qdm node - * @param dataCriteriaElem - * the data criteria elem - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - * @param isFunctionAttributeFlow - * - boolean function Attribute flow. - * @throws XPathExpressionException - * the x path expression exception - */ - private void createDataCriteriaForAttributes(Node qdmNode, Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node attributeQDMNode, - boolean isFunctionAttributeFlow) throws XPathExpressionException { - String attributeName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); - String attributeMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); - boolean checkForMode = false; - switch (attributeName.toLowerCase()) { - case NEGATION_RATIONALE: - if (!isFunctionAttributeFlow) { - generateNegationRationalEntries(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, - attributeQDMNode); - } - break; - case START_DATETIME: - case STOP_DATETIME: - case SIGNED_DATETIME: - case RECORDED_DATETIME: - case ABATEMENT_DATETIME: - generateOrderTypeAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, - attributeQDMNode); - break; - case ADMISSION_DATETIME: - case DISCHARGE_DATETIME: - case REMOVAL_DATETIME: - case ACTIVE_DATETIME: - case TIME: - case DATE: - case ONSET_DATETIME: - generateDateTimeAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, - attributeQDMNode); - break; - case FACILITY_LOCATION_ARRIVAL_DATETIME: - case FACILITY_LOCATION_DEPARTURE_DATETIME: - generateFacilityLocationTypeAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, - simpleXmlprocessor, attributeQDMNode); - break; - case DOSE: - case LENGTH_OF_STAY: - generateDoseTypeAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, - attributeQDMNode); - break; - case REFILLS: - generateRepeatNumber(qdmNode, dataCriteriaXMLProcessor, dataCriteriaElem, attributeQDMNode, REPEAT_NUMBER); - break; - case DISCHARGE_STATUS: - generateDischargeStatus(qdmNode, dataCriteriaXMLProcessor, dataCriteriaElem, attributeQDMNode); - break; - case INCISION_DATETIME: - generateIncisionDateTimeTypeAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, - simpleXmlprocessor, attributeQDMNode); - break; - case PRINCIPAL_DIAGNOSIS: - case DIAGNOSIS: - generatePrincipalAndDiagnosisAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, - simpleXmlprocessor, attributeQDMNode); - break; - default: - checkForMode = true; - break; - } - if (checkForMode) { - if (VALUE_SET.equals(attributeMode) || CHECK_IF_PRESENT.equals(attributeMode) - || attributeMode.startsWith(LESS_THAN) || attributeMode.startsWith(GREATER_THAN) - || EQUAL_TO.equals(attributeMode)) { - // handle "Value Set", "Check If Present" and comparison(less than, greater - // than, equals) mode - generateOtherAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, - attributeQDMNode); - } - } - } - - /** - * Generate dose type attributes. - * - * @param qdmNode - * the qdm node - * @param dataCriteriaElem - * the data criteria elem - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - * @throws XPathExpressionException - * the x path expression exception - */ - protected void generateDoseTypeAttributes(Node qdmNode, Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node attributeQDMNode) - throws XPathExpressionException { - - String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); - String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); - Node attrOID = attributeQDMNode.getAttributes().getNamedItem(OID); - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); - Node templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/AttrTemplate[text()='" + attrName.toLowerCase() + "']"); - Node targetNode = templateNode.getAttributes().getNamedItem("target"); - Element targetQuantityTag = null; - if (targetNode != null) { - targetQuantityTag = dataCriteriaElem.getOwnerDocument().createElement(targetNode.getNodeValue()); - } - Node unitAttrib = attributeQDMNode.getAttributes().getNamedItem("unit"); - if (CHECK_IF_PRESENT.equals(attrMode)) { - targetQuantityTag.setAttribute(FLAVOR_ID, "ANY.NONNULL"); - } else if (VALUE_SET.equals(attrMode)) { - targetQuantityTag.setAttribute(NULL_FLAVOR, "UNK"); - Element translationNode = dataCriteriaElem.getOwnerDocument().createElement(TRANSLATION); - translationNode.setAttribute("valueSet", attrOID.getNodeValue()); - - String valueSetVersion = valueSetVersionStringValue(attributeQDMNode); - if (valueSetVersion.contains("mat/vsacmodel")) { - translationNode.setAttribute("valueSetVersion", valueSetVersion); - } else { - if (translationNode.getAttributes().getNamedItem("valueSetVersion") != null) { - translationNode.getAttributes().removeNamedItem("valueSetVersion"); - } - } - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - String newQdmName = HQMFDataCriteriaGenerator - .removeOccurrenceFromName(attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue()); - displayNameElem.setAttribute(VALUE, newQdmName + " " - + attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue() + " Value Set"); - translationNode.appendChild(displayNameElem); - targetQuantityTag.appendChild(translationNode); - // } - } else if (attrMode.startsWith(Generator.LESS_THAN) || attrMode.startsWith(Generator.GREATER_THAN) - || attrMode.equals(Generator.EQUAL_TO)) { - if (attrMode.equals(Generator.EQUAL_TO)) { - targetQuantityTag.setAttribute("value", - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - targetQuantityTag.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); - } - } else if (attrMode.startsWith(Generator.LESS_THAN)) { - Element uncertainRangeNode = dataCriteriaElem.getOwnerDocument().createElement("uncertainRange"); - if (attrMode.equals(Generator.LESS_THAN)) { - uncertainRangeNode.setAttribute("highClosed", "false"); - } - Element lowNode = dataCriteriaElem.getOwnerDocument().createElement(LOW); - lowNode.setAttribute("xsi:type", "PQ"); - lowNode.setAttribute("nullFlavor", "NINF"); - Element highNode = dataCriteriaElem.getOwnerDocument().createElement(HIGH); - highNode.setAttribute("xsi:type", "PQ"); - highNode.setAttribute("value", - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - highNode.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); - } - - uncertainRangeNode.appendChild(lowNode); - uncertainRangeNode.appendChild(highNode); - targetQuantityTag.appendChild(uncertainRangeNode); - - } else if (attrMode.startsWith(Generator.GREATER_THAN)) { - Element uncertainRangeNode = dataCriteriaElem.getOwnerDocument().createElement("uncertainRange"); - if (attrMode.equals(Generator.GREATER_THAN)) { - uncertainRangeNode.setAttribute("lowClosed", "false"); - } - Element lowNode = dataCriteriaElem.getOwnerDocument().createElement(LOW); - lowNode.setAttribute("xsi:type", "PQ"); - lowNode.setAttribute("value", - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - lowNode.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); - } - Element highNode = dataCriteriaElem.getOwnerDocument().createElement(HIGH); - highNode.setAttribute("xsi:type", "PQ"); - highNode.setAttribute("nullFlavor", "PINF"); - uncertainRangeNode.appendChild(lowNode); - uncertainRangeNode.appendChild(highNode); - targetQuantityTag.appendChild(uncertainRangeNode); - } - } - String insertAfterNodeName = templateNode.getAttributes().getNamedItem("insertAfterNode").getNodeValue(); - if (insertAfterNodeName != null) { - if (dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0) != null) { - Node outBoundElement = dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0) - .getNextSibling(); - if (outBoundElement != null) { - outBoundElement.getParentNode().insertBefore(targetQuantityTag, outBoundElement); - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetQuantityTag); - } - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetQuantityTag); - } - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetQuantityTag); - } - - } - - /** - * Generate facility location type attributes. - * - * @param qdmNode - * the qdm node - * @param dataCriteriaElem - * the data criteria elem - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - * @throws XPathExpressionException - * the x path expression exception - */ - protected void generateFacilityLocationTypeAttributes(Node qdmNode, Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node attributeQDMNode) - throws XPathExpressionException { - String attributeName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); - Node templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/AttrTemplate[text()='" + attributeName.toLowerCase() + "']"); - if (templateNode == null) { - return; - } - if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { - appendSubTemplateInFacilityAttribute(templateNode, dataCriteriaXMLProcessor, templateXMLProcessor, - dataCriteriaElem, attributeQDMNode); - } - generateDateTimeAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, - attributeQDMNode); - } - - /** - * Generate incision date time type attributes. - * - * @param qdmNode - * the qdm node - * @param dataCriteriaElem - * the data criteria elem - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - * @throws XPathExpressionException - * the x path expression exception - */ - protected void generateIncisionDateTimeTypeAttributes(Node qdmNode, Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node attributeQDMNode) - throws XPathExpressionException { - String attributeName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); - Node templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/AttrTemplate[text()='" + attributeName.toLowerCase() + "']"); - if (templateNode == null) { - return; - } - if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { - appendSubTemplateNode(templateNode, dataCriteriaXMLProcessor, templateXMLProcessor, dataCriteriaElem, - qdmNode, attributeQDMNode); - } - generateDateTimeAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, - attributeQDMNode); - } - - /** - * Generate order type attributes. - * - * @param qdmNode - * the qdm node - * @param dataCriteriaElem - * the data criteria elem - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - * @throws XPathExpressionException - * the x path expression exception - */ - protected void generateOrderTypeAttributes(Node qdmNode, Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node attributeQDMNode) - throws XPathExpressionException { - String qdmName = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); - Node templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/template[text()='" + qdmName.toLowerCase() + "']"); - if (templateNode == null) { - return; - } - if ((templateNode.getAttributes().getNamedItem("includeOtherSubTemplate") != null) - || attrName.equalsIgnoreCase(SIGNED_DATETIME) || attrName.equalsIgnoreCase(RECORDED_DATETIME)) { - appendSubTemplateWithOrderAttribute(templateNode, dataCriteriaXMLProcessor, templateXMLProcessor, - dataCriteriaElem, qdmNode, attributeQDMNode); - } else { - generateDateTimeAttributes(qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, - attributeQDMNode); - } - } - - /** - * Generate negation rational entries. - * - * @param qdmNode - * the qdm node - * @param dataCriteriaElem - * the data criteria elem - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateNegationRationalEntries(Node qdmNode, Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node attributeQDMNode) - throws XPathExpressionException { - if (attributeQDMNode.getAttributes().getLength() > 0) { - - String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); - String attribUUID = (String) attributeQDMNode.getUserData(ATTRIBUTE_UUID); - - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); - Node templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/AttrTemplate[text()='" + attrName + "']"); - String attributeValueSetName = attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue(); - String attributeOID = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); - String attributeTaxonomy = attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); - dataCriteriaElem.setAttribute("actionNegationInd", "true"); - - Element outboundRelationshipElem = dataCriteriaXMLProcessor.getOriginalDoc() - .createElement(OUTBOUND_RELATIONSHIP); - outboundRelationshipElem.setAttribute(TYPE_CODE, - templateNode.getAttributes().getNamedItem(TYPE).getNodeValue()); - - Element observationCriteriaElem = dataCriteriaXMLProcessor.getOriginalDoc() - .createElement(OBSERVATION_CRITERIA); - observationCriteriaElem.setAttribute(CLASS_CODE, - templateNode.getAttributes().getNamedItem(CLASS).getNodeValue()); - observationCriteriaElem.setAttribute(MOOD_CODE, - templateNode.getAttributes().getNamedItem(MOOD).getNodeValue()); - - outboundRelationshipElem.appendChild(observationCriteriaElem); - - Element templateId = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TEMPLATE_ID); - observationCriteriaElem.appendChild(templateId); - - Element itemChild = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); - itemChild.setAttribute(ROOT, templateNode.getAttributes().getNamedItem(OID).getNodeValue()); - itemChild.setAttribute("extension", VERSION_4_1_2_ID); - templateId.appendChild(itemChild); - - Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); - idElem.setAttribute(ROOT, attribUUID); - idElem.setAttribute("extension", StringUtils.deleteWhitespace(attributeValueSetName)); - observationCriteriaElem.appendChild(idElem); - - Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - codeElem.setAttribute(CODE, templateNode.getAttributes().getNamedItem(CODE).getNodeValue()); - codeElem.setAttribute(CODE_SYSTEM, templateNode.getAttributes().getNamedItem(CODE_SYSTEM).getNodeValue()); - - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - displayNameElem.setAttribute(VALUE, "Reason"); - - observationCriteriaElem.appendChild(codeElem); - codeElem.appendChild(displayNameElem); - - Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); - titleElem.setAttribute(VALUE, "Reason"); - observationCriteriaElem.appendChild(titleElem); - - Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(VALUE); - valueElem.setAttribute(XSI_TYPE, templateNode.getAttributes().getNamedItem("valueType").getNodeValue()); - valueElem.setAttribute("valueSet", attributeOID); - addValueSetVersion(attributeQDMNode, valueElem); - Element valueDisplayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - valueDisplayNameElem.setAttribute(VALUE, - HQMFDataCriteriaGenerator.removeOccurrenceFromName(attributeValueSetName) + " " + attributeTaxonomy - + " Value Set"); - - valueElem.appendChild(valueDisplayNameElem); - observationCriteriaElem.appendChild(valueElem); - - dataCriteriaElem.appendChild(outboundRelationshipElem); - } - } - - /** - * Method is used to generate HQMF logic for Principle Diagnosis and Diagnosis - * attributes. - * - * @param qdmNode - * @param dataCriteriaElem - * @param dataCriteriaXMLProcessor - * @param simpleXmlprocessor - * @param attributeQDMNode - * @throws XPathExpressionException - */ - protected void generatePrincipalAndDiagnosisAttributes(Node qdmNode, Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node attributeQDMNode) - throws XPathExpressionException { - String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); - String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); - - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); - Node templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/AttrTemplate[text()='" + attrName.toLowerCase() + "']"); - if (templateNode == null) { - return; - } else { - Element outboundRelationshipElem = null; - Element actCriteriaElem = null; - outboundRelationshipElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); - outboundRelationshipElem.setAttribute(TYPE_CODE, - templateNode.getAttributes().getNamedItem(TYPE).getNodeValue()); - actCriteriaElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("actCriteria"); - actCriteriaElem.setAttribute(CLASS_CODE, templateNode.getAttributes().getNamedItem(CLASS).getNodeValue()); - actCriteriaElem.setAttribute(MOOD_CODE, templateNode.getAttributes().getNamedItem(MOOD).getNodeValue()); - Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); - idElem.setAttribute(ROOT, UUIDUtilClient.uuid()); - idElem.setAttribute("extension", UUIDUtilClient.uuid()); - actCriteriaElem.appendChild(idElem); - Element codeElem = createCodeForDatatype(templateNode, dataCriteriaXMLProcessor); - actCriteriaElem.appendChild(codeElem); - Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); - titleElem.setAttribute(VALUE, "Encounter " + attrName); - actCriteriaElem.appendChild(titleElem); - - outboundRelationshipElem.appendChild(actCriteriaElem); - - String subTemplateName = templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); - Node subTemplateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName); - NodeList subTemplateNodeChilds = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "/child::node()"); - - if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { - String[] attributeToBeModified = subTemplateNode.getAttributes().getNamedItem("changeAttribute") - .getNodeValue().split(","); - for (String changeAttribute : attributeToBeModified) { - NodeList attributedToBeChangedInNode = null; - attributedToBeChangedInNode = templateXMLProcessor.findNodeList( - templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); - if (changeAttribute.equalsIgnoreCase(ID)) { - String rootId = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("root").setNodeValue(rootId); - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("extension") - .setNodeValue(UUIDUtilClient.uuid()); - } else if (changeAttribute.equalsIgnoreCase(VALUE)) { - if (CHECK_IF_PRESENT.equals(attrMode)) { - if (attributedToBeChangedInNode.item(0).hasAttributes()) { - if (attributedToBeChangedInNode.item(0).hasAttributes()) { - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("valueSet"); - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("flavorId"); - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("xsi:type"); - } - } - if (attributedToBeChangedInNode.item(0).hasChildNodes()) { - attributedToBeChangedInNode.item(0) - .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); - } - Attr attribute = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createAttribute("flavorId"); - attribute.setNodeValue("ANY.NONNULL"); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attribute); - - Attr attributeXSIType = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createAttribute("xsi:type"); - attributeXSIType.setNodeValue("ANY"); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attributeXSIType); - } else if (VALUE_SET.equalsIgnoreCase(attrMode)) { - - String valueSetVersion = valueSetVersionStringValue(attributeQDMNode); - if (valueSetVersion.contains("mat/vsacmodel")) { - Attr valuesetVersionAttr = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createAttribute("valueSetVersion"); - valuesetVersionAttr.setNodeValue(valueSetVersion); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(valuesetVersionAttr); - } else { - if (attributedToBeChangedInNode.item(0).getAttributes() - .getNamedItem("valueSetVersion") != null) { - attributedToBeChangedInNode.item(0).getAttributes() - .removeNamedItem("valueSetVersion"); - } - } - if (attributedToBeChangedInNode.item(0).hasAttributes()) { - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("valueSet"); - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("flavorId"); - ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("xsi:type"); - } - if (attributedToBeChangedInNode.item(0).hasChildNodes()) { - ((Element) attributedToBeChangedInNode.item(0)) - .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); - } - String attributeValueSetName = attributeQDMNode.getAttributes().getNamedItem(NAME) - .getNodeValue(); - String attributeOID = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); - String attributeTaxonomy = attributeQDMNode.getAttributes().getNamedItem(TAXONOMY) - .getNodeValue(); - Attr attribute = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createAttribute("valueSet"); - attribute.setNodeValue(attributeOID); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attribute); - Attr attributeXSIType = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createAttribute("xsi:type"); - attributeXSIType.setNodeValue("CD"); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attributeXSIType); - Element valueDisplayNameElem = attributedToBeChangedInNode.item(0).getOwnerDocument() - .createElement(DISPLAY_NAME); - valueDisplayNameElem.setAttribute(VALUE, - HQMFDataCriteriaGenerator.removeOccurrenceFromName(attributeValueSetName) + " " - + attributeTaxonomy + " Value Set"); - attributedToBeChangedInNode.item(0).appendChild(valueDisplayNameElem); - - } - } - } - } - for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { - Node childNode = subTemplateNodeChilds.item(i); - Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); - XmlProcessor.clean(nodeToAttach); - actCriteriaElem.appendChild(nodeToAttach); - } - - dataCriteriaElem.appendChild(outboundRelationshipElem); - } - } - - /** - * Generate other attribute entries. - * - * @param qdmNode - * the qdm node - * @param dataCriteriaElem - * the data criteria elem - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - * @throws XPathExpressionException - * the x path expression exception - */ - protected void generateOtherAttributes(Node qdmNode, Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node attributeQDMNode) - throws XPathExpressionException { - - String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); - String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); - String attribUUID = (String) attributeQDMNode.getUserData(ATTRIBUTE_UUID); - String qdmName = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - boolean isResult = "result".equalsIgnoreCase(attrName); - - boolean isResultNotOutBound = isResult && ("Diagnostic Study, Performed".equalsIgnoreCase(qdmName) - || "Laboratory Test, Performed".equalsIgnoreCase(qdmName) - || "Functional Status, Performed".equalsIgnoreCase(qdmName) - || "Risk Category Assessment".equalsIgnoreCase(qdmName)); - - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); - Node templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/AttrTemplate[text()='" + attrName.toLowerCase() + "']"); - boolean isRadiation = false; - if (templateNode == null) { - templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/AttrTemplate[text()='" + attrName.toLowerCase() + "-" + attrMode.toLowerCase() + "']"); - if (templateNode == null) { - return; - } else { - if (ANATOMICAL_LOCATION_SITE.equalsIgnoreCase(attrName) || ORDINALITY.equalsIgnoreCase(attrName) - || ROUTE.equalsIgnoreCase(attrName) || "method".equalsIgnoreCase(attrName) - || ANATOMICAL_APPROACH_SITE.equalsIgnoreCase(attrName)) { - addTargetSiteOrPriorityCodeOrRouteCodeElement(dataCriteriaElem, dataCriteriaXMLProcessor, - attributeQDMNode, templateNode); - } else if (LATERALITY.equalsIgnoreCase(attrName)) { - appendSubTemplateNode(templateNode, dataCriteriaXMLProcessor, templateXMLProcessor, - dataCriteriaElem, qdmNode, attributeQDMNode); - } - return; - } - } - // flag to add statusCode for Radiation Dosage and Radiation Duration attributes - if (templateNode.getAttributes().getNamedItem("isRadiation") != null) { - isRadiation = templateNode.getAttributes().getNamedItem("isRadiation").getNodeValue() != null; - } - if (attrName.equalsIgnoreCase(FACILITY_LOCATION)) { - if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { - appendSubTemplateInFacilityAttribute(templateNode, dataCriteriaXMLProcessor, templateXMLProcessor, - dataCriteriaElem, attributeQDMNode); - } - return; - } else if (attrName.contains(REFERENCE) || attrName.equalsIgnoreCase(RELATIONSHIP)) { - if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { - appendSubTemplateAndAddValueTagBasedOnMode(templateNode, dataCriteriaXMLProcessor, templateXMLProcessor, - dataCriteriaElem, attributeQDMNode); - } - return; - } - Element outboundRelationshipElem = null; - Element observationCriteriaElem = null; - if (!isResultNotOutBound) { // result attribute with specific Datatypes does'nt add OutBoundRelationShip - outboundRelationshipElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); - outboundRelationshipElem.setAttribute(TYPE_CODE, - templateNode.getAttributes().getNamedItem(TYPE).getNodeValue()); - - Node invAttribNode = templateNode.getAttributes().getNamedItem("inv"); - if (invAttribNode != null) { - outboundRelationshipElem.setAttribute("inversionInd", invAttribNode.getNodeValue()); - } - - observationCriteriaElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(OBSERVATION_CRITERIA); - observationCriteriaElem.setAttribute(CLASS_CODE, - templateNode.getAttributes().getNamedItem(CLASS).getNodeValue()); - observationCriteriaElem.setAttribute(MOOD_CODE, - templateNode.getAttributes().getNamedItem(MOOD).getNodeValue()); - - outboundRelationshipElem.appendChild(observationCriteriaElem); - - if ((templateNode.getAttributes().getNamedItem(OID) != null) && !attrName.equalsIgnoreCase(ONSET_AGE)) { - Element templateId = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TEMPLATE_ID); - observationCriteriaElem.appendChild(templateId); - - Element itemChild = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); - itemChild.setAttribute(ROOT, templateNode.getAttributes().getNamedItem(OID).getNodeValue()); - if (templateNode.getAttributes().getNamedItem("addExtensionInTemplate") == null) { - itemChild.setAttribute("extension", VERSION_4_1_2_ID); - } - templateId.appendChild(itemChild); - } - - Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); - idElem.setAttribute(ROOT, attribUUID); - idElem.setAttribute("extension", StringUtils.deleteWhitespace(attrName)); - observationCriteriaElem.appendChild(idElem); - Element codeElem = createCodeForDatatype(templateNode, dataCriteriaXMLProcessor); - if ((isRadiation || isResult) && (codeElem != null)) { - observationCriteriaElem.appendChild(codeElem); - } else { - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - if (templateNode.getAttributes().getNamedItem("displayNameValue") != null) { - displayNameElem.setAttribute(VALUE, - templateNode.getAttributes().getNamedItem("displayNameValue").getNodeValue()); - } else { - displayNameElem.setAttribute(VALUE, attrName); - } - if (codeElem != null) { - observationCriteriaElem.appendChild(codeElem); - codeElem.appendChild(displayNameElem); - } - } - if (!isRadiation) { - if (!attrName.equalsIgnoreCase(ONSET_AGE)) { - Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); - titleElem.setAttribute(VALUE, attrName); - observationCriteriaElem.appendChild(titleElem); - } else { - Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); - titleElem.setAttribute(VALUE, "Age"); - observationCriteriaElem.appendChild(titleElem); - } - } - if (isRadiation) {// statusCode is added for Radiation Duration and Dosage - Element statusCodeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(STATUS_CODE); - if (templateNode.getAttributes().getNamedItem("status") != null) { - statusCodeElem.setAttribute(CODE, - templateNode.getAttributes().getNamedItem("status").getNodeValue()); - } - observationCriteriaElem.appendChild(statusCodeElem); - } - } - if (attrName.equalsIgnoreCase(ONSET_AGE)) { - generateRepeatNumber(templateNode, dataCriteriaXMLProcessor, observationCriteriaElem, attributeQDMNode, - VALUE); - dataCriteriaElem.appendChild(outboundRelationshipElem); - } else { - Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(VALUE); - if (VALUE_SET.equals(attrMode)) { - checkIfSelectedModeIsValueSet(dataCriteriaXMLProcessor, attributeQDMNode, templateNode, valueElem); - } else if (CHECK_IF_PRESENT.equalsIgnoreCase(attrMode)) { - checkIfSelectedModeIsPresent(dataCriteriaXMLProcessor, attributeQDMNode, templateNode, valueElem); - } else if (EQUAL_TO.equals(attrMode) || attrMode.startsWith(LESS_THAN) - || attrMode.startsWith(GREATER_THAN)) { - checkIfSelectedModeIsArthimaticExpr(dataCriteriaXMLProcessor, attributeQDMNode, templateNode, - valueElem); - } - if ((outboundRelationshipElem != null) && (observationCriteriaElem != null)) { - observationCriteriaElem.appendChild(valueElem); - dataCriteriaElem.appendChild(outboundRelationshipElem); - } else { - NodeList outboundRelationshipList = dataCriteriaElem.getElementsByTagName("outboundRelationship"); - if ((outboundRelationshipList != null) && (outboundRelationshipList.getLength() > 0)) { - Node outboundRelationshipNode = outboundRelationshipList.item(0); - dataCriteriaElem.insertBefore(valueElem, outboundRelationshipNode); - } else { - dataCriteriaElem.appendChild(valueElem); - } - } - } - } - - /** - * Refills Attribute tags. - * - * @param templateNode - * the template node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param dataCriteriaElem - * the data criteria elem - * @param attributeQDMNode - * the attribute qdm node - */ - protected void generateRepeatNumber(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, - Element dataCriteriaElem, Node attributeQDMNode, String elementNameToCreate) { - String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); - Element repeatNumberElement = dataCriteriaXMLProcessor.getOriginalDoc().createElement(elementNameToCreate); - Node unitAttrib = attributeQDMNode.getAttributes().getNamedItem("unit"); - - if (CHECK_IF_PRESENT.equalsIgnoreCase(attrMode)) { - if (elementNameToCreate.equalsIgnoreCase(VALUE)) { - repeatNumberElement.setAttribute("xsi:type", "ANY"); - } - repeatNumberElement.setAttribute(FLAVOR_ID, "ANY.NONNULL"); - } else if (EQUAL_TO.equals(attrMode) || attrMode.startsWith(LESS_THAN) || attrMode.startsWith(GREATER_THAN)) { - if (elementNameToCreate.equalsIgnoreCase(VALUE)) { - repeatNumberElement.setAttribute("xsi:type", "IVL_PQ"); - } - if (EQUAL_TO.equals(attrMode)) { - Element lowElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); - lowElem.setAttribute(VALUE, - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); - highElem.setAttribute(VALUE, - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - lowElem.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); - highElem.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); - } - repeatNumberElement.appendChild(lowElem); - repeatNumberElement.appendChild(highElem); - } else if (attrMode.startsWith(GREATER_THAN)) { - if (attrMode.equals(GREATER_THAN)) { - repeatNumberElement.setAttribute("lowClosed", "false"); - } - Element lowElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); - lowElem.setAttribute(VALUE, - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - repeatNumberElement.appendChild(lowElem); - Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); - highElem.setAttribute(NULL_FLAVOR, "PINF"); - if (unitAttrib != null) { - lowElem.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); - } - - repeatNumberElement.appendChild(highElem); - } else if (attrMode.startsWith(LESS_THAN)) { - if (attrMode.equals(LESS_THAN)) { - repeatNumberElement.setAttribute("highClosed", "false"); - } - Element lowElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); - lowElem.setAttribute(NULL_FLAVOR, "NINF"); - repeatNumberElement.appendChild(lowElem); - Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); - highElem.setAttribute(VALUE, - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - highElem.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); - } - repeatNumberElement.appendChild(highElem); - } - } - - if ((dataCriteriaElem.getElementsByTagName("statusCode").item(0) != null)) { - Node outBoundElement = dataCriteriaElem.getElementsByTagName("statusCode").item(0); - if (outBoundElement != null) { - outBoundElement.getParentNode().insertBefore(repeatNumberElement, outBoundElement); - } else { - checkIfOutBoundOcc(dataCriteriaElem, repeatNumberElement); - } - } else { - checkIfOutBoundOcc(dataCriteriaElem, repeatNumberElement); - } - } - - /** - * Discharge Status Attribute tags. - * - * @param templateNode - * the template node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param dataCriteriaElem - * the data criteria elem - * @param attributeQDMNode - * the attribute qdm node - */ - protected void generateDischargeStatus(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, - Element dataCriteriaElem, Node attributeQDMNode) { - String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); - Element dischargeDispositionElement = dataCriteriaXMLProcessor.getOriginalDoc() - .createElement("dischargeDispositionCode"); - if (CHECK_IF_PRESENT.equalsIgnoreCase(attrMode)) { - dischargeDispositionElement.setAttribute(FLAVOR_ID, "ANY.NONNULL"); - checkIfOutBoundOcc(dataCriteriaElem, dischargeDispositionElement); - } else if (VALUE_SET.equalsIgnoreCase(attrMode)) { - String attributeValueSetName = attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue(); - - String attributeOID = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); - String attributeTaxonomy = attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); - dischargeDispositionElement.setAttribute("valueSet", attributeOID); - addValueSetVersion(attributeQDMNode, dischargeDispositionElement); - Element valueDisplayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - valueDisplayNameElem.setAttribute(VALUE, - HQMFDataCriteriaGenerator.removeOccurrenceFromName(attributeValueSetName) + " " + attributeTaxonomy - + " Value Set"); - dischargeDispositionElement.appendChild(valueDisplayNameElem); - checkIfOutBoundOcc(dataCriteriaElem, dischargeDispositionElement); - } - } - - /** - * Check if selected mode is value set. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param attributeQDMNode - * the attribute qdm node - * @param templateNode - * the template node - * @param valueElem - * the value elem - * @return the element - */ - protected Element checkIfSelectedModeIsValueSet(XmlProcessor dataCriteriaXMLProcessor, Node attributeQDMNode, - Node templateNode, Element valueElem) { - String attributeValueSetName = attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue(); - String attributeOID = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); - String attributeTaxonomy = attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); - if (templateNode.getAttributes().getNamedItem("valueType") != null) { - valueElem.setAttribute(XSI_TYPE, templateNode.getAttributes().getNamedItem("valueType").getNodeValue()); - } - - valueElem.setAttribute("valueSet", attributeOID); - addValueSetVersion(attributeQDMNode, valueElem); - Element valueDisplayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - valueDisplayNameElem.setAttribute(VALUE, - HQMFDataCriteriaGenerator.removeOccurrenceFromName(attributeValueSetName) + " " + attributeTaxonomy - + " Value Set"); - valueElem.appendChild(valueDisplayNameElem); - - return valueElem; - } - - /** - * Check if selected mode is present. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param attributeQDMNode - * the attribute qdm node - * @param templateNode - * the template node - * @param valueElem - * the value elem - * @return the element - */ - protected Element checkIfSelectedModeIsPresent(XmlProcessor dataCriteriaXMLProcessor, Node attributeQDMNode, - Node templateNode, Element valueElem) { - valueElem.setAttribute(XSI_TYPE, "ANY"); - valueElem.setAttribute(FLAVOR_ID, "ANY.NONNULL"); - return valueElem; - } - - /** - * Check if selected mode is arthimatic expr. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param attributeQDMNode - * the attribute qdm node - * @param templateNode - * the template node - * @param valueElem - * the value elem - * @return the element - */ - private Element checkIfSelectedModeIsArthimaticExpr(XmlProcessor dataCriteriaXMLProcessor, Node attributeQDMNode, - Node templateNode, Element valueElem) { - String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); - String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); - String nodeName = attributeQDMNode.getNodeName(); - boolean isRadiation = false; - boolean isTargetOutCome = false; - boolean isCumMedicationDuration = CUMULATIVE_MEDICATION_DURATION.equalsIgnoreCase(attrName); - boolean isFrequency = FREQUENCY.equalsIgnoreCase(attrName); - boolean isResult = "result".equalsIgnoreCase(attrName); - if (templateNode.getAttributes().getNamedItem("isRadiation") != null) { - isRadiation = templateNode.getAttributes().getNamedItem("isRadiation").getNodeValue() != null; - } - if (templateNode.getAttributes().getNamedItem("isTargetOutcome") != null) { - isTargetOutCome = templateNode.getAttributes().getNamedItem("isTargetOutcome").getNodeValue() != null; - } - if (nodeName.equals("attribute")) { - valueElem.setAttribute(XSI_TYPE, "IVL_PQ"); - Node unitAttrib = attributeQDMNode.getAttributes().getNamedItem("unit"); - if (EQUAL_TO.equals(attrMode)) { - if (isRadiation) { // for radiation dosage and radiation duration - valueElem.getAttributes().getNamedItem(XSI_TYPE).setNodeValue("PQ"); - valueElem.setAttribute(VALUE, - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - String unitString = getUnitString(unitAttrib.getNodeValue()); - valueElem.setAttribute("unit", unitString); - } - } else { // for attributes other than radiation duration and radiation dosage - Element lowElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); - lowElem.setAttribute(VALUE, - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - - Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); - highElem.setAttribute(VALUE, - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - - if (unitAttrib != null) { - String unitString = getUnitString(unitAttrib.getNodeValue()); - lowElem.setAttribute("unit", unitString); - highElem.setAttribute("unit", unitString); - } - if (isResult) { - lowElem.setAttribute(XSI_TYPE, "PQ"); - highElem.setAttribute(XSI_TYPE, "PQ"); - } - valueElem.appendChild(lowElem); - valueElem.appendChild(highElem); - } - - } else if (attrMode.startsWith(GREATER_THAN)) { - if (attrMode.equals(GREATER_THAN)) { - valueElem.setAttribute("lowClosed", "false"); - } - Element lowElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); - if (isResult) { - lowElem.setAttribute(XSI_TYPE, "PQ"); - } - lowElem.setAttribute(VALUE, - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - String unitString = getUnitString(unitAttrib.getNodeValue()); - lowElem.setAttribute("unit", unitString); - } - valueElem.appendChild(lowElem); - if (isRadiation || isResult || isTargetOutCome || isCumMedicationDuration || isFrequency) { - Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); - highElem.setAttribute(NULL_FLAVOR, "PINF"); - valueElem.appendChild(highElem); - } - } else if (attrMode.startsWith(LESS_THAN)) { - if (attrMode.equals(LESS_THAN)) { - valueElem.setAttribute("highClosed", "false"); - } - if (isRadiation || isResult || isTargetOutCome || isCumMedicationDuration || isFrequency) { - Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); - highElem.setAttribute(NULL_FLAVOR, "NINF"); - valueElem.appendChild(highElem); - } - Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); - if (isResult) { - highElem.setAttribute(XSI_TYPE, "PQ"); - } - highElem.setAttribute(VALUE, - attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); - if (unitAttrib != null) { - String unitString = getUnitString(unitAttrib.getNodeValue()); - highElem.setAttribute("unit", unitString); - } - valueElem.appendChild(highElem); - } - } - - return valueElem; - } - - /** - * Adds the target site or priority code or route code element. - * - * @param dataCriteriaElem - * the data criteria elem - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param attributeQDMNode - * the attribute qdm node - * @param templateNode - * the template node - */ - private void addTargetSiteOrPriorityCodeOrRouteCodeElement(Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, Node attributeQDMNode, Node templateNode) { - String targetElementName = templateNode.getAttributes().getNamedItem("target").getNodeValue(); - Element targetSiteCodeElement = dataCriteriaXMLProcessor.getOriginalDoc().createElement(targetElementName); - String insertBeforeNodeName = null; - String insertAfterNodeName = null; - if (templateNode.getAttributes().getNamedItem("insertBeforeNode") != null) { - insertBeforeNodeName = templateNode.getAttributes().getNamedItem("insertBeforeNode").getNodeValue(); - } else if (templateNode.getAttributes().getNamedItem("insertAfterNode") != null) { - insertAfterNodeName = templateNode.getAttributes().getNamedItem("insertAfterNode").getNodeValue(); - } - if (templateNode.getAttributes().getNamedItem("childTarget") != null) { - String qdmOidValue = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); - // .getNodeValue(); - Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); - valueElem.setAttribute("valueSet", qdmOidValue); - addValueSetVersion(attributeQDMNode, valueElem); - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - String newQdmName = HQMFDataCriteriaGenerator - .removeOccurrenceFromName(attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue()); - displayNameElem.setAttribute(VALUE, newQdmName + " " - + attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue() + " Value Set"); - valueElem.appendChild(displayNameElem); - targetSiteCodeElement.appendChild(valueElem); - if ((insertBeforeNodeName != null) - && (dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0) != null)) { - Node outBoundElement = dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0); - if (outBoundElement != null) { - outBoundElement.getParentNode().insertBefore(targetSiteCodeElement, outBoundElement); - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); - } - } else if ((insertAfterNodeName != null) - && (dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0) != null)) { - Node outBoundElement = dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0) - .getNextSibling(); - if (outBoundElement != null) { - outBoundElement.getParentNode().insertBefore(targetSiteCodeElement, outBoundElement); - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); - } - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); - } - } else if (templateNode.getAttributes().getNamedItem(FLAVOR_ID) != null) { - String flavorIdValue = templateNode.getAttributes().getNamedItem(FLAVOR_ID).getNodeValue(); - targetSiteCodeElement.setAttribute(FLAVOR_ID, flavorIdValue); - if ((insertBeforeNodeName != null) - && (dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0) != null)) { - Node outBoundElement = dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0); - if (outBoundElement != null) { - outBoundElement.getParentNode().insertBefore(targetSiteCodeElement, outBoundElement); - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); - } - } else if ((insertAfterNodeName != null) - && (dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0) != null)) { - Node outBoundElement = dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0) - .getNextSibling(); - if (outBoundElement != null) { - outBoundElement.getParentNode().insertBefore(targetSiteCodeElement, outBoundElement); - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); - } - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); - } - } else if (templateNode.getAttributes().getNamedItem("addValueSet") != null) { - String qdmOidValue = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); - targetSiteCodeElement.setAttribute("valueSet", qdmOidValue); - addValueSetVersion(attributeQDMNode, targetSiteCodeElement); - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - String newQdmName = HQMFDataCriteriaGenerator - .removeOccurrenceFromName(attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue()); - displayNameElem.setAttribute(VALUE, newQdmName + " " - + attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue() + " Value Set"); - targetSiteCodeElement.appendChild(displayNameElem); - if ((insertBeforeNodeName != null) - && (dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0) != null)) { - Node outBoundElement = dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0); - if (outBoundElement != null) { - outBoundElement.getParentNode().insertBefore(targetSiteCodeElement, outBoundElement); - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); - } - } else { - checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); - } - } - } - - /** - * Method to generate HQMF XML for date time attributes. - * - * @param childNode - * the child node - * @param dataCriteriaElem - * the data criteria elem - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - * @param attributeQDMNode - * the attribute qdm node - */ - protected void generateDateTimeAttributes(Node childNode, Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node attributeQDMNode) { - - Element effectiveTimeNode = dataCriteriaXMLProcessor.getOriginalDoc().createElement(EFFECTIVE_TIME); - effectiveTimeNode.setAttribute(XSI_TYPE, "IVL_TS"); - generateDateTimeAttributesTag(effectiveTimeNode, attributeQDMNode, dataCriteriaElem, dataCriteriaXMLProcessor, - false); - } - - /** - * Generate date time attributes tag. - * - * @param dateTimeNode - * the effective time node - * @param attributeQDMNode - * the attribute qdm node - * @param dataCriteriaElem - * the data criteria elem - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param isOrder - * the is order - */ - protected void generateDateTimeAttributesTag(Node dateTimeNode, Node attributeQDMNode, Element dataCriteriaElem, - XmlProcessor dataCriteriaXMLProcessor, boolean isOrder) { - - String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); - String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); - String attrDate = (String) attributeQDMNode.getUserData(ATTRIBUTE_DATE); - - String timeTagName = ""; - switch (attrName.toLowerCase()) { - case START_DATETIME: - case FACILITY_LOCATION_ARRIVAL_DATETIME: - case ADMISSION_DATETIME: - case ACTIVE_DATETIME: - case DATE: - case TIME: - case INCISION_DATETIME: - case ONSET_DATETIME: - timeTagName = LOW; - break; - case STOP_DATETIME: - case FACILITY_LOCATION_DEPARTURE_DATETIME: - case DISCHARGE_DATETIME: - case REMOVAL_DATETIME: - case SIGNED_DATETIME: - case RECORDED_DATETIME: - case ABATEMENT_DATETIME: - timeTagName = HIGH; - break; - default: - timeTagName = ""; - break; - } - - if (CHECK_IF_PRESENT.equals(attrMode)) { - - if (timeTagName.length() > 0) { - Element timeTagNode = dataCriteriaElem.getOwnerDocument().createElement(timeTagName); - timeTagNode.setAttribute(FLAVOR_ID, "ANY.NONNULL"); - dateTimeNode.appendChild(timeTagNode); - } - } else { - if (attrMode.equals(Generator.EQUAL_TO)) { - if (timeTagName.length() > 0) { - Element timeTagNode = dataCriteriaElem.getOwnerDocument().createElement(timeTagName); - timeTagNode.setAttribute(VALUE, attrDate); - dateTimeNode.appendChild(timeTagNode); - } - } else if (attrMode.startsWith(Generator.GREATER_THAN)) { - if (timeTagName.length() > 0) { - Element timeTagNode = dataCriteriaElem.getOwnerDocument().createElement(timeTagName); - Element uncertainRangeNode = dataCriteriaElem.getOwnerDocument().createElement("uncertainRange"); - if (attrMode.equals(Generator.GREATER_THAN)) { - uncertainRangeNode.setAttribute("lowClosed", "false"); - } - Element lowNode = dataCriteriaElem.getOwnerDocument().createElement(LOW); - lowNode.setAttribute(XSI_TYPE, "TS"); - lowNode.setAttribute(VALUE, attrDate); - - Element highNode = dataCriteriaElem.getOwnerDocument().createElement(HIGH); - highNode.setAttribute(XSI_TYPE, "TS"); - highNode.setAttribute("nullFlavor", "PINF"); - - uncertainRangeNode.appendChild(lowNode); - uncertainRangeNode.appendChild(highNode); - timeTagNode.appendChild(uncertainRangeNode); - dateTimeNode.appendChild(timeTagNode); - } - } else if (attrMode.startsWith(Generator.LESS_THAN)) { - if (timeTagName.length() > 0) { - Element timeTagNode = dataCriteriaElem.getOwnerDocument().createElement(timeTagName); - Element uncertainRangeNode = dataCriteriaElem.getOwnerDocument().createElement("uncertainRange"); - if (attrMode.equals(Generator.LESS_THAN)) { - uncertainRangeNode.setAttribute("highClosed", "false"); - } - Element lowNode = dataCriteriaElem.getOwnerDocument().createElement(LOW); - lowNode.setAttribute(XSI_TYPE, "TS"); - lowNode.setAttribute("nullFlavor", "NINF"); - - Element highNode = dataCriteriaElem.getOwnerDocument().createElement(HIGH); - highNode.setAttribute(XSI_TYPE, "TS"); - highNode.setAttribute(VALUE, attrDate); - - uncertainRangeNode.appendChild(lowNode); - uncertainRangeNode.appendChild(highNode); - timeTagNode.appendChild(uncertainRangeNode); - dateTimeNode.appendChild(timeTagNode); - } - } - } - - /** - * If effectiveTimeNode has any child nodes then add it to the main - * dataCriteriaNode. - */ - if (dateTimeNode.hasChildNodes()) { - - if (attrName.equalsIgnoreCase(START_DATETIME) || attrName.equalsIgnoreCase(STOP_DATETIME) - || attrName.equalsIgnoreCase(SIGNED_DATETIME) || attrName.equalsIgnoreCase(RECORDED_DATETIME)) { - NodeList nodeList = dataCriteriaElem.getElementsByTagName("participation"); - if ((nodeList != null) && (nodeList.getLength() > 0) && isOrder) { - if (nodeList.getLength() > 1) { - nodeList.item(1).insertBefore(dateTimeNode, - dataCriteriaElem.getElementsByTagName("role").item(1)); - } else { - nodeList.item(0).insertBefore(dateTimeNode, - dataCriteriaElem.getElementsByTagName("role").item(0)); - } - } else { - NodeList valueNodeList = dataCriteriaElem.getElementsByTagName("value"); - if ((valueNodeList != null) && (valueNodeList.getLength() > 0)) { - dataCriteriaElem.insertBefore(dateTimeNode, valueNodeList.item(0)); - } else { - NodeList statusCodeNodeList = dataCriteriaElem.getElementsByTagName("statusCode"); - if ((statusCodeNodeList != null) && (statusCodeNodeList.getLength() > 0)) { - dataCriteriaElem.insertBefore(dateTimeNode, statusCodeNodeList.item(0).getNextSibling()); - } else { - checkIfOutBoundOcc(dataCriteriaElem, dateTimeNode); - } - } - } - } else { - NodeList nodeList = dataCriteriaElem.getElementsByTagName("value"); - if ((nodeList != null) && (nodeList.getLength() > 0)) { - dataCriteriaElem.insertBefore(dateTimeNode, nodeList.item(0)); - } else { - - if (attrName.contains("facility")) { - NodeList nodeListParticipation = dataCriteriaElem.getElementsByTagName("role"); - if ((nodeListParticipation != null) && (nodeListParticipation.getLength() > 0)) { - nodeListParticipation.item(0).getFirstChild().getParentNode().appendChild(dateTimeNode); - } - } else if (attrName.equalsIgnoreCase(INCISION_DATETIME)) { // for Incision Datetime Attribute - // effective Time is Added inside - NodeList nodeListProcedureCriteria = dataCriteriaElem.getElementsByTagName("procedureCriteria"); - if ((nodeListProcedureCriteria != null) && (nodeListProcedureCriteria.getLength() > 0)) { - nodeListProcedureCriteria.item(0).getFirstChild().getParentNode().appendChild(dateTimeNode); - } - } else { - NodeList nodeListParticipation = dataCriteriaElem.getElementsByTagName("participation"); - if ((nodeListParticipation != null) && (nodeListParticipation.getLength() > 0)) { - dataCriteriaElem.insertBefore(dateTimeNode, nodeListParticipation.item(0)); - } else { - checkIfOutBoundOcc(dataCriteriaElem, dateTimeNode); - } - } - } - } - } - - } - - /** - * Adds the data criteria comment. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - */ - private void addDataCriteriaComment(XmlProcessor dataCriteriaXMLProcessor) { - Element element = dataCriteriaXMLProcessor.getOriginalDoc().getDocumentElement(); - Comment comment = dataCriteriaXMLProcessor.getOriginalDoc().createComment("Data Criteria Section"); - element.getParentNode().insertBefore(comment, element); - } - - /** - * Creates the code for datatype. - * - * @param templateNode - * the template node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @return the element - */ - protected Element createCodeForDatatype(Node templateNode, XmlProcessor dataCriteriaXMLProcessor) { - Node codeAttr = templateNode.getAttributes().getNamedItem(CODE); - Node codeSystemAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM); - Node codeSystemNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_NAME); - Node codeDisplayNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_DISPLAY_NAME); - Element codeElement = null; - if ((codeAttr != null) || (codeSystemAttr != null) || (codeSystemNameAttr != null) - || (codeDisplayNameAttr != null)) { - codeElement = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - if (codeAttr != null) { - codeElement.setAttribute(CODE, codeAttr.getNodeValue()); - } - if (codeSystemAttr != null) { - codeElement.setAttribute(CODE_SYSTEM, codeSystemAttr.getNodeValue()); - } - if (codeSystemNameAttr != null) { - codeElement.setAttribute(CODE_SYSTEM_NAME, codeSystemNameAttr.getNodeValue()); - } - if (codeDisplayNameAttr != null) { - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - displayNameElem.setAttribute(VALUE, codeDisplayNameAttr.getNodeValue()); - codeElement.appendChild(displayNameElem); - } - } - return codeElement; - } - - /** - * This method is called before we start generating HQMF code for various data - * criteria elements. It will perform the task of prepping the Simple XML for - * the clause generation process. It will do the following, - * - * 1) Call prepForAGE_AT(MeasureExport me) which will, Look for and replace it with The - * first child of this new relationalOp will be the elementRef for Birthdate QDM - * element. The 2nd child will be the first child of the original . - */ - private void prepHQMF(MeasureExport me) { - logger.debug("Prepping for HQMF Clause generation.............."); - prepForUUID(me); - prepForAGE_AT(me); - prepForSatisfiesAll_Any(me); - logger.debug("Done prepping for HQMF Clause generation."); - } - - private void prepForUUID(MeasureExport me) { - - String xPathForFunctionalOp = "/measure/subTreeLookUp//functionalOp"; - String xPathForRelationalOp = "/measure/subTreeLookUp//relationalOp"; - String xPathForSetOp = "/measure/subTreeLookUp//setOp"; - - try { - NodeList nodeList = me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), - xPathForFunctionalOp); - addUUIDToNodes(nodeList); - - nodeList = me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), - xPathForRelationalOp); - addUUIDToNodes(nodeList); - - nodeList = me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), - xPathForSetOp); - addUUIDToNodes(nodeList); - - } catch (Exception e) { - e.printStackTrace(); - } - - } - - private void addUUIDToNodes(NodeList nodeList) { - if ((nodeList != null) && (nodeList.getLength() > 0)) { - for (int i = 0; i < nodeList.getLength(); i++) { - Node node = nodeList.item(i); - ((Element) node).setAttribute("uuid", UUIDUtilClient.uuid()); - } - } - } - - /** - * This method will be called by prepHQMF(MeasureExport me) method to prep - * functionalOp for AGE AT functions. This methiod will do the following, - * - * Look for and replace it with The first child of this new relationalOp will be the - * elementRef for Birthdate QDM element. The 2nd child will be the first child - * of the original . - * - * @param me - */ - - private void prepForAGE_AT(MeasureExport me) { - XmlProcessor xmlProcessor = me.getSimpleXmlProcessor(); - logger.debug("Prepping for HQMF Clause generation for AGE AT functionalOps."); - - try { - - // find for Birthdate QDM element in elementLookUp - String xPathForBirthdate = "/measure/elementLookUp/qdm[@name='Birthdate'][@datatype='Patient Characteristic Birthdate']"; - Node birthDateQDM = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), xPathForBirthdate); - if (birthDateQDM == null) { - logger.debug( - "********** Could not find QDM for Birthdate. No changes done for AGE AT. ***************"); - return; - } - - String xPathForAGE_AT = "/measure/subTreeLookUp//functionalOp[@type='AGE AT']"; - Node ageAtFuncNode = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), xPathForAGE_AT); - - logger.debug(".......found AGE AT functionalOps"); - - while (ageAtFuncNode != null) { - logger.debug("Changing " + ageAtFuncNode.toString() + " to relational SBS node."); - Node cloneAgeAtRelNode = ageAtFuncNode.cloneNode(true); - - // hold on to the first child of Age At - Node firstChild = cloneAgeAtRelNode.getFirstChild(); - NamedNodeMap attribMap = ageAtFuncNode.getAttributes(); - Element newRelationalOp = xmlProcessor.getOriginalDoc().createElement("relationalOp"); - - for (int j = 0; j < attribMap.getLength(); j++) { - Node attrib = attribMap.item(j); - newRelationalOp.setAttribute(attrib.getNodeName(), attrib.getNodeValue()); - } - - // set the type attribute to SBS - newRelationalOp.getAttributes().getNamedItem("type").setNodeValue("SBS"); - - // create a new tag with tag. - * - * @param me - */ - private void prepForSatisfiesAll_Any(MeasureExport me) { - XmlProcessor xmlProcessor = me.getSimpleXmlProcessor(); - logger.debug("Prepping for HQMF Clause generation for Satisfies All/Satisfies Any functionalOps."); - String xPathForSatisfiesAllAny = "/measure/subTreeLookUp//functionalOp[@type='SATISFIES ALL' or @type='SATISFIES ANY']"; - try { - Node satisfiesFuncNode = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), xPathForSatisfiesAllAny); - logger.debug(".......found Satisfies All/Satisfies Any functionalOps"); - while (satisfiesFuncNode != null) { - logger.debug("Changing functionaOp " - + satisfiesFuncNode.getAttributes().getNamedItem("displayName").getNodeValue() - + " to relationalOp node."); - - NamedNodeMap attribMap = satisfiesFuncNode.getAttributes(); - Element newSetOp = xmlProcessor.getOriginalDoc().createElement("setOp"); - - for (int j = 0; j < attribMap.getLength(); j++) { - Node attrib = attribMap.item(j); - newSetOp.setAttribute(attrib.getNodeName(), attrib.getNodeValue()); - } - - NodeList childNodeList = satisfiesFuncNode.getChildNodes(); - /** - * Ignore the first element of SATISFIES ALL/ANY. i.e. Start counter at 1 - * isntead of 0. - */ - for (int j = 1; j < childNodeList.getLength(); j++) { - Node childNode = childNodeList.item(j).cloneNode(true); - newSetOp.appendChild(childNode); - } - - Node parentNode = satisfiesFuncNode.getParentNode(); - parentNode.insertBefore(newSetOp, satisfiesFuncNode); - parentNode.removeChild(satisfiesFuncNode); - logger.debug("Change done."); - satisfiesFuncNode = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), xPathForSatisfiesAllAny); - } - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - - /** - * Gets the unit string. - * - * @param unitString - * the unit string - * @return the unit string - */ - protected String getUnitString(String unitString) { - String returnString = unitString; - - if (unitString.equals("years") || unitString.equals("year")) { - returnString = "a"; - } else if (unitString.equals("month") || unitString.equals("months")) { - returnString = "mo"; - } else if (unitString.equals("day") || unitString.equals("days")) { - returnString = "d"; - } else if (unitString.equals("hours") || unitString.equals("hour")) { - returnString = "h"; - } else if (unitString.equals("week") || unitString.equals("weeks")) { - returnString = "wk"; - } else if (unitString.equals("minutes") || unitString.equals("minute")) { - returnString = "min"; - } else if (unitString.equals("quarter") || unitString.equals("quarters")) { - returnString = "[qtr]"; - } else if (unitString.equals("second") || unitString.equals("seconds")) { - returnString = "s"; - } else if (unitString.equals("bpm")) { - returnString = "{H.B.}/min"; - } else if (unitString.equals("mmHg")) { - returnString = "mm[Hg]"; - } else if (unitString.equals("mEq")) { - returnString = "meq"; - } else if (unitString.equals("celsius")) { - returnString = "Cel"; - } else if (unitString.equals("WBC/mm3")) { - returnString = "{WBC}/mm3"; - } else if (unitString.equals("WBC/hpf")) { - returnString = "{WBC}/[HPF]"; - } else if (unitString.equals("CFU/mL")) { - returnString = "[CFU]/mL"; - } else if (unitString.equals("per mm3")) { - returnString = "/mm3"; - } else if (unitString.equals("copies/mL")) { - returnString = "{copies}/mL"; - } else if (unitString.equals("IU")) { - returnString = "[iU]"; - } else if (unitString.equals("IU/L")) { - returnString = "[iU]/L"; - } else if (unitString.equals("AU")) { - returnString = "[AU]"; - } else if (unitString.equals("BAU")) { - returnString = "[BAU]"; - } - - return returnString; - } - - /** - * Check if out bound is occurrence and append the Attribute entry before - * Temporal and outBoundRelationShip Tag. - * - * @param dataCriteriaElem - * the data criteria elem - * @param dateTimeNode - * the date time node - */ - private void checkIfOutBoundOcc(Element dataCriteriaElem, Node dateTimeNode) { - Node outBoundOccNode = dataCriteriaElem.getElementsByTagName("outboundRelationship").item(0); - if ((outBoundOccNode != null) - && outBoundOccNode.getAttributes().getNamedItem("typeCode").getNodeValue().equalsIgnoreCase("OCCR")) { - dataCriteriaElem.insertBefore(dateTimeNode, outBoundOccNode); - } else { - dataCriteriaElem.appendChild(dateTimeNode); - } - } - + /** The occurrence map. */ + private Map occurrenceMap = new HashMap(); + + protected String extensionValue = null; + + /** The Constant logger. */ + private static final Logger logger = + LoggerFactory.getLogger(HQMFDataCriteriaElementGenerator.class); + + /** + * Generate hqm for measure. + * + * @param me the me + * @return the string + * @throws Exception the exception + */ + @Override + public String generate(MeasureExport me) throws Exception { + String dataCriteria = ""; + getExtensionValueBasedOnVersion(me); + dataCriteria = getHQMFXmlString(me); + return dataCriteria; + } + + public void generateAttributeTagForFunctionalOp( + MeasureExport measureExport, Node qdmNode, Element excerptElement, Node attributeQDMNode) + throws XPathExpressionException { + getExtensionValueBasedOnVersion(measureExport); + createDataCriteriaForAttributes( + qdmNode, + excerptElement, + measureExport.getHqmfXmlProcessor(), + measureExport.getSimpleXmlProcessor(), + attributeQDMNode, + true); + } + + /** + * Gets the HQMF xml string. + * + * @param me the me + * @return the HQMF xml string + */ + private String getHQMFXmlString(MeasureExport me) { + XmlProcessor dataCriteriaXMLProcessor = createDateCriteriaTemplate(me); + me.setHqmfXmlProcessor(dataCriteriaXMLProcessor); + + String simpleXMLStr = me.getSimpleXml(); + XmlProcessor simpleXmlprocessor = new XmlProcessor(simpleXMLStr); + me.setSimpleXmlProcessor(simpleXmlprocessor); + + prepHQMF(me); + + createDataCriteriaForQDMELements(me, dataCriteriaXMLProcessor, simpleXmlprocessor); + addDataCriteriaComment(dataCriteriaXMLProcessor); + return dataCriteriaXMLProcessor.transform(dataCriteriaXMLProcessor.getOriginalDoc(), true); + } + + /** + * Creates the date criteria template. + * + * @param me the me + * @return the string + */ + private XmlProcessor createDateCriteriaTemplate(MeasureExport me) { + XmlProcessor outputProcessor = + new XmlProcessor( + ""); + + Node dataCriteriaElem = + outputProcessor.getOriginalDoc().getElementsByTagName("dataCriteriaSection").item(0); + Element templateId = outputProcessor.getOriginalDoc().createElement(TEMPLATE_ID); + dataCriteriaElem.appendChild(templateId); + Element itemChild = outputProcessor.getOriginalDoc().createElement(ITEM); + itemChild.setAttribute(ROOT, "2.16.840.1.113883.10.20.28.2.2"); + itemChild.setAttribute("extension", extensionValue); + templateId.appendChild(itemChild); + // creating Code Element for DataCriteria + Element codeElem = outputProcessor.getOriginalDoc().createElement(CODE); + codeElem.setAttribute(CODE, "57025-9"); + codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.6.1"); + dataCriteriaElem.appendChild(codeElem); + // creating title for DataCriteria + Element titleElem = outputProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, "Data Criteria Section"); + dataCriteriaElem.appendChild(titleElem); + // creating text for DataCriteria + Element textElem = outputProcessor.getOriginalDoc().createElement("text"); + dataCriteriaElem.appendChild(textElem); + + return outputProcessor; + } + + /** + * Creates the data criteria for qdm elements. + * + * @param me the me + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @return the string + */ + private void createDataCriteriaForQDMELements( + MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor) { + // XPath String for only QDM's. + String xPathForOccurQDMNoAttribs = + "/measure/elementLookUp/qdm[@datatype != 'attribute'][@instance]"; + String xPathForQDMNoAttribs = "/measure/elementLookUp/qdm[@datatype != 'attribute']"; + String xPathForQDMAttributes = "/measure/elementLookUp/qdm[@datatype = 'attribute']"; + String xpathForSupplementalQDMs = "/measure/elementLookUp/qdm[@suppDataElement = 'true']"; + String xpathForOtherSupplementalQDMs = "/measure/supplementalDataElements/elementRef/@id"; + String xpathForMeasureGroupingItemCount = "/measure//itemCount/elementRef/@id"; + + try { + + NodeList occurQdmNoAttributeNodeList = + simpleXmlprocessor.findNodeList( + simpleXmlprocessor.getOriginalDoc(), xPathForOccurQDMNoAttribs); + generateOccurrenceQDMEntries( + simpleXmlprocessor, dataCriteriaXMLProcessor, occurQdmNoAttributeNodeList); + + NodeList qdmNoAttributeNodeList = + simpleXmlprocessor.findNodeList( + simpleXmlprocessor.getOriginalDoc(), xPathForQDMNoAttribs); + generateQDMEntries(dataCriteriaXMLProcessor, simpleXmlprocessor, qdmNoAttributeNodeList); + + NodeList qdmAttributeNodeList = + simpleXmlprocessor.findNodeList( + simpleXmlprocessor.getOriginalDoc(), xPathForQDMAttributes); + generateQDMAttributeEntries( + dataCriteriaXMLProcessor, simpleXmlprocessor, qdmAttributeNodeList); + // generating QDM Entries for default Supplemental Data Elements + NodeList supplementalQDMNodeList = + simpleXmlprocessor.findNodeList( + simpleXmlprocessor.getOriginalDoc(), xpathForSupplementalQDMs); + generateSupplementalDataQDMEntries( + simpleXmlprocessor, dataCriteriaXMLProcessor, supplementalQDMNodeList); + + // generating QDM Entries for other Supplemental Data Elements + NodeList supplementalDataElements = + me.getSimpleXmlProcessor() + .findNodeList( + me.getSimpleXmlProcessor().getOriginalDoc(), xpathForOtherSupplementalQDMs); + generateOtherSupplementalDataQDMEntries( + me, dataCriteriaXMLProcessor, supplementalDataElements); + + // generating QDM entries for measureGrouping ItemCountlist + NodeList measureGroupingItemCountList = + simpleXmlprocessor.findNodeList( + simpleXmlprocessor.getOriginalDoc(), xpathForMeasureGroupingItemCount); + generateMeasureGrpnItemCountQDMEntries( + me, dataCriteriaXMLProcessor, measureGroupingItemCountList); + + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + + protected void getExtensionValueBasedOnVersion(MeasureExport me) { + extensionValue = VERSION_4_3_ID; + } + + /** + * Generate measure grp item count qdm entries. + * + * @param me the me + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param measureGroupingItemCountList the measure grouping item count list + * @throws XPathExpressionException the x path expression exception + */ + private void generateMeasureGrpnItemCountQDMEntries( + MeasureExport me, + XmlProcessor dataCriteriaXMLProcessor, + NodeList measureGroupingItemCountList) + throws XPathExpressionException { + + if ((measureGroupingItemCountList == null) || (measureGroupingItemCountList.getLength() < 1)) { + return; + } + List itemCountIDList = new ArrayList(); + for (int i = 0; i < measureGroupingItemCountList.getLength(); i++) { + if (!itemCountIDList.contains(measureGroupingItemCountList.item(i).getNodeValue())) { + itemCountIDList.add(measureGroupingItemCountList.item(i).getNodeValue()); + } + } + String xpathforElementLookUpElements = + "/measure/elementLookUp/qdm[" + getUUIDString(itemCountIDList) + "]"; + + NodeList measureGroupingElementRefNodeList = + me.getSimpleXmlProcessor() + .findNodeList( + me.getSimpleXmlProcessor().getOriginalDoc(), xpathforElementLookUpElements); + generateItemCountQDMEntries(me, dataCriteriaXMLProcessor, measureGroupingElementRefNodeList); + } + + /** + * Generate supplemental data qdm entries. + * + * @param me the me + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param supplementalDataElements the supplemental data elements + * @throws XPathExpressionException the x path expression exception + */ + private void generateOtherSupplementalDataQDMEntries( + MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, NodeList supplementalDataElements) + throws XPathExpressionException { + if ((supplementalDataElements == null) || (supplementalDataElements.getLength() < 1)) { + return; + } + List supplementalElemenRefIds = new ArrayList(); + for (int i = 0; i < supplementalDataElements.getLength(); i++) { + supplementalElemenRefIds.add(supplementalDataElements.item(i).getNodeValue()); + } + + String xpathforOtherSupplementalDataElements = + "/measure/elementLookUp/qdm[" + + getUUIDString(supplementalElemenRefIds) + + "][@suppDataElement != 'true']"; + NodeList otherSupplementalQDMNodeList = + me.getSimpleXmlProcessor() + .findNodeList( + me.getSimpleXmlProcessor().getOriginalDoc(), xpathforOtherSupplementalDataElements); + + generateSupplementalDataQDMEntries(me, dataCriteriaXMLProcessor, otherSupplementalQDMNodeList); + } + + /** + * Generate supplemental data qdm entries. + * + * @param me the me + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param qdmNodeList the qdm node list + * @throws XPathExpressionException the x path expression exception + */ + private void generateSupplementalDataQDMEntries( + MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, NodeList qdmNodeList) + throws XPathExpressionException { + for (int j = 0; j < qdmNodeList.getLength(); j++) { + Node qdmNode = qdmNodeList.item(j); + String qdmName = qdmNode.getAttributes().getNamedItem("name").getNodeValue(); + String qdmDatatype = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmUUID = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); + String qdmExtension = qdmName.replaceAll("\\s", "") + "_" + qdmDatatype.replaceAll("\\s", ""); + String xpathForQDMEntry = + "/root/component/dataCriteriaSection/entry/*/id[@root='" + + qdmUUID + + "'][@extension=\"" + + qdmExtension + + "\"]"; + Node qmdEntryIDNode = + dataCriteriaXMLProcessor.findNode( + dataCriteriaXMLProcessor.getOriginalDoc(), xpathForQDMEntry); + if (qmdEntryIDNode == null) { + createXmlForDataCriteria( + qdmNode, dataCriteriaXMLProcessor, me.getSimpleXmlProcessor(), null); + } + } + } + + /** + * Generate Item Count qdm entries. + * + * @param me the me + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param qdmNodeList the qdm node list + * @throws XPathExpressionException the x path expression exception + */ + private void generateItemCountQDMEntries( + MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, NodeList qdmNodeList) + throws XPathExpressionException { + for (int j = 0; j < qdmNodeList.getLength(); j++) { + Node qdmNode = qdmNodeList.item(j); + String qdmName = qdmNode.getAttributes().getNamedItem("name").getNodeValue(); + String qdmDatatype = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmUUID = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); + String qdmExtension = qdmName.replaceAll("\\s", "") + "_" + qdmDatatype.replaceAll("\\s", ""); + if (qdmNode.getAttributes().getNamedItem("instance") != null) { + String instanceOfValue = qdmNode.getAttributes().getNamedItem("instance").getNodeValue(); + String newExtension = instanceOfValue.replaceAll("\\s", "") + "_" + qdmExtension; + qdmExtension = newExtension; + } + String xpathForQDMEntry = + "/root/component/dataCriteriaSection/entry/*/id[@root='" + + qdmUUID + + "'][@extension=\"" + + qdmExtension + + "\"]"; + Node qmdEntryIDNode = + dataCriteriaXMLProcessor.findNode( + dataCriteriaXMLProcessor.getOriginalDoc(), xpathForQDMEntry); + if (qmdEntryIDNode == null) { + createXmlForDataCriteria( + qdmNode, dataCriteriaXMLProcessor, me.getSimpleXmlProcessor(), null); + } + } + } + + /** + * Generate default supplemental data qdm entries. + * + * @param simpleXmlprocessor the simple xmlprocessor + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param supplementalQDMNodeList the supplemental qdm node list + * @throws XPathExpressionException the x path expression exception + */ + private void generateSupplementalDataQDMEntries( + XmlProcessor simpleXmlprocessor, + XmlProcessor dataCriteriaXMLProcessor, + NodeList supplementalQDMNodeList) + throws XPathExpressionException { + + if (supplementalQDMNodeList == null) { + return; + } + + for (int i = 0; i < supplementalQDMNodeList.getLength(); i++) { + Node qdmNode = supplementalQDMNodeList.item(i); + // generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, qdmNode); + createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, null); + } + } + + /** + * Gets the UUID string. + * + * @param uuidList the uuid list + * @return the UUID string + */ + private String getUUIDString(List uuidList) { + String uuidXPathString = ""; + for (String uuidString : uuidList) { + uuidXPathString += "@uuid = '" + uuidString + "' or"; + } + + uuidXPathString = uuidXPathString.substring(0, uuidXPathString.lastIndexOf(" or")); + return uuidXPathString; + } + + /** + * This method will populate a map of all reference elements for the Occurrence elements. + * + * @param simpleXmlprocessor the simple xmlprocessor + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param occurQdmNoAttributeNodeList the occur qdm no attribute node list + * @throws XPathExpressionException the x path expression exception + */ + private void generateOccurrenceQDMEntries( + XmlProcessor simpleXmlprocessor, + XmlProcessor dataCriteriaXMLProcessor, + NodeList occurQdmNoAttributeNodeList) + throws XPathExpressionException { + + Map map = new HashMap(); + + for (int i = 0; i < occurQdmNoAttributeNodeList.getLength(); i++) { + Node occurQdmNode = occurQdmNoAttributeNodeList.item(i); + String datatype = occurQdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String oid = occurQdmNode.getAttributes().getNamedItem(OID).getNodeValue(); + + if (!map.containsKey(datatype + "-" + oid)) { + map.put(datatype + "-" + oid, occurQdmNode); + } + } + + for (Node occurNode : map.values()) { + String datatype = occurNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String oid = occurNode.getAttributes().getNamedItem(OID).getNodeValue(); + + String xpath = + "/measure/elementLookUp/qdm[@datatype != 'attribute'][not(@instance)][@oid = '" + + oid + + "'][@datatype = \"" + + datatype + + "\"]"; + Node nodeToUse = simpleXmlprocessor.findNode(simpleXmlprocessor.getOriginalDoc(), xpath); + boolean forceGenerate = true; + if (nodeToUse == null) { + nodeToUse = occurNode.cloneNode(true); + nodeToUse.getAttributes().removeNamedItem("instance"); + forceGenerate = false; + } + + generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, nodeToUse, forceGenerate); + occurrenceMap.put(datatype + "-" + oid, nodeToUse); + } + } + + /** + * Generate qdm entries. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param qdmNoAttributeNodeList the qdm no attribute node list + * @throws XPathExpressionException the x path expression exception + */ + private void generateQDMEntries( + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + NodeList qdmNoAttributeNodeList) + throws XPathExpressionException { + + if (qdmNoAttributeNodeList == null) { + return; + } + + for (int i = 0; i < qdmNoAttributeNodeList.getLength(); i++) { + Node qdmNode = qdmNoAttributeNodeList.item(i); + generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, qdmNode); + } + } + + /** + * Generate qdm entry. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param qdmNode the qdm node + * @throws XPathExpressionException the x path expression exception + */ + private void generateQDMEntry( + XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, Node qdmNode) + throws XPathExpressionException { + generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, qdmNode, false); + } + + /** + * Generate qdm entry. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param qdmNode the qdm node + * @param forceGenerate the force generate + * @throws XPathExpressionException the x path expression exception + */ + private void generateQDMEntry( + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node qdmNode, + boolean forceGenerate) + throws XPathExpressionException { + String qdmUUID = qdmNode.getAttributes().getNamedItem(UUID).getNodeValue(); + + String xPathForIndividualElementRefs = + "/measure/subTreeLookUp//elementRef[@id='" + qdmUUID + "'][not(attribute)]"; + NodeList elementRefList = + simpleXmlprocessor.findNodeList( + simpleXmlprocessor.getOriginalDoc(), xPathForIndividualElementRefs); + if (forceGenerate || (elementRefList.getLength() > 0)) { + createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, null); + } + } + + /** + * Generate qdm attribute entries. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param qdmAttributeNodeList the qdm attribute node list + * @throws XPathExpressionException the x path expression exception + */ + private void generateQDMAttributeEntries( + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + NodeList qdmAttributeNodeList) + throws XPathExpressionException { + if (qdmAttributeNodeList != null) { + for (int i = 0; i < qdmAttributeNodeList.getLength(); i++) { + Node attributeQDMNode = qdmAttributeNodeList.item(i); + String qdmUUID = attributeQDMNode.getAttributes().getNamedItem(UUID).getNodeValue(); + + // Generate entries for Negation Rationale + generateNegationRationaleEntries( + dataCriteriaXMLProcessor, simpleXmlprocessor, attributeQDMNode, qdmUUID); + + // Generate entries for "Value Set" attributes + generateValueSetAttribEntries( + dataCriteriaXMLProcessor, simpleXmlprocessor, attributeQDMNode, qdmUUID, "Value Set"); + } + } + // Generate entries for "Check if Present", attributes + generateNonValuesetAttribEntries(dataCriteriaXMLProcessor, simpleXmlprocessor); + generateDateTimeAttributeEntries(dataCriteriaXMLProcessor, simpleXmlprocessor); + } + + /** + * Generate negation rationale entries. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + * @param qdmUUID the qdm uuid + * @throws XPathExpressionException the x path expression exception + */ + private void generateNegationRationaleEntries( + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode, + String qdmUUID) + throws XPathExpressionException { + String xPathForAttributeUse = + "/measure/subTreeLookUp/subTree//elementRef/attribute[@qdmUUID='" + + qdmUUID + + "'][@name='negation rationale']"; + NodeList usedAttributeNodeList = + simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), xPathForAttributeUse); + if (usedAttributeNodeList == null) { + return; + } + + for (int j = 0; j < usedAttributeNodeList.getLength(); j++) { + Node attributeNode = usedAttributeNodeList.item(j); + Node parentElementRefNode = attributeNode.getParentNode(); + String qdmNodeUUID = parentElementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + + String xPathForQDM = "/measure/elementLookUp/qdm[@uuid='" + qdmNodeUUID + "']"; + Node qdmNode = simpleXmlprocessor.findNode(simpleXmlprocessor.getOriginalDoc(), xPathForQDM); + + if (qdmNode == null) { + continue; + } + + // We need some way of letting the methods downstream know that this is a + // "negation rationale" attribute w/o sending the tag node. + Node clonedAttributeQDMNode = attributeQDMNode.cloneNode(false); + clonedAttributeQDMNode.setUserData(ATTRIBUTE_NAME, NEGATION_RATIONALE, null); + clonedAttributeQDMNode.setUserData(ATTRIBUTE_MODE, VALUE_SET, null); + clonedAttributeQDMNode.setUserData( + ATTRIBUTE_UUID, + attributeNode.getAttributes().getNamedItem("attrUUID").getNodeValue(), + null); + + createXmlForDataCriteria( + qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, clonedAttributeQDMNode); + } + } + + /** + * Generate value set attrib entries. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + * @param qdmUUID the qdm uuid + * @param modeValue the mode value + * @throws XPathExpressionException the x path expression exception + */ + private void generateValueSetAttribEntries( + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode, + String qdmUUID, + String modeValue) + throws XPathExpressionException { + String xPathForAttributeUse = + "/measure/subTreeLookUp/subTree//elementRef/attribute[@qdmUUID='" + + qdmUUID + + "'][@name != 'negation rationale'][@mode = '" + + modeValue + + "']"; + NodeList usedAttributeNodeList = + simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), xPathForAttributeUse); + + if (usedAttributeNodeList == null) { + return; + } + + for (int j = 0; j < usedAttributeNodeList.getLength(); j++) { + Node attributeNode = usedAttributeNodeList.item(j); + Node parentElementRefNode = attributeNode.getParentNode(); + String qdmNodeUUID = parentElementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + + String xPathForQDM = "/measure/elementLookUp/qdm[@uuid='" + qdmNodeUUID + "']"; + Node qdmNode = simpleXmlprocessor.findNode(simpleXmlprocessor.getOriginalDoc(), xPathForQDM); + + if (qdmNode == null) { + continue; + } + + // We need some way of letting the methods downstream know the name of this + // attribute w/o sending the tag node. + Node clonedAttributeQDMNode = attributeQDMNode.cloneNode(false); + clonedAttributeQDMNode.setUserData( + ATTRIBUTE_NAME, attributeNode.getAttributes().getNamedItem(NAME).getNodeValue(), null); + clonedAttributeQDMNode.setUserData( + ATTRIBUTE_MODE, attributeNode.getAttributes().getNamedItem("mode").getNodeValue(), null); + clonedAttributeQDMNode.setUserData( + ATTRIBUTE_UUID, + attributeNode.getAttributes().getNamedItem("attrUUID").getNodeValue(), + null); + + createXmlForDataCriteria( + qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, clonedAttributeQDMNode); + } + } + + /** + * This method will look for attributes of mode = 'Check if Present', 'Equal To', 'Less Than (or + * Equal)', Greater than (or Equal). + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @throws XPathExpressionException the x path expression exception + */ + private void generateNonValuesetAttribEntries( + XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor) + throws XPathExpressionException { + String xPathForAttributeUse = + "/measure/subTreeLookUp/subTree//elementRef/attribute[@mode = 'Check if Present' or @mode='Equal To' or starts-with(@mode,'Less Than') or starts-with(@mode, 'Greater Than')]" + + "[@name != 'negation rationale' and @name != '" + + START_DATETIME + + "' and @name !='" + + STOP_DATETIME + + "' " + + "" + + "and @name != '" + + FACILITY_LOCATION_ARRIVAL_DATETIME + + "' and @name != '" + + FACILITY_LOCATION_DEPARTURE_DATETIME + + "' and @name != '" + + FACILITY_LOCATION + + "' and @name != '" + + ADMISSION_DATETIME + + "' and @name != '" + + DISCHARGE_DATETIME + + "' and @name != '" + + ACTIVE_DATETIME + + "' and @name != '" + + INCISION_DATETIME + + "' and @name != '" + + DATE + + "' and @name != '" + + TIME + + "' and @name != '" + + REMOVAL_DATETIME + + "' and @name != '" + + SIGNED_DATETIME + + "' and @name != '" + + ABATEMENT_DATETIME + + "'" + + "and @name != '" + + RECORDED_DATETIME + + "' and @name != '" + + ONSET_DATETIME + + "']"; + NodeList usedAttributeNodeList = + simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), xPathForAttributeUse); + + if (usedAttributeNodeList == null) { + return; + } + + for (int j = 0; j < usedAttributeNodeList.getLength(); j++) { + Node attributeNode = usedAttributeNodeList.item(j); + Node parentElementRefNode = attributeNode.getParentNode(); + String qdmNodeUUID = parentElementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + + String xPathForQDM = "/measure/elementLookUp/qdm[@uuid='" + qdmNodeUUID + "']"; + Node qdmNode = simpleXmlprocessor.findNode(simpleXmlprocessor.getOriginalDoc(), xPathForQDM); + + if (qdmNode == null) { + continue; + } + + // We need some way of letting the methods downstream know the name of this + // attribute w/o sending the tag node. + Node clonedAttributeQDMNode = attributeNode.cloneNode(false); + clonedAttributeQDMNode.setUserData( + ATTRIBUTE_NAME, attributeNode.getAttributes().getNamedItem(NAME).getNodeValue(), null); + clonedAttributeQDMNode.setUserData( + ATTRIBUTE_MODE, attributeNode.getAttributes().getNamedItem("mode").getNodeValue(), null); + clonedAttributeQDMNode.setUserData( + ATTRIBUTE_UUID, + attributeNode.getAttributes().getNamedItem("attrUUID").getNodeValue(), + null); + + createXmlForDataCriteria( + qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, clonedAttributeQDMNode); + } + } + + /** + * Generate date time attribute entries. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @throws XPathExpressionException the x path expression exception + */ + private void generateDateTimeAttributeEntries( + XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor) + throws XPathExpressionException { + + String xPathForAttributeUse = + "/measure/subTreeLookUp/subTree//elementRef/attribute" + + "[@name = '" + + START_DATETIME + + "' or @name='" + + STOP_DATETIME + + "' or @name = '" + + FACILITY_LOCATION_ARRIVAL_DATETIME + + "' or @name = '" + + FACILITY_LOCATION_DEPARTURE_DATETIME + + "' or @name = '" + + FACILITY_LOCATION + + "' or @name ='" + + ADMISSION_DATETIME + + "' or @name ='" + + DISCHARGE_DATETIME + + "'" + + "or @name ='" + + ACTIVE_DATETIME + + "' or @name ='" + + INCISION_DATETIME + + "' or @name ='" + + DATE + + "' or @name ='" + + TIME + + "'" + + "or @name ='" + + REMOVAL_DATETIME + + "' or @name ='" + + SIGNED_DATETIME + + "' or @name ='" + + ONSET_DATETIME + + "' or @name ='" + + ABATEMENT_DATETIME + + "' " + + "or @name ='" + + RECORDED_DATETIME + + "']" + + "[@mode='Equal To' or starts-with(@mode,'Less Than') or starts-with(@mode, 'Greater Than') or @mode='Check if Present']"; + + NodeList usedAttributeNodeList = + simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), xPathForAttributeUse); + + if (usedAttributeNodeList == null) { + return; + } + + for (int j = 0; j < usedAttributeNodeList.getLength(); j++) { + Node attributeNode = usedAttributeNodeList.item(j); + Node parentElementRefNode = attributeNode.getParentNode(); + String qdmNodeUUID = parentElementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + + String xPathForQDM = "/measure/elementLookUp/qdm[@uuid='" + qdmNodeUUID + "']"; + Node qdmNode = simpleXmlprocessor.findNode(simpleXmlprocessor.getOriginalDoc(), xPathForQDM); + + if (qdmNode == null) { + continue; + } + + // We need some way of letting the methods downstream know the name of this + // attribute w/o sending the tag node. + Node clonedAttributeQDMNode = attributeNode.cloneNode(false); + clonedAttributeQDMNode.setUserData( + ATTRIBUTE_NAME, attributeNode.getAttributes().getNamedItem(NAME).getNodeValue(), null); + clonedAttributeQDMNode.setUserData( + ATTRIBUTE_MODE, attributeNode.getAttributes().getNamedItem("mode").getNodeValue(), null); + clonedAttributeQDMNode.setUserData( + ATTRIBUTE_UUID, + attributeNode.getAttributes().getNamedItem("attrUUID").getNodeValue(), + null); + String attrDate = ""; + if (attributeNode.getAttributes().getNamedItem("attrDate") != null) { + attrDate = attributeNode.getAttributes().getNamedItem("attrDate").getNodeValue(); + } + clonedAttributeQDMNode.setUserData(ATTRIBUTE_DATE, attrDate, null); + + createXmlForDataCriteria( + qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor, clonedAttributeQDMNode); + } + } + + /** + * Create xml for data criteria. + * + * @param qdmNode the qdm node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + * @return void + */ + private void createXmlForDataCriteria( + Node qdmNode, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode) { + String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); + String xPathForTemplate = "/templates/template[text()='" + dataType.toLowerCase() + "']"; + String actNodeStr = ""; + try { + + Node templateNode = + templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xPathForTemplate); + if (templateNode != null) { + String attrClass = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); + String xpathForAct = "/templates/acts/act[@a_id='" + attrClass + "']"; + Node actNode = + templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xpathForAct); + if (actNode != null) { + actNodeStr = actNode.getTextContent(); + } + + createDataCriteriaElementTag( + actNodeStr, + templateNode, + qdmNode, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + templateXMLProcessor, + attributeQDMNode); + } + + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + + /** + * Gets the creates the data create element tag. + * + * @param actNodeStr the act node str + * @param templateNode the template node + * @param qdmNode the qdm node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param templateXMLProcessor - templateXmlProcessor + * @param attributeQDMNode - Attribute QDM Node. + * @throws XPathExpressionException the x path expression exception + */ + private void createDataCriteriaElementTag( + String actNodeStr, + Node templateNode, + Node qdmNode, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + XmlProcessor templateXMLProcessor, + Node attributeQDMNode) + throws XPathExpressionException { + String oidValue = templateNode.getAttributes().getNamedItem(OID).getNodeValue(); + String classCodeValue = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); + String moodValue = templateNode.getAttributes().getNamedItem(MOOD).getNodeValue(); + String statusValue = templateNode.getAttributes().getNamedItem("status").getNodeValue(); + String rootValue = qdmNode.getAttributes().getNamedItem(ID).getNodeValue(); + String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); + + String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); + String qdmTaxonomy = qdmNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); + String entryCommentText = dataType; + // Local variable changes. + String qdmLocalVariableName = qdmName + "_" + dataType; + String localVariableName = qdmLocalVariableName; + if (qdmNode.getAttributes().getNamedItem("instance") != null) { + qdmLocalVariableName = + qdmNode.getAttributes().getNamedItem("instance").getNodeValue() + + "_" + + qdmLocalVariableName; + localVariableName = + qdmNode.getAttributes().getNamedItem("instance").getNodeValue() + + "of" + + localVariableName; + } + qdmLocalVariableName = StringUtils.deleteWhitespace(qdmLocalVariableName); + if (attributeQDMNode != null) { + if (attributeQDMNode.getUserData(ATTRIBUTE_UUID) != null) { + qdmLocalVariableName = (String) attributeQDMNode.getUserData(ATTRIBUTE_UUID); + } + if (attributeQDMNode.getUserData(ATTRIBUTE_NAME) != null) { + entryCommentText = entryCommentText + " - " + attributeQDMNode.getUserData(ATTRIBUTE_NAME); + localVariableName = localVariableName + "_" + attributeQDMNode.getUserData(ATTRIBUTE_NAME); + } + if (attributeQDMNode.getUserData(ATTRIBUTE_MODE) != null) { + entryCommentText = + entryCommentText + " With " + attributeQDMNode.getUserData(ATTRIBUTE_MODE); + localVariableName = localVariableName + "_" + attributeQDMNode.getUserData(ATTRIBUTE_MODE); + } + } + localVariableName = StringUtils.deleteWhitespace(localVariableName); + + Element dataCriteriaSectionElem = + (Element) + dataCriteriaXMLProcessor + .getOriginalDoc() + .getElementsByTagName("dataCriteriaSection") + .item(0); + Element componentElem = + (Element) + dataCriteriaXMLProcessor.getOriginalDoc().getElementsByTagName("component").item(0); + Attr nameSpaceAttr = dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:xsi"); + nameSpaceAttr.setNodeValue(nameSpace); + componentElem.setAttributeNodeNS(nameSpaceAttr); + Attr qdmNameSpaceAttr = dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:qdm"); + qdmNameSpaceAttr.setNodeValue("urn:hhs-qdm:hqmf-r2-extensions:v1"); + componentElem.setAttributeNodeNS(qdmNameSpaceAttr); + // creating Entry Tag + Element entryElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("entry"); + entryElem.setAttribute(TYPE_CODE, "DRIV"); + // Local Variable Name Tag - Inside Entry tag. + Element localVarElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement("localVariableName"); + localVarElem.setAttribute(VALUE, localVariableName + "_" + UUIDUtilClient.uuid(5)); + entryElem.appendChild(localVarElem); + Element dataCriteriaElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(actNodeStr); + entryElem.appendChild(dataCriteriaElem); + dataCriteriaElem.setAttribute(CLASS_CODE, classCodeValue); + dataCriteriaElem.setAttribute(MOOD_CODE, moodValue); + Element templateId = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TEMPLATE_ID); + dataCriteriaElem.appendChild(templateId); + Element itemChild = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); + itemChild.setAttribute(ROOT, oidValue); + if (templateNode.getAttributes().getNamedItem("addExtensionInTemplate") == null) { + + itemChild.setAttribute("extension", extensionValue); + } + templateId.appendChild(itemChild); + Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); + idElem.setAttribute(ROOT, rootValue); + idElem.setAttribute("extension", qdmLocalVariableName); + dataCriteriaElem.appendChild(idElem); + + boolean appendEntryElem = false; + String occurString = dataType + "-" + qdmOidValue; + + if (qdmNode.getAttributes().getNamedItem("instance") != null) { + generateOutboundForOccur( + templateNode, + qdmNode, + dataCriteriaElem, + occurString, + dataCriteriaXMLProcessor, + simpleXmlprocessor); + entryCommentText = + qdmNode.getAttributes().getNamedItem("instance").getNodeValue() + " " + entryCommentText; + appendEntryElem = true; + } else if (!occurrenceMap.containsKey(occurString) || (attributeQDMNode != null)) { + + String isAddCodeTag = templateNode.getAttributes().getNamedItem("addCodeTag").getNodeValue(); + if ("true".equalsIgnoreCase(isAddCodeTag)) { // Add Code Element to DataCriteria Element. + addCodeElementToDataCriteriaElement( + templateNode, dataCriteriaXMLProcessor, qdmNode, dataCriteriaElem); + } + Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, dataType); + dataCriteriaElem.appendChild(titleElem); + Element statusCodeElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement("statusCode"); + statusCodeElem.setAttribute(CODE, statusValue); + dataCriteriaElem.appendChild(statusCodeElem); + // Add value tag in entry element. + String addValueSetElement = + templateNode.getAttributes().getNamedItem("addValueTag").getNodeValue(); + if ("true".equalsIgnoreCase(addValueSetElement)) { + Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(VALUE); + Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); + if (valueTypeAttr != null) { + valueElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); + } + + Node valueCodeSystem = templateNode.getAttributes().getNamedItem("valueCodeSystem"); + Node valueCode = templateNode.getAttributes().getNamedItem("valueCode"); + Node valueDisplayName = templateNode.getAttributes().getNamedItem("valueDisplayName"); + Node valueCodeSystemName = templateNode.getAttributes().getNamedItem("valueCodeSystemName"); + + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + if ((valueCode != null) && (valueCodeSystem != null)) { + valueElem.setAttribute("code", valueCode.getNodeValue()); + valueElem.setAttribute("codeSystem", valueCodeSystem.getNodeValue()); + if (valueCodeSystemName != null) { + valueElem.setAttribute("codeSystemName", valueCodeSystemName.getNodeValue()); + } + if (valueDisplayName != null) { + displayNameElem.setAttribute(VALUE, valueDisplayName.getNodeValue()); + } + } else { + valueElem.setAttribute("valueSet", qdmOidValue); + addValueSetVersion(qdmNode, valueElem); + displayNameElem.setAttribute( + VALUE, + HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + + " " + + qdmTaxonomy + + " Value Set"); + } + if (displayNameElem.hasAttribute(VALUE)) { + valueElem.appendChild(displayNameElem); + } + + dataCriteriaElem.appendChild(valueElem); + } + if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { + appendSubTemplateNode( + templateNode, + dataCriteriaXMLProcessor, + templateXMLProcessor, + dataCriteriaElem, + qdmNode, + attributeQDMNode); + } + + appendEntryElem = true; + } + if (appendEntryElem) { + if (attributeQDMNode != null) { + createDataCriteriaForAttributes( + qdmNode, + dataCriteriaElem, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + attributeQDMNode, + false); + } + dataCriteriaSectionElem.appendChild(entryElem); + } + } + + /** + * Method to add valueSetVersion attribute in value element tag. + * + * @param qdmNode the qdm node + * @param valueElem the value elem + */ + protected void addValueSetVersion(Node qdmNode, Element valueElem) { + String valueSetVersion = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); + boolean addVersionToValueTag = false; + if ("1.0".equals(valueSetVersion) + || "1".equals(valueSetVersion) + || StringUtils.isBlank(valueSetVersion)) { + if (qdmNode.getAttributes().getNamedItem("expansionIdentifier") != null) { + valueSetVersion = + "mat.vsac:profile:" + + qdmNode.getAttributes().getNamedItem("expansionIdentifier").getNodeValue(); + addVersionToValueTag = true; + } else { + addVersionToValueTag = false; + } + } else { + valueSetVersion = + "mat.vsac:version:" + qdmNode.getAttributes().getNamedItem("version").getNodeValue(); + addVersionToValueTag = true; + } + if (addVersionToValueTag) { + valueElem.setAttribute("valueSetVersion", valueSetVersion); + } + } + + /** + * Generate outbound for occur. + * + * @param templateNode the template node + * @param qdmNode the qdm node + * @param dataCriteriaElem the data criteria elem + * @param occurString the occur string + */ + private void generateOutboundForOccur( + Node templateNode, + Node qdmNode, + Element dataCriteriaElem, + String occurString, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor) { + Node refNode = occurrenceMap.get(occurString); + + logger.debug("In generateOutboundForOccur()..refNode:" + refNode); + logger.debug("----------Occurance map:" + occurrenceMap); + + if (refNode != null) { + + try { + Node cloneRefNode = refNode.cloneNode(true); + String name = cloneRefNode.getAttributes().getNamedItem("name").getNodeValue(); + String occName = qdmNode.getAttributes().getNamedItem("instance").getNodeValue(); + cloneRefNode.getAttributes().getNamedItem("name").setNodeValue(occName + "_" + name); + + if (!occurrenceMap.containsKey(occName + occurString)) { + occurrenceMap.remove(occurString); + generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, cloneRefNode, true); + occurrenceMap.put(occurString, refNode); + occurrenceMap.put(occName + occurString, cloneRefNode); + } + + String refRootValue = cloneRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + + String refDatatype = cloneRefNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String refQdmName = cloneRefNode.getAttributes().getNamedItem("name").getNodeValue(); + String reExt = StringUtils.deleteWhitespace(refQdmName + "_" + refDatatype); + + Element outboundRelElem = + dataCriteriaElem.getOwnerDocument().createElement("outboundRelationship"); + outboundRelElem.setAttribute("typeCode", "OCCR"); + + Element criteriaRefElem = + dataCriteriaElem.getOwnerDocument().createElement("criteriaReference"); + String refClassCodeValue = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); + String refMoodValue = templateNode.getAttributes().getNamedItem(MOOD).getNodeValue(); + criteriaRefElem.setAttribute(CLASS_CODE, refClassCodeValue); + criteriaRefElem.setAttribute(MOOD_CODE, refMoodValue); + + Element idRelElem = dataCriteriaElem.getOwnerDocument().createElement(ID); + idRelElem.setAttribute(ROOT, refRootValue); + idRelElem.setAttribute("extension", reExt); + + criteriaRefElem.appendChild(idRelElem); + outboundRelElem.appendChild(criteriaRefElem); + dataCriteriaElem.appendChild(outboundRelElem); + Node templateIdNode = dataCriteriaElem.getElementsByTagName("templateId").item(0); + dataCriteriaElem.removeChild(templateIdNode); + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + } + + /** + * Add Code Element To data Criteria Element based on condition. + * + * @param templateNode - Node + * @param dataCriteriaXMLProcessor - XmlProcessor + * @param qdmNode the qdm node + * @param dataCriteriaElem - Element + */ + private void addCodeElementToDataCriteriaElement( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + Node qdmNode, + Element dataCriteriaElem) { + String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); + + String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); + String qdmTaxonomy = qdmNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); + + // Patient Characteristic data type - contains code tag with valueSetId + // attribute and no title and value set tag. + boolean isPatientChar = templateNode.getAttributes().getNamedItem("valueSetId") != null; + boolean isAddValueSetInCodeTrue = + templateNode.getAttributes().getNamedItem("addValueSetInCode") != null; + boolean isIntervention = + ("Intervention, Order".equals(dataType) + || "Intervention, Performed".equals(dataType) + || "Intervention, Recommended".equals(dataType)); + if (isAddValueSetInCodeTrue) { + Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); + if (valueTypeAttr != null) { + codeElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); + } + codeElem.setAttribute("valueSet", qdmOidValue); + addValueSetVersion(qdmNode, codeElem); + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + String displayName = ""; + displayName = + HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + + " " + + qdmTaxonomy + + " Value Set"; + displayNameElem.setAttribute(VALUE, displayName); + codeElem.appendChild(displayNameElem); + dataCriteriaElem.appendChild(codeElem); + + } else if (isPatientChar) { + Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + codeElem.setAttribute( + templateNode.getAttributes().getNamedItem("valueSetId").getNodeValue(), qdmOidValue); + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + displayNameElem.setAttribute( + VALUE, + HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + + " " + + qdmTaxonomy + + " Value Set"); + codeElem.appendChild(displayNameElem); + dataCriteriaElem.appendChild(codeElem); + } else if (isIntervention) { + Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + codeElem.setAttribute("valueSet", qdmOidValue); + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + displayNameElem.setAttribute( + VALUE, + HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + + " " + + qdmTaxonomy + + " Value Set"); + codeElem.appendChild(displayNameElem); + dataCriteriaElem.appendChild(codeElem); + } else { + Element codeElement = createCodeForDatatype(templateNode, dataCriteriaXMLProcessor); + if (codeElement != null) { + dataCriteriaElem.appendChild(codeElement); + } + } + } + + /** + * This method is called for populating version/expansion Identifier of value set when value set + * attribute mode is applied. If version is most recent, 1.0 or 1 is returned. + * + * @param qdmNode + * @return version + */ + private String valueSetVersionStringValue(Node qdmNode) { + String version = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); + if ("1.0".equals(version) || "1".equals(version) || StringUtils.isBlank(version)) { + if (qdmNode.getAttributes().getNamedItem("expansionIdentifier") != null) { + version = + "mat.vsac:profile:" + + qdmNode.getAttributes().getNamedItem("expansionIdentifier").getNodeValue(); + } + } else { + version = + "mat.vsac:version:" + qdmNode.getAttributes().getNamedItem("version").getNodeValue(); + } + return version; + } + + /** + * Add SubTemplate defined in Template.xml to data criteria Element. + * + * @param templateNode - Node + * @param dataCriteriaXMLProcessor - XmlProcessor for Data Criteria + * @param templateXMLProcessor -XmlProcessor for Template Xml. + * @param dataCriteriaElem - Element + * @param qdmNode the qdm node + * @param attributeQDMNode the attribute qdm node + * @throws XPathExpressionException the x path expression exception + */ + private void appendSubTemplateNode( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor templateXMLProcessor, + Element dataCriteriaElem, + Node qdmNode, + Node attributeQDMNode) + throws XPathExpressionException { + String subTemplateName = + templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); + Node subTemplateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), "/templates/subtemplates/" + subTemplateName); + NodeList subTemplateNodeChilds = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "/child::node()"); + String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); + String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); + String qdmNameDataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmTaxonomy = qdmNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); + if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { + String[] attributeToBeModified = + subTemplateNode.getAttributes().getNamedItem("changeAttribute").getNodeValue().split(","); + for (String changeAttribute : attributeToBeModified) { + NodeList attributedToBeChangedInNode = null; + attributedToBeChangedInNode = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); + if (changeAttribute.equalsIgnoreCase(ID)) { + String rootId = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("root") + .setNodeValue(rootId); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("extension") + .setNodeValue(UUIDUtilClient.uuid()); + } else if (changeAttribute.equalsIgnoreCase(CODE)) { + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("valueSet") + .setNodeValue(qdmOidValue); + String valueSetVersion = valueSetVersionStringValue(qdmNode); + if (valueSetVersion.contains("mat/vsacmodel")) { + Attr attrNode = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createAttribute("valueSetVersion"); + attrNode.setNodeValue(valueSetVersion); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attrNode); + } else { + if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("valueSetVersion") + != null) { + attributedToBeChangedInNode + .item(0) + .getAttributes() + .removeNamedItem("valueSetVersion"); + } + } + + } else if (changeAttribute.equalsIgnoreCase(DISPLAY_NAME)) { + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("value") + .setNodeValue( + HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + + " " + + qdmTaxonomy + + " value set"); + } else if (changeAttribute.equalsIgnoreCase(TITLE)) { + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("value") + .setNodeValue(qdmNameDataType); + } else if (changeAttribute.equalsIgnoreCase(ITEM)) { + for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { + Node itemNode = attributedToBeChangedInNode.item(count); + itemNode.getAttributes().getNamedItem("extension").setNodeValue(extensionValue); + } + } + } + } + for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { + Node childNode = subTemplateNodeChilds.item(i); + Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); + XmlProcessor.clean(nodeToAttach); + dataCriteriaElem.appendChild(nodeToAttach); + } + } + + /** + * Method to append Facility Location attribute template to data type. This attribute can only + * have value ser and Check If present mode's and these are added to code tag. + * + * @param templateNode the template node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param templateXMLProcessor the template xml processor + * @param dataCriteriaElem the data criteria elem + * @param attrNode the attr node + * @throws XPathExpressionException the x path expression exception + */ + private void appendSubTemplateInFacilityAttribute( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor templateXMLProcessor, + Element dataCriteriaElem, + Node attrNode) + throws XPathExpressionException { + String subTemplateName = + templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); + Node subTemplateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), "/templates/subtemplates/" + subTemplateName); + NodeList subTemplateNodeChilds = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "/child::node()"); + if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { + NodeList attributedToBeChangedInNode = null; + String[] tagToBeModified = + subTemplateNode.getAttributes().getNamedItem("changeAttribute").getNodeValue().split(","); + for (String changeAttribute : tagToBeModified) { + attributedToBeChangedInNode = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); + if (changeAttribute.equalsIgnoreCase(ID)) { + Node childNodes = attributedToBeChangedInNode.item(0).getFirstChild().getNextSibling(); + String rootId = (String) attrNode.getUserData(ATTRIBUTE_UUID); + childNodes.getAttributes().getNamedItem("root").setNodeValue(rootId); + childNodes + .getAttributes() + .getNamedItem("extension") + .setNodeValue( + StringUtils.deleteWhitespace((String) attrNode.getUserData(ATTRIBUTE_NAME))); + } else if (changeAttribute.equalsIgnoreCase(CODE)) { + String attrMode = (String) attrNode.getUserData(ATTRIBUTE_MODE); + if (VALUE_SET.equals(attrMode)) { + if (attributedToBeChangedInNode.item(0).hasAttributes()) { + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("flavorId"); + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("xsi:type"); + } + if (attributedToBeChangedInNode.item(0).hasChildNodes()) { + ((Element) attributedToBeChangedInNode.item(0)) + .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); + } + checkIfSelectedModeIsValueSet( + templateXMLProcessor, + attrNode, + subTemplateNode, + (Element) attributedToBeChangedInNode.item(0)); + } else if (CHECK_IF_PRESENT.equals(attrMode)) { + if (attributedToBeChangedInNode.item(0).hasAttributes()) { + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("valueSet"); + } + if (attributedToBeChangedInNode.item(0).hasChildNodes()) { + ((Element) attributedToBeChangedInNode.item(0)) + .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); + } + checkIfSelectedModeIsPresent( + templateXMLProcessor, + attrNode, + subTemplateNode, + (Element) attributedToBeChangedInNode.item(0)); + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("xsi:type"); + } + } else if (changeAttribute.equalsIgnoreCase(ITEM)) { + for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { + Node itemNode = attributedToBeChangedInNode.item(count); + itemNode.getAttributes().getNamedItem("extension").setNodeValue(extensionValue); + } + } + } + } + for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { + Node childNode = subTemplateNodeChilds.item(i); + Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); + XmlProcessor.clean(nodeToAttach); + checkIfOutBoundOcc(dataCriteriaElem, nodeToAttach); + } + } + + /** + * Append sub template with order attribute. + * + * @param templateNode the template node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param templateXMLProcessor the template xml processor + * @param dataCriteriaElem the data criteria elem + * @param qdmNode the qdm node + * @param attrNode the attr node + * @throws XPathExpressionException the x path expression exception + */ + private void appendSubTemplateWithOrderAttribute( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor templateXMLProcessor, + Element dataCriteriaElem, + Node qdmNode, + Node attrNode) + throws XPathExpressionException { + String subTemplateName = + templateNode.getAttributes().getNamedItem("includeOtherSubTemplate").getNodeValue(); + Node subTemplateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), "/templates/subtemplates/" + subTemplateName); + NodeList subTemplateNodeChilds = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "/child::node()"); + boolean isOrder = templateNode.getAttributes().getNamedItem("typeOrder").getNodeValue() != null; + if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { + NodeList attributedToBeChangedInNode = null; + String[] tagToBeModified = + subTemplateNode.getAttributes().getNamedItem("changeAttribute").getNodeValue().split(","); + for (String changeAttribute : tagToBeModified) { + attributedToBeChangedInNode = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); + if (changeAttribute.equalsIgnoreCase(ID)) { + Node childNodes = attributedToBeChangedInNode.item(0).getFirstChild().getNextSibling(); + String rootId = (String) attrNode.getUserData(ATTRIBUTE_UUID); + childNodes.getAttributes().getNamedItem("root").setNodeValue(rootId); + childNodes + .getAttributes() + .getNamedItem("extension") + .setNodeValue( + StringUtils.deleteWhitespace((String) attrNode.getUserData(ATTRIBUTE_NAME))); + } else if (changeAttribute.equalsIgnoreCase(ITEM)) { + for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { + Node itemNode = attributedToBeChangedInNode.item(count); + itemNode.getAttributes().getNamedItem("extension").setNodeValue(extensionValue); + } + } + } + } + + for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { + Node childNode = subTemplateNodeChilds.item(i); + Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); + XmlProcessor.clean(nodeToAttach); + checkIfOutBoundOcc(dataCriteriaElem, nodeToAttach); + } + Element timeNode = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TIME); + generateDateTimeAttributesTag( + timeNode, attrNode, dataCriteriaElem, dataCriteriaXMLProcessor, isOrder); + } + + /** + * Append sub template and add value tag based on mode. + * + * @param templateNode the template node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param templateXMLProcessor the template xml processor + * @param dataCriteriaElem the data criteria elem + * @param attrNode the attr node + * @throws XPathExpressionException the x path expression exception + */ + protected void appendSubTemplateAndAddValueTagBasedOnMode( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor templateXMLProcessor, + Element dataCriteriaElem, + Node attrNode) + throws XPathExpressionException { + + String subTemplateName = + templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); + Node subTemplateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), "/templates/subtemplates/" + subTemplateName); + + if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { + NodeList attributedToBeChangedInNode = null; + String[] tagToBeModified = + subTemplateNode.getAttributes().getNamedItem("changeAttribute").getNodeValue().split(","); + for (String changeAttribute : tagToBeModified) { + attributedToBeChangedInNode = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); + if (changeAttribute.equalsIgnoreCase(ID)) { + String rootId = (String) attrNode.getUserData(ATTRIBUTE_UUID); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("root") + .setNodeValue(rootId); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("extension") + .setNodeValue(UUIDUtilClient.uuid()); + } else if (changeAttribute.equalsIgnoreCase(ITEM)) { + for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { + Node itemNode = attributedToBeChangedInNode.item(count); + itemNode.getAttributes().getNamedItem("extension").setNodeValue(UUIDUtilClient.uuid()); + String rootId = (String) attrNode.getUserData(ATTRIBUTE_UUID); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("root") + .setNodeValue(rootId); + } + + } else if (changeAttribute.equalsIgnoreCase(VALUE)) { + String attrMode = (String) attrNode.getUserData(ATTRIBUTE_MODE); + if (CHECK_IF_PRESENT.equals(attrMode)) { + if (attributedToBeChangedInNode.item(0).hasAttributes()) { + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("valueSet"); + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("flavorId"); + } + String elementName = + templateNode.getAttributes().getNamedItem("addTagInValueSet").getNodeValue(); + NodeList el = attributedToBeChangedInNode.item(0).getChildNodes(); + Element childElement = null; + if (el.getLength() == 0) { + childElement = + attributedToBeChangedInNode.item(0).getOwnerDocument().createElement(elementName); + } else { + childElement = (Element) el; + if (childElement.hasChildNodes()) { + for (int j = childElement.getChildNodes().getLength(); j > 0; j--) { + Node ChildNode = childElement.getChildNodes().item(j - 1); + childElement.removeChild(ChildNode); + } + } + childElement = + attributedToBeChangedInNode.item(0).getOwnerDocument().createElement(elementName); + } + childElement.setAttribute(FLAVOR_ID, "ANY.NONNULL"); + attributedToBeChangedInNode.item(0).appendChild(childElement); + } else if (attrMode.startsWith(Generator.LESS_THAN) + || attrMode.startsWith(Generator.GREATER_THAN) + || attrMode.equals(Generator.EQUAL_TO)) { + + String elementName = + templateNode.getAttributes().getNamedItem("addTagInValueSet").getNodeValue(); + NodeList el = attributedToBeChangedInNode.item(0).getChildNodes(); + Element childElement = null; + if (el.getLength() == 0) { + childElement = + attributedToBeChangedInNode.item(0).getOwnerDocument().createElement(elementName); + } else { + childElement = (Element) el; + if (childElement.hasChildNodes()) { + for (int j = childElement.getChildNodes().getLength(); j > 0; j--) { + Node ChildNode = childElement.getChildNodes().item(j - 1); + childElement.removeChild(ChildNode); + } + } + childElement = + attributedToBeChangedInNode.item(0).getOwnerDocument().createElement(elementName); + } + Node unitAttrib = attrNode.getAttributes().getNamedItem("unit"); + if (attrMode.equals(Generator.EQUAL_TO)) { + childElement.setAttribute( + "value", attrNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + childElement.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); + } + attributedToBeChangedInNode.item(0).appendChild(childElement); + } else if (attrMode.startsWith(Generator.LESS_THAN)) { + Element uncertainRangeNode = + childElement.getOwnerDocument().createElement("uncertainRange"); + if (attrMode.equals(Generator.LESS_THAN)) { + uncertainRangeNode.setAttribute("highClosed", "false"); + } + Element lowNode = childElement.getOwnerDocument().createElement(LOW); + lowNode.setAttribute(XSI_TYPE, "PQ"); + lowNode.setAttribute("nullFlavor", "NINF"); + + Element highNode = childElement.getOwnerDocument().createElement(HIGH); + highNode.setAttribute(XSI_TYPE, "PQ"); + highNode.setAttribute( + "value", attrNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + highNode.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); + } + uncertainRangeNode.appendChild(lowNode); + uncertainRangeNode.appendChild(highNode); + childElement.appendChild(uncertainRangeNode); + attributedToBeChangedInNode.item(0).appendChild(childElement); + } else if (attrMode.startsWith(Generator.GREATER_THAN)) { + Element uncertainRangeNode = + childElement.getOwnerDocument().createElement("uncertainRange"); + if (attrMode.equals(Generator.GREATER_THAN)) { + uncertainRangeNode.setAttribute("lowClosed", "false"); + } + Element lowNode = childElement.getOwnerDocument().createElement(LOW); + lowNode.setAttribute(XSI_TYPE, "PQ"); + lowNode.setAttribute( + "value", attrNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + lowNode.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); + } + Element highNode = childElement.getOwnerDocument().createElement(HIGH); + highNode.setAttribute(XSI_TYPE, "PQ"); + highNode.setAttribute("nullFlavor", "PINF"); + uncertainRangeNode.appendChild(lowNode); + uncertainRangeNode.appendChild(highNode); + childElement.appendChild(uncertainRangeNode); + attributedToBeChangedInNode.item(0).appendChild(childElement); + } + } + } else if (changeAttribute.equalsIgnoreCase(CODE)) { + String attrMode = (String) attrNode.getUserData(ATTRIBUTE_MODE); + if (CHECK_IF_PRESENT.equals(attrMode)) { + if (attributedToBeChangedInNode.item(0).hasAttributes()) { + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("valueSet"); + } + if (attributedToBeChangedInNode.item(0).hasChildNodes()) { + attributedToBeChangedInNode + .item(0) + .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); + } + Attr attribute = + attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("flavorId"); + attribute.setNodeValue("ANY.NONNULL"); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attribute); + } else if (VALUE_SET.equalsIgnoreCase(attrMode)) { + + String valueSetVersion = valueSetVersionStringValue(attrNode); + if (valueSetVersion.contains("mat/vsacmodel")) { + Attr valuesetVersionAttr = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createAttribute("valueSetVersion"); + valuesetVersionAttr.setNodeValue(valueSetVersion); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(valuesetVersionAttr); + } else { + if (attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("valueSetVersion") + != null) { + attributedToBeChangedInNode + .item(0) + .getAttributes() + .removeNamedItem("valueSetVersion"); + } + } + if (attributedToBeChangedInNode.item(0).hasAttributes()) { + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("flavorId"); + } + if (attributedToBeChangedInNode.item(0).hasChildNodes()) { + ((Element) attributedToBeChangedInNode.item(0)) + .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); + } + String attributeValueSetName = + attrNode.getAttributes().getNamedItem(NAME).getNodeValue(); + String attributeOID = attrNode.getAttributes().getNamedItem(OID).getNodeValue(); + String attributeTaxonomy = + attrNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); + Attr attribute = + attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("valueSet"); + attribute.setNodeValue(attributeOID); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attribute); + Element valueDisplayNameElem = + attributedToBeChangedInNode.item(0).getOwnerDocument().createElement(DISPLAY_NAME); + valueDisplayNameElem.setAttribute( + VALUE, + HQMFDataCriteriaGenerator.removeOccurrenceFromName(attributeValueSetName) + + " " + + attributeTaxonomy + + " Value Set"); + attributedToBeChangedInNode.item(0).appendChild(valueDisplayNameElem); + } + } + } + } + for (int i = 0; i < subTemplateNode.getChildNodes().getLength(); i++) { + Node childNode = subTemplateNode.getChildNodes().item(i); + Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); + XmlProcessor.clean(nodeToAttach); + checkIfOutBoundOcc(dataCriteriaElem, nodeToAttach); + } + } + + /** + * This method will look for attributes used in the subTree logic and then generate appropriate + * data criteria entries. + * + * @param qdmNode the qdm node + * @param dataCriteriaElem the data criteria elem + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + * @param isFunctionAttributeFlow - boolean function Attribute flow. + * @throws XPathExpressionException the x path expression exception + */ + private void createDataCriteriaForAttributes( + Node qdmNode, + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode, + boolean isFunctionAttributeFlow) + throws XPathExpressionException { + String attributeName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); + String attributeMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); + boolean checkForMode = false; + switch (attributeName.toLowerCase()) { + case NEGATION_RATIONALE: + if (!isFunctionAttributeFlow) { + generateNegationRationalEntries( + qdmNode, + dataCriteriaElem, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + attributeQDMNode); + } + break; + case START_DATETIME: + case STOP_DATETIME: + case SIGNED_DATETIME: + case RECORDED_DATETIME: + case ABATEMENT_DATETIME: + generateOrderTypeAttributes( + qdmNode, + dataCriteriaElem, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + attributeQDMNode); + break; + case ADMISSION_DATETIME: + case DISCHARGE_DATETIME: + case REMOVAL_DATETIME: + case ACTIVE_DATETIME: + case TIME: + case DATE: + case ONSET_DATETIME: + generateDateTimeAttributes( + qdmNode, + dataCriteriaElem, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + attributeQDMNode); + break; + case FACILITY_LOCATION_ARRIVAL_DATETIME: + case FACILITY_LOCATION_DEPARTURE_DATETIME: + generateFacilityLocationTypeAttributes( + qdmNode, + dataCriteriaElem, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + attributeQDMNode); + break; + case DOSE: + case LENGTH_OF_STAY: + generateDoseTypeAttributes( + qdmNode, + dataCriteriaElem, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + attributeQDMNode); + break; + case REFILLS: + generateRepeatNumber( + qdmNode, dataCriteriaXMLProcessor, dataCriteriaElem, attributeQDMNode, REPEAT_NUMBER); + break; + case DISCHARGE_STATUS: + generateDischargeStatus( + qdmNode, dataCriteriaXMLProcessor, dataCriteriaElem, attributeQDMNode); + break; + case INCISION_DATETIME: + generateIncisionDateTimeTypeAttributes( + qdmNode, + dataCriteriaElem, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + attributeQDMNode); + break; + case PRINCIPAL_DIAGNOSIS: + case DIAGNOSIS: + generatePrincipalAndDiagnosisAttributes( + qdmNode, + dataCriteriaElem, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + attributeQDMNode); + break; + default: + checkForMode = true; + break; + } + if (checkForMode) { + if (VALUE_SET.equals(attributeMode) + || CHECK_IF_PRESENT.equals(attributeMode) + || attributeMode.startsWith(LESS_THAN) + || attributeMode.startsWith(GREATER_THAN) + || EQUAL_TO.equals(attributeMode)) { + // handle "Value Set", "Check If Present" and comparison(less than, greater + // than, equals) mode + generateOtherAttributes( + qdmNode, + dataCriteriaElem, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + attributeQDMNode); + } + } + } + + /** + * Generate dose type attributes. + * + * @param qdmNode the qdm node + * @param dataCriteriaElem the data criteria elem + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + * @throws XPathExpressionException the x path expression exception + */ + protected void generateDoseTypeAttributes( + Node qdmNode, + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode) + throws XPathExpressionException { + + String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); + String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); + Node attrOID = attributeQDMNode.getAttributes().getNamedItem(OID); + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); + Node templateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), + "/templates/AttrTemplate[text()='" + attrName.toLowerCase() + "']"); + Node targetNode = templateNode.getAttributes().getNamedItem("target"); + Element targetQuantityTag = null; + if (targetNode != null) { + targetQuantityTag = + dataCriteriaElem.getOwnerDocument().createElement(targetNode.getNodeValue()); + } + Node unitAttrib = attributeQDMNode.getAttributes().getNamedItem("unit"); + if (CHECK_IF_PRESENT.equals(attrMode)) { + targetQuantityTag.setAttribute(FLAVOR_ID, "ANY.NONNULL"); + } else if (VALUE_SET.equals(attrMode)) { + targetQuantityTag.setAttribute(NULL_FLAVOR, "UNK"); + Element translationNode = dataCriteriaElem.getOwnerDocument().createElement(TRANSLATION); + translationNode.setAttribute("valueSet", attrOID.getNodeValue()); + + String valueSetVersion = valueSetVersionStringValue(attributeQDMNode); + if (valueSetVersion.contains("mat/vsacmodel")) { + translationNode.setAttribute("valueSetVersion", valueSetVersion); + } else { + if (translationNode.getAttributes().getNamedItem("valueSetVersion") != null) { + translationNode.getAttributes().removeNamedItem("valueSetVersion"); + } + } + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + String newQdmName = + HQMFDataCriteriaGenerator.removeOccurrenceFromName( + attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue()); + displayNameElem.setAttribute( + VALUE, + newQdmName + + " " + + attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue() + + " Value Set"); + translationNode.appendChild(displayNameElem); + targetQuantityTag.appendChild(translationNode); + // } + } else if (attrMode.startsWith(Generator.LESS_THAN) + || attrMode.startsWith(Generator.GREATER_THAN) + || attrMode.equals(Generator.EQUAL_TO)) { + if (attrMode.equals(Generator.EQUAL_TO)) { + targetQuantityTag.setAttribute( + "value", + attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + targetQuantityTag.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); + } + } else if (attrMode.startsWith(Generator.LESS_THAN)) { + Element uncertainRangeNode = + dataCriteriaElem.getOwnerDocument().createElement("uncertainRange"); + if (attrMode.equals(Generator.LESS_THAN)) { + uncertainRangeNode.setAttribute("highClosed", "false"); + } + Element lowNode = dataCriteriaElem.getOwnerDocument().createElement(LOW); + lowNode.setAttribute("xsi:type", "PQ"); + lowNode.setAttribute("nullFlavor", "NINF"); + Element highNode = dataCriteriaElem.getOwnerDocument().createElement(HIGH); + highNode.setAttribute("xsi:type", "PQ"); + highNode.setAttribute( + "value", + attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + highNode.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); + } + + uncertainRangeNode.appendChild(lowNode); + uncertainRangeNode.appendChild(highNode); + targetQuantityTag.appendChild(uncertainRangeNode); + + } else if (attrMode.startsWith(Generator.GREATER_THAN)) { + Element uncertainRangeNode = + dataCriteriaElem.getOwnerDocument().createElement("uncertainRange"); + if (attrMode.equals(Generator.GREATER_THAN)) { + uncertainRangeNode.setAttribute("lowClosed", "false"); + } + Element lowNode = dataCriteriaElem.getOwnerDocument().createElement(LOW); + lowNode.setAttribute("xsi:type", "PQ"); + lowNode.setAttribute( + "value", + attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + lowNode.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); + } + Element highNode = dataCriteriaElem.getOwnerDocument().createElement(HIGH); + highNode.setAttribute("xsi:type", "PQ"); + highNode.setAttribute("nullFlavor", "PINF"); + uncertainRangeNode.appendChild(lowNode); + uncertainRangeNode.appendChild(highNode); + targetQuantityTag.appendChild(uncertainRangeNode); + } + } + String insertAfterNodeName = + templateNode.getAttributes().getNamedItem("insertAfterNode").getNodeValue(); + if (insertAfterNodeName != null) { + if (dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0) != null) { + Node outBoundElement = + dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0).getNextSibling(); + if (outBoundElement != null) { + outBoundElement.getParentNode().insertBefore(targetQuantityTag, outBoundElement); + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetQuantityTag); + } + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetQuantityTag); + } + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetQuantityTag); + } + } + + /** + * Generate facility location type attributes. + * + * @param qdmNode the qdm node + * @param dataCriteriaElem the data criteria elem + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + * @throws XPathExpressionException the x path expression exception + */ + protected void generateFacilityLocationTypeAttributes( + Node qdmNode, + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode) + throws XPathExpressionException { + String attributeName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); + Node templateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), + "/templates/AttrTemplate[text()='" + attributeName.toLowerCase() + "']"); + if (templateNode == null) { + return; + } + if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { + appendSubTemplateInFacilityAttribute( + templateNode, + dataCriteriaXMLProcessor, + templateXMLProcessor, + dataCriteriaElem, + attributeQDMNode); + } + generateDateTimeAttributes( + qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, attributeQDMNode); + } + + /** + * Generate incision date time type attributes. + * + * @param qdmNode the qdm node + * @param dataCriteriaElem the data criteria elem + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + * @throws XPathExpressionException the x path expression exception + */ + protected void generateIncisionDateTimeTypeAttributes( + Node qdmNode, + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode) + throws XPathExpressionException { + String attributeName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); + Node templateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), + "/templates/AttrTemplate[text()='" + attributeName.toLowerCase() + "']"); + if (templateNode == null) { + return; + } + if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { + appendSubTemplateNode( + templateNode, + dataCriteriaXMLProcessor, + templateXMLProcessor, + dataCriteriaElem, + qdmNode, + attributeQDMNode); + } + generateDateTimeAttributes( + qdmNode, dataCriteriaElem, dataCriteriaXMLProcessor, simpleXmlprocessor, attributeQDMNode); + } + + /** + * Generate order type attributes. + * + * @param qdmNode the qdm node + * @param dataCriteriaElem the data criteria elem + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + * @throws XPathExpressionException the x path expression exception + */ + protected void generateOrderTypeAttributes( + Node qdmNode, + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode) + throws XPathExpressionException { + String qdmName = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); + Node templateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), + "/templates/template[text()='" + qdmName.toLowerCase() + "']"); + if (templateNode == null) { + return; + } + if ((templateNode.getAttributes().getNamedItem("includeOtherSubTemplate") != null) + || attrName.equalsIgnoreCase(SIGNED_DATETIME) + || attrName.equalsIgnoreCase(RECORDED_DATETIME)) { + appendSubTemplateWithOrderAttribute( + templateNode, + dataCriteriaXMLProcessor, + templateXMLProcessor, + dataCriteriaElem, + qdmNode, + attributeQDMNode); + } else { + generateDateTimeAttributes( + qdmNode, + dataCriteriaElem, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + attributeQDMNode); + } + } + + /** + * Generate negation rational entries. + * + * @param qdmNode the qdm node + * @param dataCriteriaElem the data criteria elem + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + * @throws XPathExpressionException the x path expression exception + */ + private void generateNegationRationalEntries( + Node qdmNode, + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode) + throws XPathExpressionException { + if (attributeQDMNode.getAttributes().getLength() > 0) { + + String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); + String attribUUID = (String) attributeQDMNode.getUserData(ATTRIBUTE_UUID); + + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); + Node templateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), + "/templates/AttrTemplate[text()='" + attrName + "']"); + String attributeValueSetName = + attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue(); + String attributeOID = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); + String attributeTaxonomy = + attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); + dataCriteriaElem.setAttribute("actionNegationInd", "true"); + + Element outboundRelationshipElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); + outboundRelationshipElem.setAttribute( + TYPE_CODE, templateNode.getAttributes().getNamedItem(TYPE).getNodeValue()); + + Element observationCriteriaElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(OBSERVATION_CRITERIA); + observationCriteriaElem.setAttribute( + CLASS_CODE, templateNode.getAttributes().getNamedItem(CLASS).getNodeValue()); + observationCriteriaElem.setAttribute( + MOOD_CODE, templateNode.getAttributes().getNamedItem(MOOD).getNodeValue()); + + outboundRelationshipElem.appendChild(observationCriteriaElem); + + Element templateId = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TEMPLATE_ID); + observationCriteriaElem.appendChild(templateId); + + Element itemChild = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); + itemChild.setAttribute(ROOT, templateNode.getAttributes().getNamedItem(OID).getNodeValue()); + itemChild.setAttribute("extension", VERSION_4_1_2_ID); + templateId.appendChild(itemChild); + + Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); + idElem.setAttribute(ROOT, attribUUID); + idElem.setAttribute("extension", StringUtils.deleteWhitespace(attributeValueSetName)); + observationCriteriaElem.appendChild(idElem); + + Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + codeElem.setAttribute(CODE, templateNode.getAttributes().getNamedItem(CODE).getNodeValue()); + codeElem.setAttribute( + CODE_SYSTEM, templateNode.getAttributes().getNamedItem(CODE_SYSTEM).getNodeValue()); + + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + displayNameElem.setAttribute(VALUE, "Reason"); + + observationCriteriaElem.appendChild(codeElem); + codeElem.appendChild(displayNameElem); + + Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, "Reason"); + observationCriteriaElem.appendChild(titleElem); + + Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(VALUE); + valueElem.setAttribute( + XSI_TYPE, templateNode.getAttributes().getNamedItem("valueType").getNodeValue()); + valueElem.setAttribute("valueSet", attributeOID); + addValueSetVersion(attributeQDMNode, valueElem); + Element valueDisplayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + valueDisplayNameElem.setAttribute( + VALUE, + HQMFDataCriteriaGenerator.removeOccurrenceFromName(attributeValueSetName) + + " " + + attributeTaxonomy + + " Value Set"); + + valueElem.appendChild(valueDisplayNameElem); + observationCriteriaElem.appendChild(valueElem); + + dataCriteriaElem.appendChild(outboundRelationshipElem); + } + } + + /** + * Method is used to generate HQMF logic for Principle Diagnosis and Diagnosis attributes. + * + * @param qdmNode + * @param dataCriteriaElem + * @param dataCriteriaXMLProcessor + * @param simpleXmlprocessor + * @param attributeQDMNode + * @throws XPathExpressionException + */ + protected void generatePrincipalAndDiagnosisAttributes( + Node qdmNode, + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode) + throws XPathExpressionException { + String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); + String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); + + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); + Node templateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), + "/templates/AttrTemplate[text()='" + attrName.toLowerCase() + "']"); + if (templateNode == null) { + return; + } else { + Element outboundRelationshipElem = null; + Element actCriteriaElem = null; + outboundRelationshipElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); + outboundRelationshipElem.setAttribute( + TYPE_CODE, templateNode.getAttributes().getNamedItem(TYPE).getNodeValue()); + actCriteriaElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("actCriteria"); + actCriteriaElem.setAttribute( + CLASS_CODE, templateNode.getAttributes().getNamedItem(CLASS).getNodeValue()); + actCriteriaElem.setAttribute( + MOOD_CODE, templateNode.getAttributes().getNamedItem(MOOD).getNodeValue()); + Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); + idElem.setAttribute(ROOT, UUIDUtilClient.uuid()); + idElem.setAttribute("extension", UUIDUtilClient.uuid()); + actCriteriaElem.appendChild(idElem); + Element codeElem = createCodeForDatatype(templateNode, dataCriteriaXMLProcessor); + actCriteriaElem.appendChild(codeElem); + Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, "Encounter " + attrName); + actCriteriaElem.appendChild(titleElem); + + outboundRelationshipElem.appendChild(actCriteriaElem); + + String subTemplateName = + templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); + Node subTemplateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), "/templates/subtemplates/" + subTemplateName); + NodeList subTemplateNodeChilds = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "/child::node()"); + + if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { + String[] attributeToBeModified = + subTemplateNode + .getAttributes() + .getNamedItem("changeAttribute") + .getNodeValue() + .split(","); + for (String changeAttribute : attributeToBeModified) { + NodeList attributedToBeChangedInNode = null; + attributedToBeChangedInNode = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); + if (changeAttribute.equalsIgnoreCase(ID)) { + String rootId = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("root") + .setNodeValue(rootId); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("extension") + .setNodeValue(UUIDUtilClient.uuid()); + } else if (changeAttribute.equalsIgnoreCase(VALUE)) { + if (CHECK_IF_PRESENT.equals(attrMode)) { + if (attributedToBeChangedInNode.item(0).hasAttributes()) { + if (attributedToBeChangedInNode.item(0).hasAttributes()) { + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("valueSet"); + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("flavorId"); + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("xsi:type"); + } + } + if (attributedToBeChangedInNode.item(0).hasChildNodes()) { + attributedToBeChangedInNode + .item(0) + .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); + } + Attr attribute = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createAttribute("flavorId"); + attribute.setNodeValue("ANY.NONNULL"); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attribute); + + Attr attributeXSIType = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createAttribute("xsi:type"); + attributeXSIType.setNodeValue("ANY"); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attributeXSIType); + } else if (VALUE_SET.equalsIgnoreCase(attrMode)) { + + String valueSetVersion = valueSetVersionStringValue(attributeQDMNode); + if (valueSetVersion.contains("mat/vsacmodel")) { + Attr valuesetVersionAttr = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createAttribute("valueSetVersion"); + valuesetVersionAttr.setNodeValue(valueSetVersion); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .setNamedItem(valuesetVersionAttr); + } else { + if (attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("valueSetVersion") + != null) { + attributedToBeChangedInNode + .item(0) + .getAttributes() + .removeNamedItem("valueSetVersion"); + } + } + if (attributedToBeChangedInNode.item(0).hasAttributes()) { + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("valueSet"); + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("flavorId"); + ((Element) attributedToBeChangedInNode.item(0)).removeAttribute("xsi:type"); + } + if (attributedToBeChangedInNode.item(0).hasChildNodes()) { + ((Element) attributedToBeChangedInNode.item(0)) + .removeChild(attributedToBeChangedInNode.item(0).getFirstChild()); + } + String attributeValueSetName = + attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue(); + String attributeOID = + attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); + String attributeTaxonomy = + attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); + Attr attribute = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createAttribute("valueSet"); + attribute.setNodeValue(attributeOID); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attribute); + Attr attributeXSIType = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createAttribute("xsi:type"); + attributeXSIType.setNodeValue("CD"); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attributeXSIType); + Element valueDisplayNameElem = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createElement(DISPLAY_NAME); + valueDisplayNameElem.setAttribute( + VALUE, + HQMFDataCriteriaGenerator.removeOccurrenceFromName(attributeValueSetName) + + " " + + attributeTaxonomy + + " Value Set"); + attributedToBeChangedInNode.item(0).appendChild(valueDisplayNameElem); + } + } + } + } + for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { + Node childNode = subTemplateNodeChilds.item(i); + Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); + XmlProcessor.clean(nodeToAttach); + actCriteriaElem.appendChild(nodeToAttach); + } + + dataCriteriaElem.appendChild(outboundRelationshipElem); + } + } + + /** + * Generate other attribute entries. + * + * @param qdmNode the qdm node + * @param dataCriteriaElem the data criteria elem + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + * @throws XPathExpressionException the x path expression exception + */ + protected void generateOtherAttributes( + Node qdmNode, + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode) + throws XPathExpressionException { + + String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); + String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); + String attribUUID = (String) attributeQDMNode.getUserData(ATTRIBUTE_UUID); + String qdmName = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + boolean isResult = "result".equalsIgnoreCase(attrName); + + boolean isResultNotOutBound = + isResult + && ("Diagnostic Study, Performed".equalsIgnoreCase(qdmName) + || "Laboratory Test, Performed".equalsIgnoreCase(qdmName) + || "Functional Status, Performed".equalsIgnoreCase(qdmName) + || "Risk Category Assessment".equalsIgnoreCase(qdmName)); + + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(4.3); + Node templateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), + "/templates/AttrTemplate[text()='" + attrName.toLowerCase() + "']"); + boolean isRadiation = false; + if (templateNode == null) { + templateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), + "/templates/AttrTemplate[text()='" + + attrName.toLowerCase() + + "-" + + attrMode.toLowerCase() + + "']"); + if (templateNode == null) { + return; + } else { + if (ANATOMICAL_LOCATION_SITE.equalsIgnoreCase(attrName) + || ORDINALITY.equalsIgnoreCase(attrName) + || ROUTE.equalsIgnoreCase(attrName) + || "method".equalsIgnoreCase(attrName) + || ANATOMICAL_APPROACH_SITE.equalsIgnoreCase(attrName)) { + addTargetSiteOrPriorityCodeOrRouteCodeElement( + dataCriteriaElem, dataCriteriaXMLProcessor, attributeQDMNode, templateNode); + } else if (LATERALITY.equalsIgnoreCase(attrName)) { + appendSubTemplateNode( + templateNode, + dataCriteriaXMLProcessor, + templateXMLProcessor, + dataCriteriaElem, + qdmNode, + attributeQDMNode); + } + return; + } + } + // flag to add statusCode for Radiation Dosage and Radiation Duration attributes + if (templateNode.getAttributes().getNamedItem("isRadiation") != null) { + isRadiation = templateNode.getAttributes().getNamedItem("isRadiation").getNodeValue() != null; + } + if (attrName.equalsIgnoreCase(FACILITY_LOCATION)) { + if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { + appendSubTemplateInFacilityAttribute( + templateNode, + dataCriteriaXMLProcessor, + templateXMLProcessor, + dataCriteriaElem, + attributeQDMNode); + } + return; + } else if (attrName.contains(REFERENCE) || attrName.equalsIgnoreCase(RELATIONSHIP)) { + if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { + appendSubTemplateAndAddValueTagBasedOnMode( + templateNode, + dataCriteriaXMLProcessor, + templateXMLProcessor, + dataCriteriaElem, + attributeQDMNode); + } + return; + } + Element outboundRelationshipElem = null; + Element observationCriteriaElem = null; + if (!isResultNotOutBound) { // result attribute with specific Datatypes does'nt add + // OutBoundRelationShip + outboundRelationshipElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); + outboundRelationshipElem.setAttribute( + TYPE_CODE, templateNode.getAttributes().getNamedItem(TYPE).getNodeValue()); + + Node invAttribNode = templateNode.getAttributes().getNamedItem("inv"); + if (invAttribNode != null) { + outboundRelationshipElem.setAttribute("inversionInd", invAttribNode.getNodeValue()); + } + + observationCriteriaElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(OBSERVATION_CRITERIA); + observationCriteriaElem.setAttribute( + CLASS_CODE, templateNode.getAttributes().getNamedItem(CLASS).getNodeValue()); + observationCriteriaElem.setAttribute( + MOOD_CODE, templateNode.getAttributes().getNamedItem(MOOD).getNodeValue()); + + outboundRelationshipElem.appendChild(observationCriteriaElem); + + if ((templateNode.getAttributes().getNamedItem(OID) != null) + && !attrName.equalsIgnoreCase(ONSET_AGE)) { + Element templateId = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TEMPLATE_ID); + observationCriteriaElem.appendChild(templateId); + + Element itemChild = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); + itemChild.setAttribute(ROOT, templateNode.getAttributes().getNamedItem(OID).getNodeValue()); + if (templateNode.getAttributes().getNamedItem("addExtensionInTemplate") == null) { + itemChild.setAttribute("extension", VERSION_4_1_2_ID); + } + templateId.appendChild(itemChild); + } + + Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); + idElem.setAttribute(ROOT, attribUUID); + idElem.setAttribute("extension", StringUtils.deleteWhitespace(attrName)); + observationCriteriaElem.appendChild(idElem); + Element codeElem = createCodeForDatatype(templateNode, dataCriteriaXMLProcessor); + if ((isRadiation || isResult) && (codeElem != null)) { + observationCriteriaElem.appendChild(codeElem); + } else { + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + if (templateNode.getAttributes().getNamedItem("displayNameValue") != null) { + displayNameElem.setAttribute( + VALUE, templateNode.getAttributes().getNamedItem("displayNameValue").getNodeValue()); + } else { + displayNameElem.setAttribute(VALUE, attrName); + } + if (codeElem != null) { + observationCriteriaElem.appendChild(codeElem); + codeElem.appendChild(displayNameElem); + } + } + if (!isRadiation) { + if (!attrName.equalsIgnoreCase(ONSET_AGE)) { + Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, attrName); + observationCriteriaElem.appendChild(titleElem); + } else { + Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, "Age"); + observationCriteriaElem.appendChild(titleElem); + } + } + if (isRadiation) { // statusCode is added for Radiation Duration and Dosage + Element statusCodeElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(STATUS_CODE); + if (templateNode.getAttributes().getNamedItem("status") != null) { + statusCodeElem.setAttribute( + CODE, templateNode.getAttributes().getNamedItem("status").getNodeValue()); + } + observationCriteriaElem.appendChild(statusCodeElem); + } + } + if (attrName.equalsIgnoreCase(ONSET_AGE)) { + generateRepeatNumber( + templateNode, dataCriteriaXMLProcessor, observationCriteriaElem, attributeQDMNode, VALUE); + dataCriteriaElem.appendChild(outboundRelationshipElem); + } else { + Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(VALUE); + if (VALUE_SET.equals(attrMode)) { + checkIfSelectedModeIsValueSet( + dataCriteriaXMLProcessor, attributeQDMNode, templateNode, valueElem); + } else if (CHECK_IF_PRESENT.equalsIgnoreCase(attrMode)) { + checkIfSelectedModeIsPresent( + dataCriteriaXMLProcessor, attributeQDMNode, templateNode, valueElem); + } else if (EQUAL_TO.equals(attrMode) + || attrMode.startsWith(LESS_THAN) + || attrMode.startsWith(GREATER_THAN)) { + checkIfSelectedModeIsArthimaticExpr( + dataCriteriaXMLProcessor, attributeQDMNode, templateNode, valueElem); + } + if ((outboundRelationshipElem != null) && (observationCriteriaElem != null)) { + observationCriteriaElem.appendChild(valueElem); + dataCriteriaElem.appendChild(outboundRelationshipElem); + } else { + NodeList outboundRelationshipList = + dataCriteriaElem.getElementsByTagName("outboundRelationship"); + if ((outboundRelationshipList != null) && (outboundRelationshipList.getLength() > 0)) { + Node outboundRelationshipNode = outboundRelationshipList.item(0); + dataCriteriaElem.insertBefore(valueElem, outboundRelationshipNode); + } else { + dataCriteriaElem.appendChild(valueElem); + } + } + } + } + + /** + * Refills Attribute tags. + * + * @param templateNode the template node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param dataCriteriaElem the data criteria elem + * @param attributeQDMNode the attribute qdm node + */ + protected void generateRepeatNumber( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + Element dataCriteriaElem, + Node attributeQDMNode, + String elementNameToCreate) { + String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); + Element repeatNumberElement = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(elementNameToCreate); + Node unitAttrib = attributeQDMNode.getAttributes().getNamedItem("unit"); + + if (CHECK_IF_PRESENT.equalsIgnoreCase(attrMode)) { + if (elementNameToCreate.equalsIgnoreCase(VALUE)) { + repeatNumberElement.setAttribute("xsi:type", "ANY"); + } + repeatNumberElement.setAttribute(FLAVOR_ID, "ANY.NONNULL"); + } else if (EQUAL_TO.equals(attrMode) + || attrMode.startsWith(LESS_THAN) + || attrMode.startsWith(GREATER_THAN)) { + if (elementNameToCreate.equalsIgnoreCase(VALUE)) { + repeatNumberElement.setAttribute("xsi:type", "IVL_PQ"); + } + if (EQUAL_TO.equals(attrMode)) { + Element lowElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); + lowElem.setAttribute( + VALUE, attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); + highElem.setAttribute( + VALUE, attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + lowElem.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); + highElem.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); + } + repeatNumberElement.appendChild(lowElem); + repeatNumberElement.appendChild(highElem); + } else if (attrMode.startsWith(GREATER_THAN)) { + if (attrMode.equals(GREATER_THAN)) { + repeatNumberElement.setAttribute("lowClosed", "false"); + } + Element lowElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); + lowElem.setAttribute( + VALUE, attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + repeatNumberElement.appendChild(lowElem); + Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); + highElem.setAttribute(NULL_FLAVOR, "PINF"); + if (unitAttrib != null) { + lowElem.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); + } + + repeatNumberElement.appendChild(highElem); + } else if (attrMode.startsWith(LESS_THAN)) { + if (attrMode.equals(LESS_THAN)) { + repeatNumberElement.setAttribute("highClosed", "false"); + } + Element lowElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); + lowElem.setAttribute(NULL_FLAVOR, "NINF"); + repeatNumberElement.appendChild(lowElem); + Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); + highElem.setAttribute( + VALUE, attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + highElem.setAttribute("unit", getUnitString(unitAttrib.getNodeValue())); + } + repeatNumberElement.appendChild(highElem); + } + } + + if ((dataCriteriaElem.getElementsByTagName("statusCode").item(0) != null)) { + Node outBoundElement = dataCriteriaElem.getElementsByTagName("statusCode").item(0); + if (outBoundElement != null) { + outBoundElement.getParentNode().insertBefore(repeatNumberElement, outBoundElement); + } else { + checkIfOutBoundOcc(dataCriteriaElem, repeatNumberElement); + } + } else { + checkIfOutBoundOcc(dataCriteriaElem, repeatNumberElement); + } + } + + /** + * Discharge Status Attribute tags. + * + * @param templateNode the template node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param dataCriteriaElem the data criteria elem + * @param attributeQDMNode the attribute qdm node + */ + protected void generateDischargeStatus( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + Element dataCriteriaElem, + Node attributeQDMNode) { + String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); + Element dischargeDispositionElement = + dataCriteriaXMLProcessor.getOriginalDoc().createElement("dischargeDispositionCode"); + if (CHECK_IF_PRESENT.equalsIgnoreCase(attrMode)) { + dischargeDispositionElement.setAttribute(FLAVOR_ID, "ANY.NONNULL"); + checkIfOutBoundOcc(dataCriteriaElem, dischargeDispositionElement); + } else if (VALUE_SET.equalsIgnoreCase(attrMode)) { + String attributeValueSetName = + attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue(); + + String attributeOID = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); + String attributeTaxonomy = + attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); + dischargeDispositionElement.setAttribute("valueSet", attributeOID); + addValueSetVersion(attributeQDMNode, dischargeDispositionElement); + Element valueDisplayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + valueDisplayNameElem.setAttribute( + VALUE, + HQMFDataCriteriaGenerator.removeOccurrenceFromName(attributeValueSetName) + + " " + + attributeTaxonomy + + " Value Set"); + dischargeDispositionElement.appendChild(valueDisplayNameElem); + checkIfOutBoundOcc(dataCriteriaElem, dischargeDispositionElement); + } + } + + /** + * Check if selected mode is value set. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param attributeQDMNode the attribute qdm node + * @param templateNode the template node + * @param valueElem the value elem + * @return the element + */ + protected Element checkIfSelectedModeIsValueSet( + XmlProcessor dataCriteriaXMLProcessor, + Node attributeQDMNode, + Node templateNode, + Element valueElem) { + String attributeValueSetName = + attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue(); + String attributeOID = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); + String attributeTaxonomy = + attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); + if (templateNode.getAttributes().getNamedItem("valueType") != null) { + valueElem.setAttribute( + XSI_TYPE, templateNode.getAttributes().getNamedItem("valueType").getNodeValue()); + } + + valueElem.setAttribute("valueSet", attributeOID); + addValueSetVersion(attributeQDMNode, valueElem); + Element valueDisplayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + valueDisplayNameElem.setAttribute( + VALUE, + HQMFDataCriteriaGenerator.removeOccurrenceFromName(attributeValueSetName) + + " " + + attributeTaxonomy + + " Value Set"); + valueElem.appendChild(valueDisplayNameElem); + + return valueElem; + } + + /** + * Check if selected mode is present. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param attributeQDMNode the attribute qdm node + * @param templateNode the template node + * @param valueElem the value elem + * @return the element + */ + protected Element checkIfSelectedModeIsPresent( + XmlProcessor dataCriteriaXMLProcessor, + Node attributeQDMNode, + Node templateNode, + Element valueElem) { + valueElem.setAttribute(XSI_TYPE, "ANY"); + valueElem.setAttribute(FLAVOR_ID, "ANY.NONNULL"); + return valueElem; + } + + /** + * Check if selected mode is arthimatic expr. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param attributeQDMNode the attribute qdm node + * @param templateNode the template node + * @param valueElem the value elem + * @return the element + */ + private Element checkIfSelectedModeIsArthimaticExpr( + XmlProcessor dataCriteriaXMLProcessor, + Node attributeQDMNode, + Node templateNode, + Element valueElem) { + String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); + String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); + String nodeName = attributeQDMNode.getNodeName(); + boolean isRadiation = false; + boolean isTargetOutCome = false; + boolean isCumMedicationDuration = CUMULATIVE_MEDICATION_DURATION.equalsIgnoreCase(attrName); + boolean isFrequency = FREQUENCY.equalsIgnoreCase(attrName); + boolean isResult = "result".equalsIgnoreCase(attrName); + if (templateNode.getAttributes().getNamedItem("isRadiation") != null) { + isRadiation = templateNode.getAttributes().getNamedItem("isRadiation").getNodeValue() != null; + } + if (templateNode.getAttributes().getNamedItem("isTargetOutcome") != null) { + isTargetOutCome = + templateNode.getAttributes().getNamedItem("isTargetOutcome").getNodeValue() != null; + } + if (nodeName.equals("attribute")) { + valueElem.setAttribute(XSI_TYPE, "IVL_PQ"); + Node unitAttrib = attributeQDMNode.getAttributes().getNamedItem("unit"); + if (EQUAL_TO.equals(attrMode)) { + if (isRadiation) { // for radiation dosage and radiation duration + valueElem.getAttributes().getNamedItem(XSI_TYPE).setNodeValue("PQ"); + valueElem.setAttribute( + VALUE, + attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + String unitString = getUnitString(unitAttrib.getNodeValue()); + valueElem.setAttribute("unit", unitString); + } + } else { // for attributes other than radiation duration and radiation dosage + Element lowElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); + lowElem.setAttribute( + VALUE, + attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + + Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); + highElem.setAttribute( + VALUE, + attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + + if (unitAttrib != null) { + String unitString = getUnitString(unitAttrib.getNodeValue()); + lowElem.setAttribute("unit", unitString); + highElem.setAttribute("unit", unitString); + } + if (isResult) { + lowElem.setAttribute(XSI_TYPE, "PQ"); + highElem.setAttribute(XSI_TYPE, "PQ"); + } + valueElem.appendChild(lowElem); + valueElem.appendChild(highElem); + } + + } else if (attrMode.startsWith(GREATER_THAN)) { + if (attrMode.equals(GREATER_THAN)) { + valueElem.setAttribute("lowClosed", "false"); + } + Element lowElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); + if (isResult) { + lowElem.setAttribute(XSI_TYPE, "PQ"); + } + lowElem.setAttribute( + VALUE, attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + String unitString = getUnitString(unitAttrib.getNodeValue()); + lowElem.setAttribute("unit", unitString); + } + valueElem.appendChild(lowElem); + if (isRadiation || isResult || isTargetOutCome || isCumMedicationDuration || isFrequency) { + Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); + highElem.setAttribute(NULL_FLAVOR, "PINF"); + valueElem.appendChild(highElem); + } + } else if (attrMode.startsWith(LESS_THAN)) { + if (attrMode.equals(LESS_THAN)) { + valueElem.setAttribute("highClosed", "false"); + } + if (isRadiation || isResult || isTargetOutCome || isCumMedicationDuration || isFrequency) { + Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(LOW); + highElem.setAttribute(NULL_FLAVOR, "NINF"); + valueElem.appendChild(highElem); + } + Element highElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(HIGH); + if (isResult) { + highElem.setAttribute(XSI_TYPE, "PQ"); + } + highElem.setAttribute( + VALUE, attributeQDMNode.getAttributes().getNamedItem("comparisonValue").getNodeValue()); + if (unitAttrib != null) { + String unitString = getUnitString(unitAttrib.getNodeValue()); + highElem.setAttribute("unit", unitString); + } + valueElem.appendChild(highElem); + } + } + + return valueElem; + } + + /** + * Adds the target site or priority code or route code element. + * + * @param dataCriteriaElem the data criteria elem + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param attributeQDMNode the attribute qdm node + * @param templateNode the template node + */ + private void addTargetSiteOrPriorityCodeOrRouteCodeElement( + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + Node attributeQDMNode, + Node templateNode) { + String targetElementName = templateNode.getAttributes().getNamedItem("target").getNodeValue(); + Element targetSiteCodeElement = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(targetElementName); + String insertBeforeNodeName = null; + String insertAfterNodeName = null; + if (templateNode.getAttributes().getNamedItem("insertBeforeNode") != null) { + insertBeforeNodeName = + templateNode.getAttributes().getNamedItem("insertBeforeNode").getNodeValue(); + } else if (templateNode.getAttributes().getNamedItem("insertAfterNode") != null) { + insertAfterNodeName = + templateNode.getAttributes().getNamedItem("insertAfterNode").getNodeValue(); + } + if (templateNode.getAttributes().getNamedItem("childTarget") != null) { + String qdmOidValue = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); + // .getNodeValue(); + Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); + valueElem.setAttribute("valueSet", qdmOidValue); + addValueSetVersion(attributeQDMNode, valueElem); + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + String newQdmName = + HQMFDataCriteriaGenerator.removeOccurrenceFromName( + attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue()); + displayNameElem.setAttribute( + VALUE, + newQdmName + + " " + + attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue() + + " Value Set"); + valueElem.appendChild(displayNameElem); + targetSiteCodeElement.appendChild(valueElem); + if ((insertBeforeNodeName != null) + && (dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0) != null)) { + Node outBoundElement = dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0); + if (outBoundElement != null) { + outBoundElement.getParentNode().insertBefore(targetSiteCodeElement, outBoundElement); + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); + } + } else if ((insertAfterNodeName != null) + && (dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0) != null)) { + Node outBoundElement = + dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0).getNextSibling(); + if (outBoundElement != null) { + outBoundElement.getParentNode().insertBefore(targetSiteCodeElement, outBoundElement); + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); + } + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); + } + } else if (templateNode.getAttributes().getNamedItem(FLAVOR_ID) != null) { + String flavorIdValue = templateNode.getAttributes().getNamedItem(FLAVOR_ID).getNodeValue(); + targetSiteCodeElement.setAttribute(FLAVOR_ID, flavorIdValue); + if ((insertBeforeNodeName != null) + && (dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0) != null)) { + Node outBoundElement = dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0); + if (outBoundElement != null) { + outBoundElement.getParentNode().insertBefore(targetSiteCodeElement, outBoundElement); + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); + } + } else if ((insertAfterNodeName != null) + && (dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0) != null)) { + Node outBoundElement = + dataCriteriaElem.getElementsByTagName(insertAfterNodeName).item(0).getNextSibling(); + if (outBoundElement != null) { + outBoundElement.getParentNode().insertBefore(targetSiteCodeElement, outBoundElement); + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); + } + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); + } + } else if (templateNode.getAttributes().getNamedItem("addValueSet") != null) { + String qdmOidValue = attributeQDMNode.getAttributes().getNamedItem(OID).getNodeValue(); + targetSiteCodeElement.setAttribute("valueSet", qdmOidValue); + addValueSetVersion(attributeQDMNode, targetSiteCodeElement); + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + String newQdmName = + HQMFDataCriteriaGenerator.removeOccurrenceFromName( + attributeQDMNode.getAttributes().getNamedItem(NAME).getNodeValue()); + displayNameElem.setAttribute( + VALUE, + newQdmName + + " " + + attributeQDMNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue() + + " Value Set"); + targetSiteCodeElement.appendChild(displayNameElem); + if ((insertBeforeNodeName != null) + && (dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0) != null)) { + Node outBoundElement = dataCriteriaElem.getElementsByTagName(insertBeforeNodeName).item(0); + if (outBoundElement != null) { + outBoundElement.getParentNode().insertBefore(targetSiteCodeElement, outBoundElement); + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); + } + } else { + checkIfOutBoundOcc(dataCriteriaElem, targetSiteCodeElement); + } + } + } + + /** + * Method to generate HQMF XML for date time attributes. + * + * @param childNode the child node + * @param dataCriteriaElem the data criteria elem + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param attributeQDMNode the attribute qdm node + */ + protected void generateDateTimeAttributes( + Node childNode, + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node attributeQDMNode) { + + Element effectiveTimeNode = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(EFFECTIVE_TIME); + effectiveTimeNode.setAttribute(XSI_TYPE, "IVL_TS"); + generateDateTimeAttributesTag( + effectiveTimeNode, attributeQDMNode, dataCriteriaElem, dataCriteriaXMLProcessor, false); + } + + /** + * Generate date time attributes tag. + * + * @param dateTimeNode the effective time node + * @param attributeQDMNode the attribute qdm node + * @param dataCriteriaElem the data criteria elem + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param isOrder the is order + */ + protected void generateDateTimeAttributesTag( + Node dateTimeNode, + Node attributeQDMNode, + Element dataCriteriaElem, + XmlProcessor dataCriteriaXMLProcessor, + boolean isOrder) { + + String attrName = (String) attributeQDMNode.getUserData(ATTRIBUTE_NAME); + String attrMode = (String) attributeQDMNode.getUserData(ATTRIBUTE_MODE); + String attrDate = (String) attributeQDMNode.getUserData(ATTRIBUTE_DATE); + + String timeTagName = ""; + switch (attrName.toLowerCase()) { + case START_DATETIME: + case FACILITY_LOCATION_ARRIVAL_DATETIME: + case ADMISSION_DATETIME: + case ACTIVE_DATETIME: + case DATE: + case TIME: + case INCISION_DATETIME: + case ONSET_DATETIME: + timeTagName = LOW; + break; + case STOP_DATETIME: + case FACILITY_LOCATION_DEPARTURE_DATETIME: + case DISCHARGE_DATETIME: + case REMOVAL_DATETIME: + case SIGNED_DATETIME: + case RECORDED_DATETIME: + case ABATEMENT_DATETIME: + timeTagName = HIGH; + break; + default: + timeTagName = ""; + break; + } + + if (CHECK_IF_PRESENT.equals(attrMode)) { + + if (timeTagName.length() > 0) { + Element timeTagNode = dataCriteriaElem.getOwnerDocument().createElement(timeTagName); + timeTagNode.setAttribute(FLAVOR_ID, "ANY.NONNULL"); + dateTimeNode.appendChild(timeTagNode); + } + } else { + if (attrMode.equals(Generator.EQUAL_TO)) { + if (timeTagName.length() > 0) { + Element timeTagNode = dataCriteriaElem.getOwnerDocument().createElement(timeTagName); + timeTagNode.setAttribute(VALUE, attrDate); + dateTimeNode.appendChild(timeTagNode); + } + } else if (attrMode.startsWith(Generator.GREATER_THAN)) { + if (timeTagName.length() > 0) { + Element timeTagNode = dataCriteriaElem.getOwnerDocument().createElement(timeTagName); + Element uncertainRangeNode = + dataCriteriaElem.getOwnerDocument().createElement("uncertainRange"); + if (attrMode.equals(Generator.GREATER_THAN)) { + uncertainRangeNode.setAttribute("lowClosed", "false"); + } + Element lowNode = dataCriteriaElem.getOwnerDocument().createElement(LOW); + lowNode.setAttribute(XSI_TYPE, "TS"); + lowNode.setAttribute(VALUE, attrDate); + + Element highNode = dataCriteriaElem.getOwnerDocument().createElement(HIGH); + highNode.setAttribute(XSI_TYPE, "TS"); + highNode.setAttribute("nullFlavor", "PINF"); + + uncertainRangeNode.appendChild(lowNode); + uncertainRangeNode.appendChild(highNode); + timeTagNode.appendChild(uncertainRangeNode); + dateTimeNode.appendChild(timeTagNode); + } + } else if (attrMode.startsWith(Generator.LESS_THAN)) { + if (timeTagName.length() > 0) { + Element timeTagNode = dataCriteriaElem.getOwnerDocument().createElement(timeTagName); + Element uncertainRangeNode = + dataCriteriaElem.getOwnerDocument().createElement("uncertainRange"); + if (attrMode.equals(Generator.LESS_THAN)) { + uncertainRangeNode.setAttribute("highClosed", "false"); + } + Element lowNode = dataCriteriaElem.getOwnerDocument().createElement(LOW); + lowNode.setAttribute(XSI_TYPE, "TS"); + lowNode.setAttribute("nullFlavor", "NINF"); + + Element highNode = dataCriteriaElem.getOwnerDocument().createElement(HIGH); + highNode.setAttribute(XSI_TYPE, "TS"); + highNode.setAttribute(VALUE, attrDate); + + uncertainRangeNode.appendChild(lowNode); + uncertainRangeNode.appendChild(highNode); + timeTagNode.appendChild(uncertainRangeNode); + dateTimeNode.appendChild(timeTagNode); + } + } + } + + /** If effectiveTimeNode has any child nodes then add it to the main dataCriteriaNode. */ + if (dateTimeNode.hasChildNodes()) { + + if (attrName.equalsIgnoreCase(START_DATETIME) + || attrName.equalsIgnoreCase(STOP_DATETIME) + || attrName.equalsIgnoreCase(SIGNED_DATETIME) + || attrName.equalsIgnoreCase(RECORDED_DATETIME)) { + NodeList nodeList = dataCriteriaElem.getElementsByTagName("participation"); + if ((nodeList != null) && (nodeList.getLength() > 0) && isOrder) { + if (nodeList.getLength() > 1) { + nodeList + .item(1) + .insertBefore(dateTimeNode, dataCriteriaElem.getElementsByTagName("role").item(1)); + } else { + nodeList + .item(0) + .insertBefore(dateTimeNode, dataCriteriaElem.getElementsByTagName("role").item(0)); + } + } else { + NodeList valueNodeList = dataCriteriaElem.getElementsByTagName("value"); + if ((valueNodeList != null) && (valueNodeList.getLength() > 0)) { + dataCriteriaElem.insertBefore(dateTimeNode, valueNodeList.item(0)); + } else { + NodeList statusCodeNodeList = dataCriteriaElem.getElementsByTagName("statusCode"); + if ((statusCodeNodeList != null) && (statusCodeNodeList.getLength() > 0)) { + dataCriteriaElem.insertBefore( + dateTimeNode, statusCodeNodeList.item(0).getNextSibling()); + } else { + checkIfOutBoundOcc(dataCriteriaElem, dateTimeNode); + } + } + } + } else { + NodeList nodeList = dataCriteriaElem.getElementsByTagName("value"); + if ((nodeList != null) && (nodeList.getLength() > 0)) { + dataCriteriaElem.insertBefore(dateTimeNode, nodeList.item(0)); + } else { + + if (attrName.contains("facility")) { + NodeList nodeListParticipation = dataCriteriaElem.getElementsByTagName("role"); + if ((nodeListParticipation != null) && (nodeListParticipation.getLength() > 0)) { + nodeListParticipation + .item(0) + .getFirstChild() + .getParentNode() + .appendChild(dateTimeNode); + } + } else if (attrName.equalsIgnoreCase( + INCISION_DATETIME)) { // for Incision Datetime Attribute + // effective Time is Added inside + NodeList nodeListProcedureCriteria = + dataCriteriaElem.getElementsByTagName("procedureCriteria"); + if ((nodeListProcedureCriteria != null) + && (nodeListProcedureCriteria.getLength() > 0)) { + nodeListProcedureCriteria + .item(0) + .getFirstChild() + .getParentNode() + .appendChild(dateTimeNode); + } + } else { + NodeList nodeListParticipation = dataCriteriaElem.getElementsByTagName("participation"); + if ((nodeListParticipation != null) && (nodeListParticipation.getLength() > 0)) { + dataCriteriaElem.insertBefore(dateTimeNode, nodeListParticipation.item(0)); + } else { + checkIfOutBoundOcc(dataCriteriaElem, dateTimeNode); + } + } + } + } + } + } + + /** + * Adds the data criteria comment. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + */ + private void addDataCriteriaComment(XmlProcessor dataCriteriaXMLProcessor) { + Element element = dataCriteriaXMLProcessor.getOriginalDoc().getDocumentElement(); + Comment comment = + dataCriteriaXMLProcessor.getOriginalDoc().createComment("Data Criteria Section"); + element.getParentNode().insertBefore(comment, element); + } + + /** + * Creates the code for datatype. + * + * @param templateNode the template node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @return the element + */ + protected Element createCodeForDatatype( + Node templateNode, XmlProcessor dataCriteriaXMLProcessor) { + Node codeAttr = templateNode.getAttributes().getNamedItem(CODE); + Node codeSystemAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM); + Node codeSystemNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_NAME); + Node codeDisplayNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_DISPLAY_NAME); + Element codeElement = null; + if ((codeAttr != null) + || (codeSystemAttr != null) + || (codeSystemNameAttr != null) + || (codeDisplayNameAttr != null)) { + codeElement = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + if (codeAttr != null) { + codeElement.setAttribute(CODE, codeAttr.getNodeValue()); + } + if (codeSystemAttr != null) { + codeElement.setAttribute(CODE_SYSTEM, codeSystemAttr.getNodeValue()); + } + if (codeSystemNameAttr != null) { + codeElement.setAttribute(CODE_SYSTEM_NAME, codeSystemNameAttr.getNodeValue()); + } + if (codeDisplayNameAttr != null) { + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + displayNameElem.setAttribute(VALUE, codeDisplayNameAttr.getNodeValue()); + codeElement.appendChild(displayNameElem); + } + } + return codeElement; + } + + /** + * This method is called before we start generating HQMF code for various data criteria elements. + * It will perform the task of prepping the Simple XML for the clause generation process. It will + * do the following, + * + *

1) Call prepForAGE_AT(MeasureExport me) which will, Look for and replace it with The first child of this new + * relationalOp will be the elementRef for Birthdate QDM element. The 2nd child will be the first + * child of the original . + */ + private void prepHQMF(MeasureExport me) { + logger.debug("Prepping for HQMF Clause generation.............."); + prepForUUID(me); + prepForAGE_AT(me); + prepForSatisfiesAll_Any(me); + logger.debug("Done prepping for HQMF Clause generation."); + } + + private void prepForUUID(MeasureExport me) { + + String xPathForFunctionalOp = "/measure/subTreeLookUp//functionalOp"; + String xPathForRelationalOp = "/measure/subTreeLookUp//relationalOp"; + String xPathForSetOp = "/measure/subTreeLookUp//setOp"; + + try { + NodeList nodeList = + me.getSimpleXmlProcessor() + .findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), xPathForFunctionalOp); + addUUIDToNodes(nodeList); + + nodeList = + me.getSimpleXmlProcessor() + .findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), xPathForRelationalOp); + addUUIDToNodes(nodeList); + + nodeList = + me.getSimpleXmlProcessor() + .findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), xPathForSetOp); + addUUIDToNodes(nodeList); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void addUUIDToNodes(NodeList nodeList) { + if ((nodeList != null) && (nodeList.getLength() > 0)) { + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + ((Element) node).setAttribute("uuid", UUIDUtilClient.uuid()); + } + } + } + + /** + * This method will be called by prepHQMF(MeasureExport me) method to prep functionalOp for AGE AT + * functions. This methiod will do the following, + * + *

Look for and replace it with The first child of this new relationalOp will be the elementRef for Birthdate QDM + * element. The 2nd child will be the first child of the original . + * + * @param me + */ + private void prepForAGE_AT(MeasureExport me) { + XmlProcessor xmlProcessor = me.getSimpleXmlProcessor(); + logger.debug("Prepping for HQMF Clause generation for AGE AT functionalOps."); + + try { + + // find for Birthdate QDM element in elementLookUp + String xPathForBirthdate = + "/measure/elementLookUp/qdm[@name='Birthdate'][@datatype='Patient Characteristic Birthdate']"; + Node birthDateQDM = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), xPathForBirthdate); + if (birthDateQDM == null) { + logger.debug( + "********** Could not find QDM for Birthdate. No changes done for AGE AT. ***************"); + return; + } + + String xPathForAGE_AT = "/measure/subTreeLookUp//functionalOp[@type='AGE AT']"; + Node ageAtFuncNode = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), xPathForAGE_AT); + + logger.debug(".......found AGE AT functionalOps"); + + while (ageAtFuncNode != null) { + logger.debug("Changing " + ageAtFuncNode.toString() + " to relational SBS node."); + Node cloneAgeAtRelNode = ageAtFuncNode.cloneNode(true); + + // hold on to the first child of Age At + Node firstChild = cloneAgeAtRelNode.getFirstChild(); + NamedNodeMap attribMap = ageAtFuncNode.getAttributes(); + Element newRelationalOp = xmlProcessor.getOriginalDoc().createElement("relationalOp"); + + for (int j = 0; j < attribMap.getLength(); j++) { + Node attrib = attribMap.item(j); + newRelationalOp.setAttribute(attrib.getNodeName(), attrib.getNodeValue()); + } + + // set the type attribute to SBS + newRelationalOp.getAttributes().getNamedItem("type").setNodeValue("SBS"); + + // create a new This method will look for all functionalOp's with names, SATISFIES ALL/SATISFIES ANY renames + * the tag with tag. + * + * @param me + */ + private void prepForSatisfiesAll_Any(MeasureExport me) { + XmlProcessor xmlProcessor = me.getSimpleXmlProcessor(); + logger.debug( + "Prepping for HQMF Clause generation for Satisfies All/Satisfies Any functionalOps."); + String xPathForSatisfiesAllAny = + "/measure/subTreeLookUp//functionalOp[@type='SATISFIES ALL' or @type='SATISFIES ANY']"; + try { + Node satisfiesFuncNode = + xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), xPathForSatisfiesAllAny); + logger.debug(".......found Satisfies All/Satisfies Any functionalOps"); + while (satisfiesFuncNode != null) { + logger.debug( + "Changing functionaOp " + + satisfiesFuncNode.getAttributes().getNamedItem("displayName").getNodeValue() + + " to relationalOp node."); + + NamedNodeMap attribMap = satisfiesFuncNode.getAttributes(); + Element newSetOp = xmlProcessor.getOriginalDoc().createElement("setOp"); + + for (int j = 0; j < attribMap.getLength(); j++) { + Node attrib = attribMap.item(j); + newSetOp.setAttribute(attrib.getNodeName(), attrib.getNodeValue()); + } + + NodeList childNodeList = satisfiesFuncNode.getChildNodes(); + /** Ignore the first element of SATISFIES ALL/ANY. i.e. Start counter at 1 isntead of 0. */ + for (int j = 1; j < childNodeList.getLength(); j++) { + Node childNode = childNodeList.item(j).cloneNode(true); + newSetOp.appendChild(childNode); + } + + Node parentNode = satisfiesFuncNode.getParentNode(); + parentNode.insertBefore(newSetOp, satisfiesFuncNode); + parentNode.removeChild(satisfiesFuncNode); + logger.debug("Change done."); + satisfiesFuncNode = + xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), xPathForSatisfiesAllAny); + } + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + + /** + * Gets the unit string. + * + * @param unitString the unit string + * @return the unit string + */ + protected String getUnitString(String unitString) { + String returnString = unitString; + + if (unitString.equals("years") || unitString.equals("year")) { + returnString = "a"; + } else if (unitString.equals("month") || unitString.equals("months")) { + returnString = "mo"; + } else if (unitString.equals("day") || unitString.equals("days")) { + returnString = "d"; + } else if (unitString.equals("hours") || unitString.equals("hour")) { + returnString = "h"; + } else if (unitString.equals("week") || unitString.equals("weeks")) { + returnString = "wk"; + } else if (unitString.equals("minutes") || unitString.equals("minute")) { + returnString = "min"; + } else if (unitString.equals("quarter") || unitString.equals("quarters")) { + returnString = "[qtr]"; + } else if (unitString.equals("second") || unitString.equals("seconds")) { + returnString = "s"; + } else if (unitString.equals("bpm")) { + returnString = "{H.B.}/min"; + } else if (unitString.equals("mmHg")) { + returnString = "mm[Hg]"; + } else if (unitString.equals("mEq")) { + returnString = "meq"; + } else if (unitString.equals("celsius")) { + returnString = "Cel"; + } else if (unitString.equals("WBC/mm3")) { + returnString = "{WBC}/mm3"; + } else if (unitString.equals("WBC/hpf")) { + returnString = "{WBC}/[HPF]"; + } else if (unitString.equals("CFU/mL")) { + returnString = "[CFU]/mL"; + } else if (unitString.equals("per mm3")) { + returnString = "/mm3"; + } else if (unitString.equals("copies/mL")) { + returnString = "{copies}/mL"; + } else if (unitString.equals("IU")) { + returnString = "[iU]"; + } else if (unitString.equals("IU/L")) { + returnString = "[iU]/L"; + } else if (unitString.equals("AU")) { + returnString = "[AU]"; + } else if (unitString.equals("BAU")) { + returnString = "[BAU]"; + } + + return returnString; + } + + /** + * Check if out bound is occurrence and append the Attribute entry before Temporal and + * outBoundRelationShip Tag. + * + * @param dataCriteriaElem the data criteria elem + * @param dateTimeNode the date time node + */ + private void checkIfOutBoundOcc(Element dataCriteriaElem, Node dateTimeNode) { + Node outBoundOccNode = dataCriteriaElem.getElementsByTagName("outboundRelationship").item(0); + if ((outBoundOccNode != null) + && outBoundOccNode + .getAttributes() + .getNamedItem("typeCode") + .getNodeValue() + .equalsIgnoreCase("OCCR")) { + dataCriteriaElem.insertBefore(dateTimeNode, outBoundOccNode); + } else { + dataCriteriaElem.appendChild(dateTimeNode); + } + } } diff --git a/src/main/java/gov/cms/madie/hqmf/HQMFFinalCleanUp.java b/src/main/java/gov/cms/madie/hqmf/HQMFFinalCleanUp.java index 7502e12..4cd9bff 100644 --- a/src/main/java/gov/cms/madie/hqmf/HQMFFinalCleanUp.java +++ b/src/main/java/gov/cms/madie/hqmf/HQMFFinalCleanUp.java @@ -10,182 +10,189 @@ import javax.xml.xpath.XPathExpressionException; public class HQMFFinalCleanUp { - - /** The Constant logger. */ - private static final Logger logger = LoggerFactory - .getLogger(HQMFFinalCleanUp.class); - - /** The Constant reverseEntryCheckFile. */ - private static final String reverseEntryCheckFile = "xsl/final_hqmf_entry_deletion_check.xsl"; - - /** The Constant deleteUnUsedEntryFile. */ - private static final String deleteUnUsedEntryFile = "xsl/hqmf_delete_Unused_entry.xsl"; - - /** - * Clean. - * - * @param me the me - */ - public static void clean(MeasureExport me) { - - XmlProcessor hqmfProcessor = me.getHqmfXmlProcessor(); - XmlProcessor simpleProcessor = me.getSimpleXmlProcessor(); - - if(hqmfProcessor == null){ - logger.debug("HQMF document is null. Aborting clean up."); - return; - } - - if(simpleProcessor == null){ - logger.debug("SimpleXML document is null. Aborting clean up."); - return; - } - - cleanExtensions(me); - cleanLocalVariableNames(me); - //deleteUnusedEntry(me); - - } - - public static void cleanAndDeleteUnused(MeasureExport me) { - clean(me); - deleteUnusedEntry(me); - } - - - /** - * Clean extensions. - * - * @param me the me - */ - private static void cleanExtensions(MeasureExport me) { - - String xPathForExtensions = "//*/@extension"; - try { - NodeList extensionsList = me.getHqmfXmlProcessor().findNodeList(me.getHqmfXmlProcessor().getOriginalDoc(), xPathForExtensions); - for(int i=0;i=") > -1){ - extValue = StringUtils.replace(extValue, ">=", "grtr_thn_eql_"); - - } - if(extValue.indexOf(">") > -1){ - extValue = StringUtils.replace(extValue, ">", "grtr_thn_"); - - } - if(extValue.indexOf("<=") > -1){ - extValue = StringUtils.replace(extValue, "<=", "less_thn_eql_"); - } - if(extValue.indexOf("<") > -1){ - extValue = StringUtils.replace(extValue, "<", "less_thn_"); - } - if(extValue.indexOf("=") > -1){ - extValue = StringUtils.replace(extValue, "=", "eql_"); - } - if(extValue.contains(",")) { - extValue = StringUtils.remove(extValue, ','); - } - if(extValue.contains("'")) { - extValue = StringUtils.remove(extValue, "'"); - } - return extValue; - } - - - /** - * Delete unused entry. - * This method is to check and delete Unused QDM Entries - * in HQMF - * - * @param me the me - */ - private static void deleteUnusedEntry(MeasureExport me) { - String delDupEntryResults = XMLUtility.getInstance().applyXSL(me.getHqmfXmlProcessor().transform(me.getHqmfXmlProcessor().getOriginalDoc()), - XMLUtility.getInstance().getXMLResource(deleteUnUsedEntryFile)); - - me.setHqmfXmlProcessor(new XmlProcessor(delDupEntryResults)); - - reverseEntryCheck(delDupEntryResults); - } + /** The Constant logger. */ + private static final Logger logger = LoggerFactory.getLogger(HQMFFinalCleanUp.class); + + /** The Constant reverseEntryCheckFile. */ + private static final String reverseEntryCheckFile = "xsl/final_hqmf_entry_deletion_check.xsl"; + + /** The Constant deleteUnUsedEntryFile. */ + private static final String deleteUnUsedEntryFile = "xsl/hqmf_delete_Unused_entry.xsl"; + + /** + * Clean. + * + * @param me the me + */ + public static void clean(MeasureExport me) { + + XmlProcessor hqmfProcessor = me.getHqmfXmlProcessor(); + XmlProcessor simpleProcessor = me.getSimpleXmlProcessor(); + + if (hqmfProcessor == null) { + logger.debug("HQMF document is null. Aborting clean up."); + return; + } + + if (simpleProcessor == null) { + logger.debug("SimpleXML document is null. Aborting clean up."); + return; + } + + cleanExtensions(me); + cleanLocalVariableNames(me); + // deleteUnusedEntry(me); + + } + + public static void cleanAndDeleteUnused(MeasureExport me) { + clean(me); + deleteUnusedEntry(me); + } + + /** + * Clean extensions. + * + * @param me the me + */ + private static void cleanExtensions(MeasureExport me) { + + String xPathForExtensions = "//*/@extension"; + try { + NodeList extensionsList = + me.getHqmfXmlProcessor() + .findNodeList(me.getHqmfXmlProcessor().getOriginalDoc(), xPathForExtensions); + for (int i = 0; i < extensionsList.getLength(); i++) { + Node extNode = extensionsList.item(i); + String extValue = extNode.getNodeValue(); + + extValue = getReplaceString(extValue); + extNode.setNodeValue(extValue); + } + + } catch (XPathExpressionException e) { + logger.error("Exception in HQMFFinalCleanUp.cleanExtensions:" + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * Clean local variable names. + * + * @param me the me + */ + private static void cleanLocalVariableNames(MeasureExport me) { + + String xPathForLocalVars = "//localVariableName/@value"; + String xPathForMeasureObValueExpression = "//measureObservationDefinition//value/expression"; + String xPathForMeasureObPreconditionVal = "//measureObservationDefinition//precondition//value"; + + try { + NodeList localVarValuesList = + me.getHqmfXmlProcessor() + .findNodeList(me.getHqmfXmlProcessor().getOriginalDoc(), xPathForLocalVars); + NodeList measureObValueExpList = + me.getHqmfXmlProcessor() + .findNodeList( + me.getHqmfXmlProcessor().getOriginalDoc(), xPathForMeasureObValueExpression); + NodeList measureObPreConditionValList = + me.getHqmfXmlProcessor() + .findNodeList( + me.getHqmfXmlProcessor().getOriginalDoc(), xPathForMeasureObPreconditionVal); + for (int i = 0; i < localVarValuesList.getLength(); i++) { + Node extNode = localVarValuesList.item(i); + String extValue = extNode.getNodeValue(); + extValue = getReplaceString(extValue); + extNode.setNodeValue(extValue); + } + + for (int i = 0; i < measureObValueExpList.getLength(); i++) { + Node expressionNode = measureObValueExpList.item(i); + String value = expressionNode.getAttributes().getNamedItem("value").getNodeValue(); + value = getReplaceString(value); + expressionNode.getAttributes().getNamedItem("value").setNodeValue(value); + } + + for (int i = 0; i < measureObPreConditionValList.getLength(); i++) { + Node valueNode = measureObPreConditionValList.item(i); + String value = valueNode.getAttributes().getNamedItem("value").getNodeValue(); + String[] preConditionExpArray = value.split("=="); + String preCondExpValue = null; + for (String valueToEval : preConditionExpArray) { + if (preCondExpValue == null) { + preCondExpValue = getReplaceString(valueToEval); + } else { + preCondExpValue = preCondExpValue + "==" + getReplaceString(valueToEval); + } + } + value = getReplaceString(value); + valueNode.getAttributes().getNamedItem("value").setNodeValue(preCondExpValue); + } + + } catch (XPathExpressionException e) { + logger.error("Exception in HQMFFinalCleanUp.cleanExtensions:" + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * Reverse entry check. + * + * @param me the me + */ + private static void reverseEntryCheck(String hqmfXML) { + String reverseEntryCheckResults = + XMLUtility.getInstance() + .applyXSL(hqmfXML, XMLUtility.getInstance().getXMLResource(reverseEntryCheckFile)); + logger.debug("Reverse Entry Check results: " + reverseEntryCheckResults); + } + + /** + * Gets the replace string. + * + * @param extValue the ext value + * @return the replace string + */ + private static String getReplaceString(String extValue) { + if (extValue.indexOf(">=") > -1) { + extValue = StringUtils.replace(extValue, ">=", "grtr_thn_eql_"); + } + if (extValue.indexOf(">") > -1) { + extValue = StringUtils.replace(extValue, ">", "grtr_thn_"); + } + if (extValue.indexOf("<=") > -1) { + extValue = StringUtils.replace(extValue, "<=", "less_thn_eql_"); + } + if (extValue.indexOf("<") > -1) { + extValue = StringUtils.replace(extValue, "<", "less_thn_"); + } + if (extValue.indexOf("=") > -1) { + extValue = StringUtils.replace(extValue, "=", "eql_"); + } + if (extValue.contains(",")) { + extValue = StringUtils.remove(extValue, ','); + } + if (extValue.contains("'")) { + extValue = StringUtils.remove(extValue, "'"); + } + return extValue; + } + + /** + * Delete unused entry. This method is to check and delete Unused QDM Entries in HQMF + * + * @param me the me + */ + private static void deleteUnusedEntry(MeasureExport me) { + String delDupEntryResults = + XMLUtility.getInstance() + .applyXSL( + me.getHqmfXmlProcessor().transform(me.getHqmfXmlProcessor().getOriginalDoc()), + XMLUtility.getInstance().getXMLResource(deleteUnUsedEntryFile)); + + me.setHqmfXmlProcessor(new XmlProcessor(delDupEntryResults)); + + reverseEntryCheck(delDupEntryResults); + } } diff --git a/src/main/java/gov/cms/madie/hqmf/HQMFGeneratorFactory.java b/src/main/java/gov/cms/madie/hqmf/HQMFGeneratorFactory.java index 568f241..cef6555 100644 --- a/src/main/java/gov/cms/madie/hqmf/HQMFGeneratorFactory.java +++ b/src/main/java/gov/cms/madie/hqmf/HQMFGeneratorFactory.java @@ -2,23 +2,20 @@ import gov.cms.madie.hqmf.qdm_5_6.HQMFGenerator; import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -/** - * Factory class to select the proper HQMF generator based on QDM model version. - */ +/** Factory class to select the proper HQMF generator based on QDM model version. */ @Slf4j @Component @AllArgsConstructor -@NoArgsConstructor public class HQMFGeneratorFactory { - private HQMFGenerator qdm_5_6_generator; + private HQMFGenerator qdm_5_6_generator; - public Generator getHQMFGenerator() { - // Keeping generator around in case we need to support additional versions or implementations in the future - return qdm_5_6_generator; - } + public Generator getHQMFGenerator() { + // Keeping generator around in case we need to support additional versions or implementations in + // the future + return qdm_5_6_generator; + } } diff --git a/src/main/java/gov/cms/madie/hqmf/MatConstants.java b/src/main/java/gov/cms/madie/hqmf/MatConstants.java index ebd5885..85905f7 100644 --- a/src/main/java/gov/cms/madie/hqmf/MatConstants.java +++ b/src/main/java/gov/cms/madie/hqmf/MatConstants.java @@ -1,97 +1,94 @@ -/** - * - */ +/** */ package gov.cms.madie.hqmf; /** - * This holds constants used across MAT. - * These constants are available on client as well as server side. + * This holds constants used across MAT. These constants are available on client as well as server + * side. */ - public interface MatConstants { - String NUMERATOR_EXCLUSIONS = "numeratorExclusions"; - String DENOMINATOR_EXCEPTIONS = "denominatorExceptions"; - String DENOMINATOR_EXCLUSIONS = "denominatorExclusions"; - String STRATUM = "stratum"; - String MEASURE_POPULATION_EXCLUSIONS = "measurePopulationExclusions"; - String INITIAL_POPULATION = "initialPopulation"; - String MEASURE_OBSERVATION_POPULATION = "measureObservation"; - String TAXONOMY = "taxonomy"; - String DATATYPE = "datatype"; - String DATETIMEDIFF = "Datetimediff"; - String FIRST = "First"; - String SECOND = "Second"; - String THIRD = "Third"; - String FOURTH = "Fourth"; - String FIFTH = "Fifth"; - String MOST_RECENT = "Most Recent"; - String TIMEDIFF = "TIMEDIFF"; - String SUM = "Sum"; - String MEDIAN = "Median"; - String MIN = "Min"; - String MAX = "Max"; - String DATEDIFF = "DATEDIFF"; - String COUNT = "Count"; - String AVG = "Avg"; - String AGE_AT = "Age At"; - String DATE = "date"; - String MODE = "mode"; - String NAME = "name"; - String NEGATION_RATIONALE = "negation rationale"; - String ATTRIBUTE = "attribute"; - String OCCURRENCE = "Occurrence"; - String UNIT = "unit"; - String UUID = "uuid"; - String ASSOCIATED_POPULATION_UUID = "associatedPopulationUUID"; - String NONE = "None"; - String CONTINUOUS_VARIABLE = "continuous Variable"; - String COHORT = "cohort"; - String PROPORTION = "proportion"; - String SATISFIES = "SATISFIES"; - String STRATIFICATION = "Stratification"; - String TRUE = "true"; - String AND = "AND"; - String MEASURE_OBSERVATION = "Measure Observation"; - String MEASURE_DETAILS = "measureDetails"; - String RATIO = "ratio"; - String MEASURE_POPULATION = "measurePopulation"; - String NUMERATOR = "numerator"; - String DENOMINATOR = "denominator"; - String TYPE = "type"; - String FALSE = "false"; - String QDM_VARIABLE = "qdmVariable"; - String ID = "id"; - String INSTANCE_OF = "instanceOf"; - String INSTANCE = "instance"; - String ELEMENT_LOOK_UP = "elementLookUp"; - String FUNCTIONAL_OP = "functionalOp"; - String DISPLAY_NAME = "displayName"; - String ELEMENT_REF = "elementRef"; - String RELATIONAL_OP = "relationalOp"; - String HTML_LI = "li"; - String HTML_UL = "ul"; - String SET_OP = "setOp"; - String SUB_TREE = "subTree"; - String COMMENT = "comment"; - String LOGICAL_OP = "logicalOp"; - String ATTR_UUID = "attrUUID"; - String SUB_TREE_REF = "subTreeRef"; - String EXTENSION = "extension"; - String FULFILLS = "FULFILLS"; - String QUANTITY = "quantity"; - String ATTR_DATE = "attrDate"; - String COMPARISON_VALUE = "comparisonValue"; - String OPERATOR_TYPE = "operatorType"; - String SATISFIES_ANY = "Satisfies Any"; - String SATISFIES_ALL = "Satisfies All"; - String STARTS_CONCURRENT_WITH = "Starts Concurrent With"; - String STARTS_CONCURRENT_WITH_END_OF = "Starts Concurrent With End Of"; - String STARTS_DURING = "Starts During"; - String ENDS_CONCURRENT_WITH = "Ends Concurrent With"; - String ENDS_CONCURRENT_WITH_START_OF = "Ends Concurrent With Start Of"; - String ENDS_DURING = "Ends During"; - String CONCURRENT_WITH = "Concurrent With"; - String DURING = "During"; - String OVERLAPS = "Overlaps"; - String NOT_APPLICABLE = "Not Applicable"; + String NUMERATOR_EXCLUSIONS = "numeratorExclusions"; + String DENOMINATOR_EXCEPTIONS = "denominatorExceptions"; + String DENOMINATOR_EXCLUSIONS = "denominatorExclusions"; + String STRATUM = "stratum"; + String MEASURE_POPULATION_EXCLUSIONS = "measurePopulationExclusions"; + String INITIAL_POPULATION = "initialPopulation"; + String MEASURE_OBSERVATION_POPULATION = "measureObservation"; + String TAXONOMY = "taxonomy"; + String DATATYPE = "datatype"; + String DATETIMEDIFF = "Datetimediff"; + String FIRST = "First"; + String SECOND = "Second"; + String THIRD = "Third"; + String FOURTH = "Fourth"; + String FIFTH = "Fifth"; + String MOST_RECENT = "Most Recent"; + String TIMEDIFF = "TIMEDIFF"; + String SUM = "Sum"; + String MEDIAN = "Median"; + String MIN = "Min"; + String MAX = "Max"; + String DATEDIFF = "DATEDIFF"; + String COUNT = "Count"; + String AVG = "Avg"; + String AGE_AT = "Age At"; + String DATE = "date"; + String MODE = "mode"; + String NAME = "name"; + String NEGATION_RATIONALE = "negation rationale"; + String ATTRIBUTE = "attribute"; + String OCCURRENCE = "Occurrence"; + String UNIT = "unit"; + String UUID = "uuid"; + String ASSOCIATED_POPULATION_UUID = "associatedPopulationUUID"; + String NONE = "None"; + String CONTINUOUS_VARIABLE = "continuous Variable"; + String COHORT = "cohort"; + String PROPORTION = "proportion"; + String SATISFIES = "SATISFIES"; + String STRATIFICATION = "Stratification"; + String TRUE = "true"; + String AND = "AND"; + String MEASURE_OBSERVATION = "Measure Observation"; + String MEASURE_DETAILS = "measureDetails"; + String RATIO = "ratio"; + String MEASURE_POPULATION = "measurePopulation"; + String NUMERATOR = "numerator"; + String DENOMINATOR = "denominator"; + String TYPE = "type"; + String FALSE = "false"; + String QDM_VARIABLE = "qdmVariable"; + String ID = "id"; + String INSTANCE_OF = "instanceOf"; + String INSTANCE = "instance"; + String ELEMENT_LOOK_UP = "elementLookUp"; + String FUNCTIONAL_OP = "functionalOp"; + String DISPLAY_NAME = "displayName"; + String ELEMENT_REF = "elementRef"; + String RELATIONAL_OP = "relationalOp"; + String HTML_LI = "li"; + String HTML_UL = "ul"; + String SET_OP = "setOp"; + String SUB_TREE = "subTree"; + String COMMENT = "comment"; + String LOGICAL_OP = "logicalOp"; + String ATTR_UUID = "attrUUID"; + String SUB_TREE_REF = "subTreeRef"; + String EXTENSION = "extension"; + String FULFILLS = "FULFILLS"; + String QUANTITY = "quantity"; + String ATTR_DATE = "attrDate"; + String COMPARISON_VALUE = "comparisonValue"; + String OPERATOR_TYPE = "operatorType"; + String SATISFIES_ANY = "Satisfies Any"; + String SATISFIES_ALL = "Satisfies All"; + String STARTS_CONCURRENT_WITH = "Starts Concurrent With"; + String STARTS_CONCURRENT_WITH_END_OF = "Starts Concurrent With End Of"; + String STARTS_DURING = "Starts During"; + String ENDS_CONCURRENT_WITH = "Ends Concurrent With"; + String ENDS_CONCURRENT_WITH_START_OF = "Ends Concurrent With Start Of"; + String ENDS_DURING = "Ends During"; + String CONCURRENT_WITH = "Concurrent With"; + String DURING = "During"; + String OVERLAPS = "Overlaps"; + String NOT_APPLICABLE = "Not Applicable"; } diff --git a/src/main/java/gov/cms/madie/hqmf/QDMTemplateProcessorFactory.java b/src/main/java/gov/cms/madie/hqmf/QDMTemplateProcessorFactory.java index d7fb6e6..2e33a2f 100644 --- a/src/main/java/gov/cms/madie/hqmf/QDMTemplateProcessorFactory.java +++ b/src/main/java/gov/cms/madie/hqmf/QDMTemplateProcessorFactory.java @@ -7,35 +7,23 @@ /** * DO NOT DELETE OLDER GENERATORS. * - * On Export, MAT will serve up the latest pre-existing instance in the MEASURE_EXPORT table. If no HQMF exists, - * then MAT will generate the HQMF during the Export operation and save it to the table. Older versions of the Generators - * are kept to ensure the HQMF can be generated on-demand. + *

On Export, MAT will serve up the latest pre-existing instance in the MEASURE_EXPORT table. If + * no HQMF exists, then MAT will generate the HQMF during the Export operation and save it to the + * table. Older versions of the Generators are kept to ensure the HQMF can be generated on-demand. */ public class QDMTemplateProcessorFactory { - - public static XmlProcessor getTemplateProcessor(double qdmVersion) { - String fileName; -// if(qdmVersion == 5.3) { -// fileName = "templates/hqmf/qdm_v5_3_datatype_templates.xml"; -// } else if(qdmVersion == 5.4) { -// fileName = "templates/hqmf/qdm_v5_4_datatype_templates.xml"; -// } else if(qdmVersion == 5.5) { -// fileName = "templates/hqmf/qdm_v5_5_datatype_templates.xml"; -// } else if(qdmVersion == 5.6) { - fileName = "templates/hqmf/qdm_v5_6_datatype_templates.xml"; -// } else { -// fileName = "templates/hqmf/qdm_v4_x_datatype_templates.xml"; -// } + public static XmlProcessor getTemplateProcessor(double qdmVersion) { + String fileName = "templates/hqmf/qdm_v5_6_datatype_templates.xml"; - URL templateFileUrl = QDMTemplateProcessorFactory.class.getClassLoader().getResource(fileName); - File templateFile = null; - try { - templateFile = new File(templateFileUrl.toURI()); - } catch (URISyntaxException e) { - e.printStackTrace(); - } - - return new XmlProcessor(templateFile); - } + URL templateFileUrl = QDMTemplateProcessorFactory.class.getClassLoader().getResource(fileName); + File templateFile = null; + try { + templateFile = new File(templateFileUrl.toURI()); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + + return new XmlProcessor(templateFile); + } } diff --git a/src/main/java/gov/cms/madie/hqmf/UUIDUtilClient.java b/src/main/java/gov/cms/madie/hqmf/UUIDUtilClient.java index 1b3caba..9b524db 100644 --- a/src/main/java/gov/cms/madie/hqmf/UUIDUtilClient.java +++ b/src/main/java/gov/cms/madie/hqmf/UUIDUtilClient.java @@ -1,75 +1,68 @@ package gov.cms.madie.hqmf; -/** - * The Class UUIDUtilClient. - */ +/** The Class UUIDUtilClient. */ public class UUIDUtilClient { - /** The Constant CHARS. */ - private static final char[] CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); - - /** - * Generate a random uuid of the specified length. Example: uuid(15) - * returns "VcydxgltxrVZSTV" - * - * @param len - * the desired number of characters - * @return the string - */ - public static String uuid(int len) { - return uuid(len, CHARS.length); - } - - /** - * Generate a random uuid of the specified length, and radix. Examples: - *

    - *
  • uuid(8, 2) returns "01001010" (8 character ID, base=2) - *
  • uuid(8, 10) returns "47473046" (8 character ID, base=10) - *
  • uuid(8, 16) returns "098F4D35" (8 character ID, base=16) - *
- * - * @param len - * the desired number of characters - * @param radix - * the number of allowable values for each character (must be - * <= 62) - * @return the string - */ - public static String uuid(int len, int radix) { - if (radix > CHARS.length) { - throw new IllegalArgumentException(); - } - char[] uuid = new char[len]; - // Compact form - for (int i = 0; i < len; i++) { - uuid[i] = CHARS[(int)(Math.random()*radix)]; - } - return new String(uuid); - } - - /** - * Generate a RFC4122, version 4 ID. Example: - * "92329D39-6F5C-4520-ABFC-AAB64544E172" - * - * @return the string - */ - public static String uuid() { - char[] uuid = new char[36]; - int r; + /** The Constant CHARS. */ + private static final char[] CHARS = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); - // rfc4122 requires these characters - uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'; - uuid[14] = '4'; + /** + * Generate a random uuid of the specified length. Example: uuid(15) returns "VcydxgltxrVZSTV" + * + * @param len the desired number of characters + * @return the string + */ + public static String uuid(int len) { + return uuid(len, CHARS.length); + } - // Fill in random data. At i==19 set the high bits of clock sequence as - // per rfc4122, sec. 4.1.5 - for (int i = 0; i < 36; i++) { - if (uuid[i] == 0) { - r = (int) (Math.random()*16); - uuid[i] = CHARS[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf]; - } - } - return new String(uuid); - } + /** + * Generate a random uuid of the specified length, and radix. Examples: + * + *
    + *
  • uuid(8, 2) returns "01001010" (8 character ID, base=2) + *
  • uuid(8, 10) returns "47473046" (8 character ID, base=10) + *
  • uuid(8, 16) returns "098F4D35" (8 character ID, base=16) + *
+ * + * @param len the desired number of characters + * @param radix the number of allowable values for each character (must be <= 62) + * @return the string + */ + public static String uuid(int len, int radix) { + if (radix > CHARS.length) { + throw new IllegalArgumentException(); + } + char[] uuid = new char[len]; + // Compact form + for (int i = 0; i < len; i++) { + uuid[i] = CHARS[(int) (Math.random() * radix)]; + } + return new String(uuid); + } + /** + * Generate a RFC4122, version 4 ID. Example: "92329D39-6F5C-4520-ABFC-AAB64544E172" + * + * @return the string + */ + public static String uuid() { + char[] uuid = new char[36]; + int r; + + // rfc4122 requires these characters + uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'; + uuid[14] = '4'; + + // Fill in random data. At i==19 set the high bits of clock sequence as + // per rfc4122, sec. 4.1.5 + for (int i = 0; i < 36; i++) { + if (uuid[i] == 0) { + r = (int) (Math.random() * 16); + uuid[i] = CHARS[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf]; + } + } + return new String(uuid); + } } diff --git a/src/main/java/gov/cms/madie/hqmf/XMLUtility.java b/src/main/java/gov/cms/madie/hqmf/XMLUtility.java index 290ca28..00c64d1 100644 --- a/src/main/java/gov/cms/madie/hqmf/XMLUtility.java +++ b/src/main/java/gov/cms/madie/hqmf/XMLUtility.java @@ -26,121 +26,124 @@ @Slf4j public class XMLUtility { - private static final String HTTP_WWW_W3_ORG_2001_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; - private static XMLUtility instance; - private static final String DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl"; - private static final String LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd"; - private static final String EXTERNAL_GENERAL_ENTITIES = "http://xml.org/sax/features/external-general-entities"; - private static final String EXTERNAL_PARAMETER_ENTITIES = "http://xml.org/sax/features/external-parameter-entities"; - - public static XMLUtility getInstance() { - if(instance == null) { - instance = new XMLUtility(); - } - return instance; - } - private XMLUtility() {} + private static final String HTTP_WWW_W3_ORG_2001_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; + private static XMLUtility instance; + private static final String DISALLOW_DOCTYPE_DECL = + "http://apache.org/xml/features/disallow-doctype-decl"; + private static final String LOAD_EXTERNAL_DTD = + "http://apache.org/xml/features/nonvalidating/load-external-dtd"; + private static final String EXTERNAL_GENERAL_ENTITIES = + "http://xml.org/sax/features/external-general-entities"; + private static final String EXTERNAL_PARAMETER_ENTITIES = + "http://xml.org/sax/features/external-parameter-entities"; - /** - * Apply xsl. - * - * @param input - * the input - * @param xslt - * the xslt - * @return the string - */ - public String applyXSL(String input, String xslt) - { - //This system property sets the TransformFactory to use the Saxon TransformerFactoryImpl method - //This line is needed to prevent issues with XSLT transform. - System.setProperty("javax.xml.transform.TransformerFactory","net.sf.saxon.TransformerFactoryImpl"); - String result; - ByteArrayOutputStream outStream; - outStream = new ByteArrayOutputStream(); - TransformerFactory tFactory = buildTransformerFactory(); - Transformer transformer; - try { - transformer = tFactory.newTransformer(new StreamSource(xslt)); - transformer.transform(new StreamSource(new StringReader(input)), new StreamResult(outStream)); - } catch (TransformerConfigurationException e) { - log.error("An error occurred in transformer", e); - throw new RuntimeException("Error Configuring XML Transformer:", e.getCause()); - } catch (TransformerException e) { - log.error("An error occurred in transformer", e); - throw new RuntimeException("Error Transforming XML:", e.getCause()); - }catch(Exception e){ - log.error("An error occurred in transformer", e); - } - result = outStream.toString(); - return result; - } - - /** - * Gets the xML resource. - * - * @param name - * the name - * @return the xML resource - */ - public String getXMLResource(String name) { - try { - return new ClassPathResource(name).getURL().toExternalForm(); - } catch (IOException e) { - log.error("An error occurred loading the resource [{}]: ", name, e); - } - return null; - } - - public TransformerFactory buildTransformerFactory() { - TransformerFactory transformerFactory = SAXTransformerFactory.newInstance(); + public static XMLUtility getInstance() { + if (instance == null) { + instance = new XMLUtility(); + } + return instance; + } - try { - transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); - } catch(IllegalArgumentException | TransformerConfigurationException e) { - /* see JDK-8015487, some parsers do not handle these attributes */ - } + private XMLUtility() {} + /** + * Apply xsl. + * + * @param input the input + * @param xslt the xslt + * @return the string + */ + public String applyXSL(String input, String xslt) { + // This system property sets the TransformFactory to use the Saxon TransformerFactoryImpl method + // This line is needed to prevent issues with XSLT transform. + System.setProperty( + "javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl"); + String result; + ByteArrayOutputStream outStream; + outStream = new ByteArrayOutputStream(); + TransformerFactory tFactory = buildTransformerFactory(); + Transformer transformer; + try { + transformer = tFactory.newTransformer(new StreamSource(xslt)); + transformer.transform(new StreamSource(new StringReader(input)), new StreamResult(outStream)); + } catch (TransformerConfigurationException e) { + log.error("An error occurred in transformer", e); + throw new RuntimeException("Error Configuring XML Transformer:", e.getCause()); + } catch (TransformerException e) { + log.error("An error occurred in transformer", e); + throw new RuntimeException("Error Transforming XML:", e.getCause()); + } catch (Exception e) { + log.error("An error occurred in transformer", e); + } + result = outStream.toString(); + return result; + } - return transformerFactory; - } - - public DocumentBuilderFactory buildDocumentBuilderFactory() throws ParserConfigurationException { - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - documentBuilderFactory.setFeature(DISALLOW_DOCTYPE_DECL, true); - documentBuilderFactory.setFeature(EXTERNAL_GENERAL_ENTITIES, false); - documentBuilderFactory.setFeature(EXTERNAL_PARAMETER_ENTITIES, false); - documentBuilderFactory.setFeature(LOAD_EXTERNAL_DTD, false); - documentBuilderFactory.setXIncludeAware(false); - documentBuilderFactory.setExpandEntityReferences(false); - return documentBuilderFactory; - } - - public SAXParserFactory buildSaxParserFactory() throws SAXNotRecognizedException, SAXNotSupportedException, ParserConfigurationException { - SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); - saxParserFactory.setFeature(DISALLOW_DOCTYPE_DECL, true); - saxParserFactory.setFeature(EXTERNAL_GENERAL_ENTITIES, false); - saxParserFactory.setFeature(EXTERNAL_PARAMETER_ENTITIES, false); - saxParserFactory.setFeature(LOAD_EXTERNAL_DTD, false); - saxParserFactory.setXIncludeAware(false); - return saxParserFactory; - } - - public SchemaFactory buildSchemaFactory() throws SAXNotRecognizedException, SAXNotSupportedException { - SchemaFactory schemaFactory = SchemaFactory.newInstance(HTTP_WWW_W3_ORG_2001_XML_SCHEMA); - schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); - schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); - return schemaFactory; - } - - public XMLReader getXMLReader(SAXParser parser) throws SAXException { - XMLReader reader = parser.getXMLReader(); - reader.setFeature(DISALLOW_DOCTYPE_DECL, true); - reader.setFeature(LOAD_EXTERNAL_DTD, false); - reader.setFeature(EXTERNAL_GENERAL_ENTITIES, false); - reader.setFeature(EXTERNAL_PARAMETER_ENTITIES, false); - return reader; - } + /** + * Gets the xML resource. + * + * @param name the name + * @return the xML resource + */ + public String getXMLResource(String name) { + try { + return new ClassPathResource(name).getURL().toExternalForm(); + } catch (IOException e) { + log.error("An error occurred loading the resource [{}]: ", name, e); + } + return null; + } + + public TransformerFactory buildTransformerFactory() { + TransformerFactory transformerFactory = SAXTransformerFactory.newInstance(); + + try { + transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + } catch (IllegalArgumentException | TransformerConfigurationException e) { + /* see JDK-8015487, some parsers do not handle these attributes */ + } + + return transformerFactory; + } + + public DocumentBuilderFactory buildDocumentBuilderFactory() throws ParserConfigurationException { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setFeature(DISALLOW_DOCTYPE_DECL, true); + documentBuilderFactory.setFeature(EXTERNAL_GENERAL_ENTITIES, false); + documentBuilderFactory.setFeature(EXTERNAL_PARAMETER_ENTITIES, false); + documentBuilderFactory.setFeature(LOAD_EXTERNAL_DTD, false); + documentBuilderFactory.setXIncludeAware(false); + documentBuilderFactory.setExpandEntityReferences(false); + return documentBuilderFactory; + } + + public SAXParserFactory buildSaxParserFactory() + throws SAXNotRecognizedException, SAXNotSupportedException, ParserConfigurationException { + SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + saxParserFactory.setFeature(DISALLOW_DOCTYPE_DECL, true); + saxParserFactory.setFeature(EXTERNAL_GENERAL_ENTITIES, false); + saxParserFactory.setFeature(EXTERNAL_PARAMETER_ENTITIES, false); + saxParserFactory.setFeature(LOAD_EXTERNAL_DTD, false); + saxParserFactory.setXIncludeAware(false); + return saxParserFactory; + } + + public SchemaFactory buildSchemaFactory() + throws SAXNotRecognizedException, SAXNotSupportedException { + SchemaFactory schemaFactory = SchemaFactory.newInstance(HTTP_WWW_W3_ORG_2001_XML_SCHEMA); + schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + return schemaFactory; + } + + public XMLReader getXMLReader(SAXParser parser) throws SAXException { + XMLReader reader = parser.getXMLReader(); + reader.setFeature(DISALLOW_DOCTYPE_DECL, true); + reader.setFeature(LOAD_EXTERNAL_DTD, false); + reader.setFeature(EXTERNAL_GENERAL_ENTITIES, false); + reader.setFeature(EXTERNAL_PARAMETER_ENTITIES, false); + return reader; + } } diff --git a/src/main/java/gov/cms/madie/hqmf/XmlProcessor.java b/src/main/java/gov/cms/madie/hqmf/XmlProcessor.java index fcecbf0..ef1a29d 100644 --- a/src/main/java/gov/cms/madie/hqmf/XmlProcessor.java +++ b/src/main/java/gov/cms/madie/hqmf/XmlProcessor.java @@ -1,6 +1,5 @@ package gov.cms.madie.hqmf; - import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Document; @@ -38,1143 +37,1154 @@ @Slf4j public class XmlProcessor { - private static final String COHORT = "COHORT"; - private static final String XPATH_POPULATIONS = "/measure/populations"; - private static final String XPATH_NUMERATORS = "/measure/populations/numerators"; - private static final String XPATH_DENOMINATOR = "/measure/populations/denominators"; - private static final String XPATH_NUMERATOR_EXCLUSIONS = "/measure/populations/numeratorExclusions"; - private static final String XPATH_MEASURE_OBSERVATIONS = "/measure/measureObservations"; - private static final String XPATH_MEASURE_STRATIFICATIONS = "/measure/strata"; - private static final String XPATH_MEASURE_SD_ELEMENTS = "/measure/supplementalDataElements"; - private static final String XPATH_MEASURE_RAV_ELEMENTS = "/measure/riskAdjustmentVariables"; - private static final String XPATH_MEASURE_ELEMENT_LOOKUP = "/measure/elementLookUp"; - private static final String XPATH_MEASURE_SUBTREE_LOOKUP = "/measure/subTreeLookUp"; - private static final String XPATH_MEASURE_POPULATIONS = "/measure/populations/measurePopulations"; - private static final String XPATH_MEASURE_POPULATION_EXCLUSIONS = "/measure/populations/measurePopulationExclusions"; - private static final String XPATH_DENOMINATOR_EXCEPTIONS = "/measure/populations/denominatorExceptions"; - private static final String XPATH_DENOMINATOR_EXCLUSIONS = "/measure/populations/denominatorExclusions"; - private static final String RATIO = "RATIO"; - private static final String PROPORTION = "PROPORTION"; - private static final String CONTINUOUS_VARIABLE = "CONTINUOUS VARIABLE"; - private static final String NUMERATOR_EXCLUSIONS = "numeratorExclusions"; - private static final String DENOMINATOR_EXCEPTIONS = "denominatorExceptions"; - private static final String DENOMINATOR_EXCLUSIONS = "denominatorExclusions"; - private static final String DENOMINATORS = "denominators"; - private static final String NUMERATORS = "numerators"; - private static final String MEASURE_POPULATIONS = "measurePopulations"; - private static final String MEASURE_POPULATION_EXCLUSIONS = "measurePopulationExclusions"; - private static final String INITIAL_POPULATIONS = "initialPopulations"; - public static final String XPATH_MEASURE_CLAUSE = "/measure/populations/*/clause | /measure/*/clause | /measure/strata/stratification | /measure/strata/Stratification"; - public static final String XPATH_MEASURE_GROUPING = "/measure/measureGrouping"; - public static final String XPATH_MEASURE_GROUPING_GROUP = "/measure/measureGrouping/group"; - public static final String XPATH_GROUP_SEQ_START = "/measure/measureGrouping/group[@sequence = '"; - public static final String XPATH_GROUP_SEQ_END = "' ] "; - public static final String XPATH_FIND_GROUP_CLAUSE = "/measure/measureGrouping/group[packageClause["; - public static final String XPATH_OLD_ALL_RELATIONALOP_SBOD = "/measure//*/relationalOp[@type='SBOD']"; - public static final String XPATH_OLD_ALL_RELATIONALOP_EBOD = "/measure//*/relationalOp[@type='EBOD']"; - public static final String STRATIFICATION = "stratification"; - private static final String STRATIFICATION_DISPLAYNAME = "Stratification 1"; - private static final String MEASURE_OBSERVATION = "measureObservations"; - private static final String AND = "and"; - private static final String OR_STRING = "or"; - private static final String UUID_STRING = "uuid"; - private static final String DISPLAY_NAME = "displayName"; - private static final String TYPE = "type"; - private static final String PATIENT = " Patient "; - private static Map constantsMap = new HashMap(); - private static Map topNodeOperatorMap = new HashMap(); - private String originalXml; - private DocumentBuilder docBuilder; - private Document originalDoc; - private static final String PARAMETER_MEASUREMENT_PERIOD = "Measurement Period"; - private static final String XPATH_FOR_CODES = "//cqlLookUp/codes/code"; - private static final String XPATH_FOR_VALUESETS = "//cqlLookUp/valuesets/valueset"; - private static final String ATTRIBUTE_CODE_OID = "codeOID"; - private static final String ATTRIBUTE_CODE_NAME = "codeName"; - private static final String ATTRIBUTE_READ_ONLY = "readOnly"; - private static final String ATTRIBUTE_CODE_SYSTEM_OID = "codeSystemOID"; - private static final String[] POPULATIONS = { - INITIAL_POPULATIONS, NUMERATORS, NUMERATOR_EXCLUSIONS, DENOMINATORS, - DENOMINATOR_EXCLUSIONS, DENOMINATOR_EXCEPTIONS, MEASURE_POPULATIONS, - MEASURE_POPULATION_EXCLUSIONS}; - - static { - constantsMap.put("populations", "Populations"); - constantsMap.put(MEASURE_OBSERVATION, "Measure Observations"); - constantsMap.put("strata", "Stratification"); - constantsMap.put("initialPopulations", "Initial Populations"); - constantsMap.put("numerators", "Numerators"); - constantsMap.put("denominators", "Denominators"); - constantsMap.put("denominatorExclusions", "Denominator Exclusions"); - constantsMap.put("denominatorExceptions", "Denominator Exceptions"); - constantsMap.put("measurePopulations", "Measure Populations"); - constantsMap.put("measurePopulationExclusions", "Measure Population Exclusions"); - constantsMap.put("numeratorExclusions", "Numerator Exclusions"); - constantsMap.put("Measure Observations", "Measure Observation"); - constantsMap.put("Stratum", "Stratum"); - constantsMap.put("Initial Populations", "Initial Population"); - constantsMap.put("Numerators", "Numerator"); - constantsMap.put("Denominators", "Denominator"); - constantsMap.put("Denominator Exclusions", "Denominator Exclusions"); - constantsMap.put("Denominator Exceptions", "Denominator Exceptions"); - constantsMap.put("Measure Populations", "Measure Population"); - constantsMap.put("Measure Population Exclusions", "Measure Population Exclusions"); - constantsMap.put("Numerator Exclusions", "Numerator Exclusions"); - topNodeOperatorMap.put("initialPopulations", AND); - topNodeOperatorMap.put("numerators", AND); - topNodeOperatorMap.put("denominators", AND); - topNodeOperatorMap.put("measurePopulations", AND); - topNodeOperatorMap.put("denominatorExclusions", OR_STRING); - topNodeOperatorMap.put("numeratorExclusions", OR_STRING); - topNodeOperatorMap.put("denominatorExceptions", OR_STRING); - topNodeOperatorMap.put("measurePopulationExclusions", OR_STRING); + private static final String COHORT = "COHORT"; + private static final String XPATH_POPULATIONS = "/measure/populations"; + private static final String XPATH_NUMERATORS = "/measure/populations/numerators"; + private static final String XPATH_DENOMINATOR = "/measure/populations/denominators"; + private static final String XPATH_NUMERATOR_EXCLUSIONS = + "/measure/populations/numeratorExclusions"; + private static final String XPATH_MEASURE_OBSERVATIONS = "/measure/measureObservations"; + private static final String XPATH_MEASURE_STRATIFICATIONS = "/measure/strata"; + private static final String XPATH_MEASURE_SD_ELEMENTS = "/measure/supplementalDataElements"; + private static final String XPATH_MEASURE_RAV_ELEMENTS = "/measure/riskAdjustmentVariables"; + private static final String XPATH_MEASURE_ELEMENT_LOOKUP = "/measure/elementLookUp"; + private static final String XPATH_MEASURE_SUBTREE_LOOKUP = "/measure/subTreeLookUp"; + private static final String XPATH_MEASURE_POPULATIONS = "/measure/populations/measurePopulations"; + private static final String XPATH_MEASURE_POPULATION_EXCLUSIONS = + "/measure/populations/measurePopulationExclusions"; + private static final String XPATH_DENOMINATOR_EXCEPTIONS = + "/measure/populations/denominatorExceptions"; + private static final String XPATH_DENOMINATOR_EXCLUSIONS = + "/measure/populations/denominatorExclusions"; + private static final String RATIO = "RATIO"; + private static final String PROPORTION = "PROPORTION"; + private static final String CONTINUOUS_VARIABLE = "CONTINUOUS VARIABLE"; + private static final String NUMERATOR_EXCLUSIONS = "numeratorExclusions"; + private static final String DENOMINATOR_EXCEPTIONS = "denominatorExceptions"; + private static final String DENOMINATOR_EXCLUSIONS = "denominatorExclusions"; + private static final String DENOMINATORS = "denominators"; + private static final String NUMERATORS = "numerators"; + private static final String MEASURE_POPULATIONS = "measurePopulations"; + private static final String MEASURE_POPULATION_EXCLUSIONS = "measurePopulationExclusions"; + private static final String INITIAL_POPULATIONS = "initialPopulations"; + public static final String XPATH_MEASURE_CLAUSE = + "/measure/populations/*/clause | /measure/*/clause | /measure/strata/stratification | /measure/strata/Stratification"; + public static final String XPATH_MEASURE_GROUPING = "/measure/measureGrouping"; + public static final String XPATH_MEASURE_GROUPING_GROUP = "/measure/measureGrouping/group"; + public static final String XPATH_GROUP_SEQ_START = "/measure/measureGrouping/group[@sequence = '"; + public static final String XPATH_GROUP_SEQ_END = "' ] "; + public static final String XPATH_FIND_GROUP_CLAUSE = + "/measure/measureGrouping/group[packageClause["; + public static final String XPATH_OLD_ALL_RELATIONALOP_SBOD = + "/measure//*/relationalOp[@type='SBOD']"; + public static final String XPATH_OLD_ALL_RELATIONALOP_EBOD = + "/measure//*/relationalOp[@type='EBOD']"; + public static final String STRATIFICATION = "stratification"; + private static final String STRATIFICATION_DISPLAYNAME = "Stratification 1"; + private static final String MEASURE_OBSERVATION = "measureObservations"; + private static final String AND = "and"; + private static final String OR_STRING = "or"; + private static final String UUID_STRING = "uuid"; + private static final String DISPLAY_NAME = "displayName"; + private static final String TYPE = "type"; + private static final String PATIENT = " Patient "; + private static Map constantsMap = new HashMap(); + private static Map topNodeOperatorMap = new HashMap(); + private String originalXml; + private DocumentBuilder docBuilder; + private Document originalDoc; + private static final String PARAMETER_MEASUREMENT_PERIOD = "Measurement Period"; + private static final String XPATH_FOR_CODES = "//cqlLookUp/codes/code"; + private static final String XPATH_FOR_VALUESETS = "//cqlLookUp/valuesets/valueset"; + private static final String ATTRIBUTE_CODE_OID = "codeOID"; + private static final String ATTRIBUTE_CODE_NAME = "codeName"; + private static final String ATTRIBUTE_READ_ONLY = "readOnly"; + private static final String ATTRIBUTE_CODE_SYSTEM_OID = "codeSystemOID"; + private static final String[] POPULATIONS = { + INITIAL_POPULATIONS, + NUMERATORS, + NUMERATOR_EXCLUSIONS, + DENOMINATORS, + DENOMINATOR_EXCLUSIONS, + DENOMINATOR_EXCEPTIONS, + MEASURE_POPULATIONS, + MEASURE_POPULATION_EXCLUSIONS + }; + + static { + constantsMap.put("populations", "Populations"); + constantsMap.put(MEASURE_OBSERVATION, "Measure Observations"); + constantsMap.put("strata", "Stratification"); + constantsMap.put("initialPopulations", "Initial Populations"); + constantsMap.put("numerators", "Numerators"); + constantsMap.put("denominators", "Denominators"); + constantsMap.put("denominatorExclusions", "Denominator Exclusions"); + constantsMap.put("denominatorExceptions", "Denominator Exceptions"); + constantsMap.put("measurePopulations", "Measure Populations"); + constantsMap.put("measurePopulationExclusions", "Measure Population Exclusions"); + constantsMap.put("numeratorExclusions", "Numerator Exclusions"); + constantsMap.put("Measure Observations", "Measure Observation"); + constantsMap.put("Stratum", "Stratum"); + constantsMap.put("Initial Populations", "Initial Population"); + constantsMap.put("Numerators", "Numerator"); + constantsMap.put("Denominators", "Denominator"); + constantsMap.put("Denominator Exclusions", "Denominator Exclusions"); + constantsMap.put("Denominator Exceptions", "Denominator Exceptions"); + constantsMap.put("Measure Populations", "Measure Population"); + constantsMap.put("Measure Population Exclusions", "Measure Population Exclusions"); + constantsMap.put("Numerator Exclusions", "Numerator Exclusions"); + topNodeOperatorMap.put("initialPopulations", AND); + topNodeOperatorMap.put("numerators", AND); + topNodeOperatorMap.put("denominators", AND); + topNodeOperatorMap.put("measurePopulations", AND); + topNodeOperatorMap.put("denominatorExclusions", OR_STRING); + topNodeOperatorMap.put("numeratorExclusions", OR_STRING); + topNodeOperatorMap.put("denominatorExceptions", OR_STRING); + topNodeOperatorMap.put("measurePopulationExclusions", OR_STRING); + } + + /** + * Instantiates a new xml processor. + * + * @param originalXml the original xml + */ + public XmlProcessor(String originalXml) { + log.debug("In XmlProcessor() constructor"); + this.originalXml = originalXml; + try { + DocumentBuilderFactory documentBuilderFactory = + XMLUtility.getInstance().buildDocumentBuilderFactory(); + docBuilder = documentBuilderFactory.newDocumentBuilder(); + InputSource oldXmlstream = new InputSource(new StringReader(originalXml)); + originalDoc = docBuilder.parse(oldXmlstream); + log.debug("Document Object created successfully for the XML String"); + } catch (Exception e) { + log.error("Exception thrown on XmlProcessor() constructor", e); + caughtExceptions(e); } - - /** - * Instantiates a new xml processor. - * - * @param originalXml the original xml - */ - public XmlProcessor(String originalXml) { - log.debug("In XmlProcessor() constructor"); - this.originalXml = originalXml; - try { - DocumentBuilderFactory documentBuilderFactory = XMLUtility.getInstance().buildDocumentBuilderFactory(); - docBuilder = documentBuilderFactory.newDocumentBuilder(); - InputSource oldXmlstream = new InputSource(new StringReader(originalXml)); - originalDoc = docBuilder.parse(oldXmlstream); - log.debug("Document Object created successfully for the XML String"); - } catch (Exception e) { - log.error("Exception thrown on XmlProcessor() constructor",e); - caughtExceptions(e); - } - + } + + /** + * Instantiates a new xml processor for HQMFMeasureXml. + * + * @param file the file + */ + public XmlProcessor(File file) { + try { + DocumentBuilderFactory documentBuilderFactory = + XMLUtility.getInstance().buildDocumentBuilderFactory(); + docBuilder = documentBuilderFactory.newDocumentBuilder(); + originalDoc = docBuilder.parse(file); + log.debug("Document Object created successfully for the XML String"); + } catch (ParserConfigurationException e) { + log.error("Exception thrown on XmlProcessor() constructor", e); + } catch (SAXException e) { + log.error("Exception thrown on XmlProcessor() constructor", e); + } catch (IOException e) { + log.debug("Exception thrown on XmlProcessor() constructor", e); + caughtExceptions(e); } - - /** - * Instantiates a new xml processor for HQMFMeasureXml. - * - * @param file the file - */ - public XmlProcessor(File file) { - try { - DocumentBuilderFactory documentBuilderFactory = XMLUtility.getInstance().buildDocumentBuilderFactory(); - docBuilder = documentBuilderFactory.newDocumentBuilder(); - originalDoc = docBuilder.parse(file); - log.debug("Document Object created successfully for the XML String"); - } catch (ParserConfigurationException e) { - log.error("Exception thrown on XmlProcessor() constructor", e); - } catch (SAXException e) { - log.error("Exception thrown on XmlProcessor() constructor", e); - } catch (IOException e) { - log.debug("Exception thrown on XmlProcessor() constructor", e); - caughtExceptions(e); + } + + /** + * Method to insert new Node under existing parent Node. + * + * @param newElement the new element + * @param nodeName the node name + * @param parentNode the parent node + * @return the string + * @throws SAXException the sAX exception + * @throws IOException Signals that an I/O exception has occurred. + */ + public String appendNode(String newElement, String nodeName, String parentNode) + throws SAXException, IOException { + log.debug("In appendNode method with newElement ::: "); + if ((originalDoc == null) || (newElement == null)) { + return ""; + } + try { + Node parentTypeNode = findNode(originalDoc, parentNode); + if (parentTypeNode != null) { + InputSource newXmlstream = new InputSource(new StringReader(newElement)); + // Parse the NewXml which should be replaced. + Document newDoc = docBuilder.parse(newXmlstream); + NodeList newNodeList = newDoc.getElementsByTagName(nodeName); + for (int i = 0; i < newNodeList.getLength(); i++) { + Node newNode = newNodeList.item(i); + parentTypeNode.appendChild(originalDoc.importNode(newNode, true)); } + log.debug("Document Object created successfully for the XML String."); + } else { + log.debug( + "parentNode:" + parentNode + " not found. method appendNode exiting prematurely."); + } + } catch (XPathExpressionException e) { + log.debug("Exception thrown on appendNode method"); + caughtExceptions(e); } - - /** - * Method to insert new Node under existing parent Node. - * - * @param newElement the new element - * @param nodeName the node name - * @param parentNode the parent node - * @return the string - * @throws SAXException the sAX exception - * @throws IOException Signals that an I/O exception has occurred. - */ - public String appendNode(String newElement, String nodeName, - String parentNode) throws SAXException, IOException { - log.debug("In appendNode method with newElement ::: "); - if ((originalDoc == null) || (newElement == null)) { - return ""; - } - try { - Node parentTypeNode = findNode(originalDoc, parentNode); - if (parentTypeNode != null) { - InputSource newXmlstream = new InputSource(new StringReader( - newElement)); - // Parse the NewXml which should be replaced. - Document newDoc = docBuilder.parse(newXmlstream); - NodeList newNodeList = newDoc.getElementsByTagName(nodeName); - for (int i = 0; i < newNodeList.getLength(); i++) { - Node newNode = newNodeList.item(i); - parentTypeNode.appendChild(originalDoc.importNode(newNode, - true)); - } - - log.debug("Document Object created successfully for the XML String."); - } else { - log.debug("parentNode:" + parentNode - + " not found. method appendNode exiting prematurely."); + return transform(originalDoc); + } + + /** + * Method with Replace/Insert Node into the Original Xml ------- REPLACE ----- Example NewXml - + * new text OldXml - old Text Result - new + * text ------- INSERT ------ Example NewXml - new text OldXml - + * first Result - firstnew text. + * + * @param newXml the new xml + * @param nodeName the node name + * @param parentName // this is optional, can be null or empty. if parentName not null, the + * oldNode to be replaced will be retrieved based on the parent Node, this is done to make + * sure we are replacing the correct node. + * @return the string + */ + public String replaceNode(String newXml, String nodeName, String parentName) { + try { + log.debug("In replaceNode() method"); + InputSource newXmlstream = new InputSource(new StringReader(newXml)); + Document newDoc = docBuilder.parse(newXmlstream); // Parse the NewXml + // which should + // be replaced + Node newNode = null; + Node oldNode = null; + NodeList newNodeList = newDoc.getElementsByTagName(nodeName); + NodeList oldNodeList = originalDoc.getElementsByTagName(nodeName); + if (oldNodeList.getLength() > 0) { + if (StringUtils.isBlank(parentName)) { + oldNode = oldNodeList.item(0); + } else { + for (int i = 0; i < oldNodeList.getLength(); i++) { + if (parentName.equals( + oldNodeList.item(i).getParentNode().getNodeName())) { // get the old + // node with + // the + // matching + // Parent + // Node. + oldNode = oldNodeList.item(i); + break; } - } catch (XPathExpressionException e) { - log.debug("Exception thrown on appendNode method"); - caughtExceptions(e); + } + } + } + if (newNodeList.getLength() > 0) { + newNode = newNodeList.item(0); + for (int i = 0; i < newNodeList.getLength(); i++) { + if (parentName.equals( + newNodeList.item(i).getParentNode().getNodeName())) { // get the new node used to + // replace. + newNode = newNodeList.item(i); + break; + } + } + if (oldNode != null) { // check if the OriginalXml has the Node + // that should be replaced + Node nextSibling = oldNode.getNextSibling(); + Node parentNode = oldNode.getParentNode(); + parentNode.removeChild(oldNode); // Removing the old child + // node + if (nextSibling != null) { + // to maintain the order insert before the next sibling if exists + parentNode.insertBefore(originalDoc.importNode(newNode, true), nextSibling); + } else { + parentNode.appendChild( + originalDoc.importNode(newNode, true)); // insert the new child node to the old + // child's Parent node,. + } + log.debug("Replaced old Child Node with new Child Node " + nodeName); + } else { // if the Original Document doesnt have the Node, then + // insert the new Node under the first child + Node importNode = originalDoc.importNode(newNode, true); + originalDoc.getFirstChild().appendChild(importNode); + log.debug("Inserted new Child Node" + nodeName); } return transform(originalDoc); - } + } - /** - * Method with Replace/Insert Node into the Original Xml ------- REPLACE - * ----- Example NewXml - new text OldXml - old - * Text Result - new text ------- INSERT - * ------ Example NewXml - new text OldXml - - * first Result - firstnew - * text. - * - * @param newXml the new xml - * @param nodeName the node name - * @param parentName // this is optional, can be null or empty. if parentName not - * null, the oldNode to be replaced will be retrieved based on - * the parent Node, this is done to make sure we are replacing - * the correct node. - * @return the string - */ - public String replaceNode(String newXml, String nodeName, String parentName) { - try { - log.debug("In replaceNode() method"); - InputSource newXmlstream = new InputSource(new StringReader(newXml)); - Document newDoc = docBuilder.parse(newXmlstream); // Parse the NewXml - // which should - // be replaced - Node newNode = null; - Node oldNode = null; - NodeList newNodeList = newDoc.getElementsByTagName(nodeName); - NodeList oldNodeList = originalDoc.getElementsByTagName(nodeName); - if (oldNodeList.getLength() > 0) { - if (StringUtils.isBlank(parentName)) { - oldNode = oldNodeList.item(0); - } else { - for (int i = 0; i < oldNodeList.getLength(); i++) { - if (parentName.equals(oldNodeList.item(i) - .getParentNode().getNodeName())) { // get the old - // node with - // the - // matching - // Parent - // Node. - oldNode = oldNodeList.item(i); - break; - } - } - } - } - if (newNodeList.getLength() > 0) { - newNode = newNodeList.item(0); - for (int i = 0; i < newNodeList.getLength(); i++) { - if (parentName.equals(newNodeList.item(i).getParentNode() - .getNodeName())) { // get the new node used to - // replace. - newNode = newNodeList.item(i); - break; - } - } - if (oldNode != null) { // check if the OriginalXml has the Node - // that should be replaced - Node nextSibling = oldNode.getNextSibling(); - Node parentNode = oldNode.getParentNode(); - parentNode.removeChild(oldNode); // Removing the old child - // node - if (nextSibling != null) { - // to maintain the order insert before the next sibling if exists - parentNode.insertBefore( - originalDoc.importNode(newNode, true), - nextSibling); - } else { - parentNode.appendChild(originalDoc.importNode(newNode, - true)); // insert the new child node to the old - // child's Parent node,. - } - log.debug("Replaced old Child Node with new Child Node " - + nodeName); - } else { // if the Original Document doesnt have the Node, then - // insert the new Node under the first child - Node importNode = originalDoc.importNode(newNode, true); - originalDoc.getFirstChild().appendChild(importNode); - log.debug("Inserted new Child Node" + nodeName); - } - return transform(originalDoc); - } - - } catch (Exception e) { - log.debug("Exception thrown on replaceNode() method", e); - caughtExceptions(e); - } - return originalXml; // not replaced returnig the original Xml; + } catch (Exception e) { + log.debug("Exception thrown on replaceNode() method", e); + caughtExceptions(e); } - - /** - * Update node text. - * - * @param nodeName the node name - * @param nodeValue the node value - * @return the string - */ - public String updateNodeText(String nodeName, String nodeValue) { - try { - log.debug("In updateNodeText() method"); - InputSource xmlStream = new InputSource(new StringReader( - originalXml)); - Document doc = docBuilder.parse(xmlStream); - doc.getElementsByTagName(nodeName).item(0).setTextContent(nodeValue); - log.debug("update NoedText"); - return transform(doc); - } catch (Exception e) { - log.error("Exception thrown on updateNodeText() method", e); - caughtExceptions(e); - } - return null; + return originalXml; // not replaced returnig the original Xml; + } + + /** + * Update node text. + * + * @param nodeName the node name + * @param nodeValue the node value + * @return the string + */ + public String updateNodeText(String nodeName, String nodeValue) { + try { + log.debug("In updateNodeText() method"); + InputSource xmlStream = new InputSource(new StringReader(originalXml)); + Document doc = docBuilder.parse(xmlStream); + doc.getElementsByTagName(nodeName).item(0).setTextContent(nodeValue); + log.debug("update NoedText"); + return transform(doc); + } catch (Exception e) { + log.error("Exception thrown on updateNodeText() method", e); + caughtExceptions(e); } - - /** - * Gets the original xml. - * - * @return the original xml - */ - public String getOriginalXml() { - return originalXml; + return null; + } + + /** + * Gets the original xml. + * + * @return the original xml + */ + public String getOriginalXml() { + return originalXml; + } + + /** + * Sets the original xml. + * + * @param originalXml the new original xml + */ + public void setOriginalXml(String originalXml) { + this.originalXml = originalXml; + } + + /** + * Gets the xml by tag name. + * + * @param tagName the tag name + * @return the xml by tag name + */ + public String getXmlByTagName(String tagName) { + String returnVar = null; + Node node = + originalDoc.getElementsByTagName(tagName).getLength() > 0 + ? originalDoc.getElementsByTagName(tagName).item(0) + : null; + if (null != node) { + returnVar = transform(node); } - - /** - * Sets the original xml. - * - * @param originalXml the new original xml - */ - public void setOriginalXml(String originalXml) { - this.originalXml = originalXml; + return returnVar; + } + + /** + * Adds the parent node. + * + * @param parentTagName the parent tag name + */ + public void addParentNode(String parentTagName) { + if (originalDoc.hasChildNodes()) { + Document newDoc = docBuilder.newDocument(); + Node parentNode = newDoc.appendChild(newDoc.createElement(parentTagName)); + Node importedNode = newDoc.importNode(originalDoc.getFirstChild(), true); + parentNode.appendChild(importedNode); + originalDoc = newDoc; } - - /** - * Gets the xml by tag name. - * - * @param tagName the tag name - * @return the xml by tag name - */ - public String getXmlByTagName(String tagName) { - String returnVar = null; - Node node = originalDoc.getElementsByTagName(tagName).getLength() > 0 ? originalDoc - .getElementsByTagName(tagName).item(0) : null; - if (null != node) { - returnVar = transform(node); - } - return returnVar; + } + + /** + * Caught exceptions. + * + * @param excp the exception that was caught + */ + private void caughtExceptions(Exception excp) { + if (excp instanceof ParserConfigurationException) { + log.error("Document Builder Object creation failed:" + excp.getMessage(), excp); + } else if (excp instanceof SAXException) { + log.error("Xml parsing failed:" + excp.getMessage(), excp); + } else if (excp instanceof IOException) { + log.error("Conversion of String XML to InputSource failed" + excp.getMessage(), excp); + } else { + log.error("Generic Exception: " + excp.getMessage(), excp); } - - /** - * Adds the parent node. - * - * @param parentTagName the parent tag name - */ - public void addParentNode(String parentTagName) { - if (originalDoc.hasChildNodes()) { - Document newDoc = docBuilder.newDocument(); - Node parentNode = newDoc.appendChild(newDoc - .createElement(parentTagName)); - Node importedNode = newDoc.importNode(originalDoc.getFirstChild(), - true); - parentNode.appendChild(importedNode); - originalDoc = newDoc; - } + } + + /** + * Check for scoring type. + * + * @return the string + */ + public String checkForScoringType(String scoringType) { + if (originalDoc == null) { + return ""; } - - /** - * Caught exceptions. - * - * @param excp the exception that was caught - */ - private void caughtExceptions(Exception excp) { - if (excp instanceof ParserConfigurationException) { - log.error("Document Builder Object creation failed:" + excp.getMessage(), excp); - } else if (excp instanceof SAXException) { - log.error("Xml parsing failed:" + excp.getMessage(), excp); - } else if (excp instanceof IOException) { - log.error("Conversion of String XML to InputSource failed" + excp.getMessage(), excp); - } else { - log.error("Generic Exception: " + excp.getMessage(), excp); - } + try { + removeNodesBasedOnScoring(scoringType); + createNewNodesBasedOnScoring(scoringType); + } catch (XPathExpressionException e) { + log.error(e.getMessage(), e); } - - /** - * Check for scoring type. - * - * @return the string - */ - public String checkForScoringType(String scoringType) { - if (originalDoc == null) { - return ""; - } - try { - removeNodesBasedOnScoring(scoringType); - createNewNodesBasedOnScoring(scoringType); - } catch (XPathExpressionException e) { - log.error(e.getMessage(), e); - } - return transform(originalDoc); + return transform(originalDoc); + } + + /** + * This method looks at the Scoring Type for a measure and removes nodes based on the value of + * Scoring Type. + * + * @param scoringType the scoring type + * @throws XPathExpressionException the x path expression exception + */ + public void removeNodesBasedOnScoring(String scoringType) throws XPathExpressionException { + List xPathList = new ArrayList(); + + if (RATIO.equalsIgnoreCase(scoringType)) { + // Denominator Exceptions, Measure Populations + xPathList.add(XPATH_DENOMINATOR_EXCEPTIONS); + xPathList.add(XPATH_MEASURE_POPULATIONS); + xPathList.add(XPATH_MEASURE_POPULATION_EXCLUSIONS); + } else if (PROPORTION.equalsIgnoreCase(scoringType)) { + // Measure Population Exlusions, Measure Populations + xPathList.add(XPATH_MEASURE_POPULATIONS); + xPathList.add(XPATH_MEASURE_POPULATION_EXCLUSIONS); + xPathList.add(XPATH_MEASURE_OBSERVATIONS); + } else if (CONTINUOUS_VARIABLE.equalsIgnoreCase(scoringType)) { + // Numerators,Numerator Exclusions, Denominators, Denominator + // Exceptions, Denominator Exclusions + xPathList.add(XPATH_NUMERATORS); + xPathList.add(XPATH_NUMERATOR_EXCLUSIONS); + xPathList.add(XPATH_DENOMINATOR); + xPathList.add(XPATH_DENOMINATOR_EXCEPTIONS); + xPathList.add(XPATH_DENOMINATOR_EXCLUSIONS); + } else if (COHORT.equalsIgnoreCase(scoringType)) { + xPathList.add(XPATH_NUMERATORS); + xPathList.add(XPATH_NUMERATOR_EXCLUSIONS); + xPathList.add(XPATH_DENOMINATOR); + xPathList.add(XPATH_DENOMINATOR_EXCEPTIONS); + xPathList.add(XPATH_DENOMINATOR_EXCLUSIONS); + xPathList.add(XPATH_MEASURE_POPULATIONS); + xPathList.add(XPATH_MEASURE_POPULATION_EXCLUSIONS); + xPathList.add(XPATH_MEASURE_OBSERVATIONS); } - - /** - * This method looks at the Scoring Type for a measure and removes nodes - * based on the value of Scoring Type. - * - * @param scoringType the scoring type - * @throws XPathExpressionException the x path expression exception - */ - public void removeNodesBasedOnScoring(String scoringType) throws XPathExpressionException { - List xPathList = new ArrayList(); - - if (RATIO.equalsIgnoreCase(scoringType)) { - // Denominator Exceptions, Measure Populations - xPathList.add(XPATH_DENOMINATOR_EXCEPTIONS); - xPathList.add(XPATH_MEASURE_POPULATIONS); - xPathList.add(XPATH_MEASURE_POPULATION_EXCLUSIONS); - } else if (PROPORTION.equalsIgnoreCase(scoringType)) { - // Measure Population Exlusions, Measure Populations - xPathList.add(XPATH_MEASURE_POPULATIONS); - xPathList.add(XPATH_MEASURE_POPULATION_EXCLUSIONS); - xPathList.add(XPATH_MEASURE_OBSERVATIONS); - } else if (CONTINUOUS_VARIABLE.equalsIgnoreCase(scoringType)) { - // Numerators,Numerator Exclusions, Denominators, Denominator - // Exceptions, Denominator Exclusions - xPathList.add(XPATH_NUMERATORS); - xPathList.add(XPATH_NUMERATOR_EXCLUSIONS); - xPathList.add(XPATH_DENOMINATOR); - xPathList.add(XPATH_DENOMINATOR_EXCEPTIONS); - xPathList.add(XPATH_DENOMINATOR_EXCLUSIONS); - } else if (COHORT.equalsIgnoreCase(scoringType)) { - xPathList.add(XPATH_NUMERATORS); - xPathList.add(XPATH_NUMERATOR_EXCLUSIONS); - xPathList.add(XPATH_DENOMINATOR); - xPathList.add(XPATH_DENOMINATOR_EXCEPTIONS); - xPathList.add(XPATH_DENOMINATOR_EXCLUSIONS); - xPathList.add(XPATH_MEASURE_POPULATIONS); - xPathList.add(XPATH_MEASURE_POPULATION_EXCLUSIONS); - xPathList.add(XPATH_MEASURE_OBSERVATIONS); - } - for (String xPathString : xPathList) { - Node node = findNode(originalDoc, xPathString); - removeFromParent(node); - } + for (String xPathString : xPathList) { + Node node = findNode(originalDoc, xPathString); + removeFromParent(node); } - - /** - * Rename ip p_ to_ ip. - * - * @param document the document - * @throws XPathExpressionException the x path expression exception - */ - public void renameIPPToIP(Document document) throws XPathExpressionException { - String clause = "clause"; - String initialPopulation = "initialPopulation"; - String initialPatientPopulation = "initialPatientPopulation"; - String xpathOldInitPatientPop = "/measure/populations/initialPatientPopulations"; - String xpathOldGroupingPackageClause = "/measure/measureGrouping/*/packageClause"; - - if (document == null) { - return; - } - - //Find and Replace IPP to IP in measureGrouping/group/packageClause. - javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); - NodeList nodesPackageClauses = (NodeList) xPath.evaluate(xpathOldGroupingPackageClause, - originalDoc.getDocumentElement(), XPathConstants.NODESET); - - for (int i = 0; i < nodesPackageClauses.getLength(); i++) { - Node childNode = nodesPackageClauses.item(i); - String packageClauseType = childNode.getAttributes().getNamedItem(TYPE).getNodeValue(); - String packageClauseName = childNode.getAttributes().getNamedItem("name").getNodeValue(); - if (packageClauseType.equalsIgnoreCase(initialPatientPopulation)) { - childNode.getAttributes().getNamedItem(TYPE).setNodeValue(initialPopulation); - if (packageClauseName.indexOf(PATIENT) > 0) { - packageClauseName = packageClauseName.replaceAll(PATIENT, " "); - } - childNode.getAttributes().getNamedItem("name").setNodeValue(packageClauseName); - } - } - - //find initialPatientPopulations tag - Node initialPopulationsNode = findNode(document, xpathOldInitPatientPop); - if (initialPopulationsNode == null) { - return; - } - - //Also change the value of the 'displayName' attribute - initialPopulationsNode.getAttributes().getNamedItem(DISPLAY_NAME).setNodeValue("Initial Populations"); - - //within 'initialPopulations' tag, for all 'clause' tags, rename the 'displayName' attribute - //from 'Initial Patient Population 1' to 'Initial Population 1'. - //Also change 'type' attribute to 'initialPopulation' - NodeList childNodes = initialPopulationsNode.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node childNode = childNodes.item(i); - if (clause.equals(childNode.getNodeName())) { - childNode.getAttributes().getNamedItem(TYPE).setNodeValue(initialPopulation); - - String clauseDisplayName = childNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - if (clauseDisplayName.indexOf(PATIENT) > 0) { - clauseDisplayName = clauseDisplayName.replaceAll(PATIENT, " "); - } - childNode.getAttributes().getNamedItem(DISPLAY_NAME).setNodeValue(clauseDisplayName); - } - } - - //rename 'initialPatientPopulations' to 'initialPopulations'. - document.renameNode(initialPopulationsNode, "", INITIAL_POPULATIONS); + } + + /** + * Rename ip p_ to_ ip. + * + * @param document the document + * @throws XPathExpressionException the x path expression exception + */ + public void renameIPPToIP(Document document) throws XPathExpressionException { + String clause = "clause"; + String initialPopulation = "initialPopulation"; + String initialPatientPopulation = "initialPatientPopulation"; + String xpathOldInitPatientPop = "/measure/populations/initialPatientPopulations"; + String xpathOldGroupingPackageClause = "/measure/measureGrouping/*/packageClause"; + + if (document == null) { + return; } - /** - * Rename timing conventions. - * - * @param document the document - * @throws XPathExpressionException the x path expression exception - */ - public void renameTimingConventions(Document document) throws XPathExpressionException { - String startsBeforeOrDuring = "Starts Before Or During"; - String endsBeforeOrDuring = "Ends Before Or During"; - String startBeforeEnd = "Starts Before End"; - String endsBeforeEnd = "Ends Before End"; - String sBE = "SBE"; - String eBE = "EBE"; - javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); - //replace relationalOp attribute values for displayName and type from SBOD to SBE - NodeList nodesRelationalOpsSBOD = (NodeList) xPath.evaluate(XPATH_OLD_ALL_RELATIONALOP_SBOD, - originalDoc.getDocumentElement(), XPathConstants.NODESET); - for (int i = 0; i < nodesRelationalOpsSBOD.getLength(); i++) { - Node childNode = nodesRelationalOpsSBOD.item(i); - String relationalOpDisplayName = childNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - relationalOpDisplayName = relationalOpDisplayName.replace(startsBeforeOrDuring, startBeforeEnd); - childNode.getAttributes().getNamedItem(DISPLAY_NAME).setNodeValue(relationalOpDisplayName); - childNode.getAttributes().getNamedItem(TYPE).setNodeValue(sBE); - } - //replace relationalOp attribute values for displayName and type from EBOD to EBE - NodeList nodesRelationalOpsEBOD = (NodeList) xPath.evaluate(XPATH_OLD_ALL_RELATIONALOP_EBOD, - originalDoc.getDocumentElement(), XPathConstants.NODESET); - for (int i = 0; i < nodesRelationalOpsEBOD.getLength(); i++) { - Node childNode = nodesRelationalOpsEBOD.item(i); - String relationalOpDisplayName = childNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - relationalOpDisplayName = relationalOpDisplayName.replace(endsBeforeOrDuring, endsBeforeEnd); - childNode.getAttributes().getNamedItem(DISPLAY_NAME).setNodeValue(relationalOpDisplayName); - childNode.getAttributes().getNamedItem(TYPE).setNodeValue(eBE); + // Find and Replace IPP to IP in measureGrouping/group/packageClause. + javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); + NodeList nodesPackageClauses = + (NodeList) + xPath.evaluate( + xpathOldGroupingPackageClause, + originalDoc.getDocumentElement(), + XPathConstants.NODESET); + + for (int i = 0; i < nodesPackageClauses.getLength(); i++) { + Node childNode = nodesPackageClauses.item(i); + String packageClauseType = childNode.getAttributes().getNamedItem(TYPE).getNodeValue(); + String packageClauseName = childNode.getAttributes().getNamedItem("name").getNodeValue(); + if (packageClauseType.equalsIgnoreCase(initialPatientPopulation)) { + childNode.getAttributes().getNamedItem(TYPE).setNodeValue(initialPopulation); + if (packageClauseName.indexOf(PATIENT) > 0) { + packageClauseName = packageClauseName.replaceAll(PATIENT, " "); } + childNode.getAttributes().getNamedItem("name").setNodeValue(packageClauseName); + } } - - /** - * This method looks at the Scoring Type for a measure and adds nodes based - * on the value of Scoring Type. - * - * @param scoringType the scoring type - * @throws XPathExpressionException the x path expression exception - */ - public void createNewNodesBasedOnScoring(String scoringType) - throws XPathExpressionException { - List scoreBasedNodes = retrieveScoreBasedNodes(scoringType); - Node populationsNode = findNode(originalDoc, XPATH_POPULATIONS); - - if (populationsNode == null) { - populationsNode = addPopulationsNode(); - } - boolean childAppended = calculateChildAppend(scoreBasedNodes, - populationsNode); - /** - * Add Measure Observations node after Populations node if not present - * and scoring type is Continuous Variable. - */ - Node measureObservationsNode = findNode(originalDoc, XPATH_MEASURE_OBSERVATIONS); - if ((CONTINUOUS_VARIABLE.equalsIgnoreCase(scoringType) || RATIO.equalsIgnoreCase(scoringType)) - && (measureObservationsNode == null)) { - // Create a new measureObservations element. - String nodeName = MEASURE_OBSERVATION; - String displayName = constantsMap.get(nodeName); - Element mainChildElem = createTemplateNode(nodeName, - displayName); - measureObservationsNode = mainChildElem; - // insert measureObservations element after populations element - Node measureNode = populationsNode.getParentNode(); - Element measureElement = (Element) measureNode; - measureElement.insertBefore(mainChildElem, - populationsNode.getNextSibling()); - } - // Create stratifications node - Node measureStratificationsNode = findNode(originalDoc, - XPATH_MEASURE_STRATIFICATIONS); - if (measureStratificationsNode == null && !RATIO.equalsIgnoreCase(scoringType)) { - String stratificationsNodeName = "strata"; - String clauseDisplayName = "Stratum"; - Element stratificationElement = createTemplateNode( - stratificationsNodeName, clauseDisplayName); - - NodeList childs = stratificationElement.getChildNodes(); - Element stratificationEle = originalDoc - .createElement(STRATIFICATION); - stratificationEle.setAttribute(DISPLAY_NAME, STRATIFICATION_DISPLAYNAME); - stratificationEle.setAttribute(UUID_STRING, UUID.randomUUID().toString()); - stratificationEle.setAttribute(TYPE, STRATIFICATION); - List nCList = new ArrayList(); - for (int i = 0; i < childs.getLength(); i++) { - nCList.add(childs.item(i)); - stratificationElement.removeChild(childs.item(i)); - } - for (Node cNode : nCList) { - stratificationEle.appendChild(cNode); - } - stratificationElement.appendChild(stratificationEle); - - measureStratificationsNode = stratificationElement; - // insert measureObservations element after populations element - Node measureNode = populationsNode.getParentNode(); - Element measureElement = (Element) measureNode; - if (measureObservationsNode != null) { - measureElement.insertBefore(stratificationElement, - measureObservationsNode.getNextSibling()); - } else { - measureElement.insertBefore(stratificationElement, - populationsNode.getNextSibling()); - } - } else if (measureStratificationsNode != null && RATIO.equalsIgnoreCase(scoringType)) { - Node measureNode = measureStratificationsNode.getParentNode(); - Element measureElement = (Element) measureNode; - - measureElement.removeChild(measureStratificationsNode); - } - // Create supplementalDataElements node - createSupplementalDataElementNode(measureStratificationsNode); - /* - * All the adding and removing can put the children of 'populations' in - * a random order. Arrange the population nodes in correct order.*/ - // If no children have been appended, dont go through the process of - // re-arranging the - // populations node children. - if (!childAppended) { - return; - } - // remove all the child nodes of populations node first - NodeList childNodes = populationsNode.getChildNodes(); - List childNodesList = new ArrayList(); - for (int c = 0; c < childNodes.getLength(); c++) { - childNodesList.add(childNodes.item(c)); - } - for (int i = 0; i < childNodesList.size(); i++) { - populationsNode - .removeChild(populationsNode.getChildNodes().item(0)); - } - arrangeChildNodeList(populationsNode, childNodesList); - + // find initialPatientPopulations tag + Node initialPopulationsNode = findNode(document, xpathOldInitPatientPop); + if (initialPopulationsNode == null) { + return; } - /** - * Take the child nodeList & re-arrange it according to this order - * "Initial Patient Populations", "Numerators", "Numerator Exclusions", - * "Denominators", "Denominator Exclusions", - * "Denominator Exceptions", "Measure Populations", "Measure Population Exclusions". - * - * @param populationsNode the population node - * @param childNodesList array list of nodes to be ordered - */ - private void arrangeChildNodeList(Node populationsNode, - List childNodesList) { - // Take the child nodeList & re-arrange it according to this order - // "Initial Patient Populations", "Numerators", "Numerator Exclusions", - // "Denominators", "Denominator Exclusions", - // "Denominator Exceptions", "Measure Populations", "Measure Population Exclusions" - for (String populationsChild : XmlProcessor.POPULATIONS) { - Node populationsChildNode = null; - for (int j = 0; j < childNodesList.size(); j++) { - Node child = childNodesList.get(j); - if (child.getNodeName().equals(populationsChild)) { - populationsChildNode = child; - break; - } - } - if (populationsChildNode != null) { - populationsNode.appendChild(populationsChildNode); - } + // Also change the value of the 'displayName' attribute + initialPopulationsNode + .getAttributes() + .getNamedItem(DISPLAY_NAME) + .setNodeValue("Initial Populations"); + + // within 'initialPopulations' tag, for all 'clause' tags, rename the 'displayName' attribute + // from 'Initial Patient Population 1' to 'Initial Population 1'. + // Also change 'type' attribute to 'initialPopulation' + NodeList childNodes = initialPopulationsNode.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node childNode = childNodes.item(i); + if (clause.equals(childNode.getNodeName())) { + childNode.getAttributes().getNamedItem(TYPE).setNodeValue(initialPopulation); + + String clauseDisplayName = + childNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + if (clauseDisplayName.indexOf(PATIENT) > 0) { + clauseDisplayName = clauseDisplayName.replaceAll(PATIENT, " "); } + childNode.getAttributes().getNamedItem(DISPLAY_NAME).setNodeValue(clauseDisplayName); + } } - /** - * Creates the Supplemental Data Element Node. - * - * @param measureStratificationsNode stratifications Node for the measure - * @throws XPathExpressionException the x path expression exception - */ - private void createSupplementalDataElementNode(Node measureStratificationsNode) throws XPathExpressionException { - Node supplementaDataElementsElement = findNode(originalDoc, - XPATH_MEASURE_SD_ELEMENTS); - if (supplementaDataElementsElement == null) { - supplementaDataElementsElement = originalDoc - .createElement("supplementalDataElements"); - ((Element) measureStratificationsNode.getParentNode()) - .insertBefore(supplementaDataElementsElement, - measureStratificationsNode.getNextSibling()); - } - // Create elementLookUp node - if (findNode(originalDoc, XPATH_MEASURE_ELEMENT_LOOKUP) == null) { - Element elementLookUpElement = originalDoc - .createElement("elementLookUp"); - ((Element) supplementaDataElementsElement.getParentNode()) - .insertBefore(elementLookUpElement, - supplementaDataElementsElement.getNextSibling()); - } - if (findNode(originalDoc, XPATH_MEASURE_SUBTREE_LOOKUP) == null) { - Element subTreeLookUpElement = originalDoc - .createElement("subTreeLookUp"); - ((Element) supplementaDataElementsElement.getParentNode()) - .insertBefore(subTreeLookUpElement, - supplementaDataElementsElement.getNextSibling()); - } - // create Measure Grouping node - if (findNode(originalDoc, XPATH_MEASURE_GROUPING) == null) { - Element measureGroupingElement = originalDoc - .createElement("measureGrouping"); - ((Element) supplementaDataElementsElement.getParentNode()) - .insertBefore(measureGroupingElement, - supplementaDataElementsElement.getNextSibling()); - } - - Node riskAdjustmentVariablesElement = findNode(originalDoc, - XPATH_MEASURE_RAV_ELEMENTS); - if (riskAdjustmentVariablesElement == null) { - riskAdjustmentVariablesElement = originalDoc - .createElement("riskAdjustmentVariables"); - ((Element) supplementaDataElementsElement.getParentNode()) - .insertBefore(riskAdjustmentVariablesElement, - supplementaDataElementsElement.getNextSibling()); - } - - log.debug("Original Doc: " + originalDoc.toString()); + // rename 'initialPatientPopulations' to 'initialPopulations'. + document.renameNode(initialPopulationsNode, "", INITIAL_POPULATIONS); + } + + /** + * Rename timing conventions. + * + * @param document the document + * @throws XPathExpressionException the x path expression exception + */ + public void renameTimingConventions(Document document) throws XPathExpressionException { + String startsBeforeOrDuring = "Starts Before Or During"; + String endsBeforeOrDuring = "Ends Before Or During"; + String startBeforeEnd = "Starts Before End"; + String endsBeforeEnd = "Ends Before End"; + String sBE = "SBE"; + String eBE = "EBE"; + javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); + // replace relationalOp attribute values for displayName and type from SBOD to SBE + NodeList nodesRelationalOpsSBOD = + (NodeList) + xPath.evaluate( + XPATH_OLD_ALL_RELATIONALOP_SBOD, + originalDoc.getDocumentElement(), + XPathConstants.NODESET); + for (int i = 0; i < nodesRelationalOpsSBOD.getLength(); i++) { + Node childNode = nodesRelationalOpsSBOD.item(i); + String relationalOpDisplayName = + childNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + relationalOpDisplayName = + relationalOpDisplayName.replace(startsBeforeOrDuring, startBeforeEnd); + childNode.getAttributes().getNamedItem(DISPLAY_NAME).setNodeValue(relationalOpDisplayName); + childNode.getAttributes().getNamedItem(TYPE).setNodeValue(sBE); } - - /** - * Calculates whether we appended a child node or not. - * - * @param scoreBasedNodes the score Base Node - * @param populationsNode the node for the measures population - * @return Boolean - * true: if we appended a child - * false: if we didn't append a child - */ - private boolean calculateChildAppend(List scoreBasedNodes, - Node populationsNode) { - boolean childAppended = false; - for (String nodeName : scoreBasedNodes) { - boolean isNodePresent = false; - NodeList childNodes = populationsNode.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node childNode = childNodes.item(i); - String childNodeName = childNode.getNodeName(); - if (childNodeName.equals(nodeName)) { - isNodePresent = true; - break; - } - } - if (!isNodePresent) { - String displayName = constantsMap.get(nodeName); - Element mainChildElem = createTemplateNode(nodeName, - displayName); - populationsNode.appendChild(mainChildElem); - childAppended = true; - } - } - return childAppended; + // replace relationalOp attribute values for displayName and type from EBOD to EBE + NodeList nodesRelationalOpsEBOD = + (NodeList) + xPath.evaluate( + XPATH_OLD_ALL_RELATIONALOP_EBOD, + originalDoc.getDocumentElement(), + XPathConstants.NODESET); + for (int i = 0; i < nodesRelationalOpsEBOD.getLength(); i++) { + Node childNode = nodesRelationalOpsEBOD.item(i); + String relationalOpDisplayName = + childNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + relationalOpDisplayName = relationalOpDisplayName.replace(endsBeforeOrDuring, endsBeforeEnd); + childNode.getAttributes().getNamedItem(DISPLAY_NAME).setNodeValue(relationalOpDisplayName); + childNode.getAttributes().getNamedItem(TYPE).setNodeValue(eBE); } - - /** - * Retrieves the Score Based nodes. - * - * @param scoringType the scoring type - * @return List - * the score based Nodes - */ - private List retrieveScoreBasedNodes(String scoringType) { - List scoreBasedNodes = new ArrayList(); - if (CONTINUOUS_VARIABLE.equalsIgnoreCase(scoringType)) { - scoreBasedNodes.add(INITIAL_POPULATIONS); - scoreBasedNodes.add(MEASURE_POPULATIONS); - scoreBasedNodes.add(MEASURE_POPULATION_EXCLUSIONS); - } else if (PROPORTION.equalsIgnoreCase(scoringType)) { - scoreBasedNodes.add(INITIAL_POPULATIONS); - scoreBasedNodes.add(NUMERATORS); - scoreBasedNodes.add(NUMERATOR_EXCLUSIONS); - scoreBasedNodes.add(DENOMINATORS); - scoreBasedNodes.add(DENOMINATOR_EXCLUSIONS); - scoreBasedNodes.add(DENOMINATOR_EXCEPTIONS); - } else if (RATIO.equalsIgnoreCase(scoringType)) { - scoreBasedNodes.add(INITIAL_POPULATIONS); - scoreBasedNodes.add(NUMERATORS); - scoreBasedNodes.add(NUMERATOR_EXCLUSIONS); - scoreBasedNodes.add(DENOMINATORS); - scoreBasedNodes.add(DENOMINATOR_EXCLUSIONS); - } else if (COHORT.equalsIgnoreCase(scoringType)) { - scoreBasedNodes.add(INITIAL_POPULATIONS); - } - return scoreBasedNodes; + } + + /** + * This method looks at the Scoring Type for a measure and adds nodes based on the value of + * Scoring Type. + * + * @param scoringType the scoring type + * @throws XPathExpressionException the x path expression exception + */ + public void createNewNodesBasedOnScoring(String scoringType) throws XPathExpressionException { + List scoreBasedNodes = retrieveScoreBasedNodes(scoringType); + Node populationsNode = findNode(originalDoc, XPATH_POPULATIONS); + + if (populationsNode == null) { + populationsNode = addPopulationsNode(); } - + boolean childAppended = calculateChildAppend(scoreBasedNodes, populationsNode); /** - * This method will add a 'populations' node to the XML. It assumes that the - * 'measureDetails' node is already present in the XML Document and tries to - * add the 'populations' node after the 'measureDetails' node. - * - * @return the node - * @throws XPathExpressionException the x path expression exception + * Add Measure Observations node after Populations node if not present and scoring type is + * Continuous Variable. */ - private Node addPopulationsNode() throws XPathExpressionException { - Element populationsElem = originalDoc.createElement("populations"); - populationsElem.setAttribute(DISPLAY_NAME, - XmlProcessor.constantsMap.get("populations")); - Node measureNode = findNode(originalDoc, - "/measure"); - Element measureElement = (Element) measureNode; - measureElement.insertBefore(populationsElem, - measureNode.getFirstChild()); - return populationsElem; + Node measureObservationsNode = findNode(originalDoc, XPATH_MEASURE_OBSERVATIONS); + if ((CONTINUOUS_VARIABLE.equalsIgnoreCase(scoringType) || RATIO.equalsIgnoreCase(scoringType)) + && (measureObservationsNode == null)) { + // Create a new measureObservations element. + String nodeName = MEASURE_OBSERVATION; + String displayName = constantsMap.get(nodeName); + Element mainChildElem = createTemplateNode(nodeName, displayName); + measureObservationsNode = mainChildElem; + // insert measureObservations element after populations element + Node measureNode = populationsNode.getParentNode(); + Element measureElement = (Element) measureNode; + measureElement.insertBefore(mainChildElem, populationsNode.getNextSibling()); } - - /** - * This method creates blank nodes for Elements like 'child elements of - * populations node, measureObservations node and stratifications node' The - * method will return the newly created Element. The called needs to add - * this Element to the appropriate parent node in the Document. - * - * @param nodeName the node name - * @param clauseDisplayName the clause display name - * @return the element - */ - private Element createTemplateNode(String nodeName, String clauseDisplayName) { - Element mainChildElem = originalDoc.createElement(nodeName); - mainChildElem.setAttribute(DISPLAY_NAME, constantsMap.get(nodeName)); - - Element clauseChildElem = originalDoc.createElement("clause"); - String dispName = constantsMap.get(clauseDisplayName); - clauseChildElem.setAttribute(DISPLAY_NAME, dispName + " 1"); - clauseChildElem.setAttribute(TYPE, toCamelCase(dispName)); - clauseChildElem.setAttribute(UUID_STRING, UUID.randomUUID().toString()); - mainChildElem.appendChild(clauseChildElem); - - mainChildElem.appendChild(clauseChildElem); - - return mainChildElem; + // Create stratifications node + Node measureStratificationsNode = findNode(originalDoc, XPATH_MEASURE_STRATIFICATIONS); + if (measureStratificationsNode == null && !RATIO.equalsIgnoreCase(scoringType)) { + String stratificationsNodeName = "strata"; + String clauseDisplayName = "Stratum"; + Element stratificationElement = + createTemplateNode(stratificationsNodeName, clauseDisplayName); + + NodeList childs = stratificationElement.getChildNodes(); + Element stratificationEle = originalDoc.createElement(STRATIFICATION); + stratificationEle.setAttribute(DISPLAY_NAME, STRATIFICATION_DISPLAYNAME); + stratificationEle.setAttribute(UUID_STRING, UUID.randomUUID().toString()); + stratificationEle.setAttribute(TYPE, STRATIFICATION); + List nCList = new ArrayList(); + for (int i = 0; i < childs.getLength(); i++) { + nCList.add(childs.item(i)); + stratificationElement.removeChild(childs.item(i)); + } + for (Node cNode : nCList) { + stratificationEle.appendChild(cNode); + } + stratificationElement.appendChild(stratificationEle); + + measureStratificationsNode = stratificationElement; + // insert measureObservations element after populations element + Node measureNode = populationsNode.getParentNode(); + Element measureElement = (Element) measureNode; + if (measureObservationsNode != null) { + measureElement.insertBefore( + stratificationElement, measureObservationsNode.getNextSibling()); + } else { + measureElement.insertBefore(stratificationElement, populationsNode.getNextSibling()); + } + } else if (measureStratificationsNode != null && RATIO.equalsIgnoreCase(scoringType)) { + Node measureNode = measureStratificationsNode.getParentNode(); + Element measureElement = (Element) measureNode; + + measureElement.removeChild(measureStratificationsNode); } - - /** - * Removes the from parent. - * - * @param node the node - */ - public void removeFromParent(Node node) { - if (node != null) { - Node parentNode = node.getParentNode(); - parentNode.removeChild(node); + // Create supplementalDataElements node + createSupplementalDataElementNode(measureStratificationsNode); + /* + * All the adding and removing can put the children of 'populations' in + * a random order. Arrange the population nodes in correct order.*/ + // If no children have been appended, dont go through the process of + // re-arranging the + // populations node children. + if (!childAppended) { + return; + } + // remove all the child nodes of populations node first + NodeList childNodes = populationsNode.getChildNodes(); + List childNodesList = new ArrayList(); + for (int c = 0; c < childNodes.getLength(); c++) { + childNodesList.add(childNodes.item(c)); + } + for (int i = 0; i < childNodesList.size(); i++) { + populationsNode.removeChild(populationsNode.getChildNodes().item(0)); + } + arrangeChildNodeList(populationsNode, childNodesList); + } + + /** + * Take the child nodeList & re-arrange it according to this order "Initial Patient Populations", + * "Numerators", "Numerator Exclusions", "Denominators", "Denominator Exclusions", "Denominator + * Exceptions", "Measure Populations", "Measure Population Exclusions". + * + * @param populationsNode the population node + * @param childNodesList array list of nodes to be ordered + */ + private void arrangeChildNodeList(Node populationsNode, List childNodesList) { + // Take the child nodeList & re-arrange it according to this order + // "Initial Patient Populations", "Numerators", "Numerator Exclusions", + // "Denominators", "Denominator Exclusions", + // "Denominator Exceptions", "Measure Populations", "Measure Population Exclusions" + for (String populationsChild : XmlProcessor.POPULATIONS) { + Node populationsChildNode = null; + for (int j = 0; j < childNodesList.size(); j++) { + Node child = childNodesList.get(j); + if (child.getNodeName().equals(populationsChild)) { + populationsChildNode = child; + break; } + } + if (populationsChildNode != null) { + populationsNode.appendChild(populationsChildNode); + } } - - /** - * Find node. - * - * @param document the document - * @param xPathString the x path string - * @return the node - * @throws XPathExpressionException the x path expression exception - */ - public Node findNode(Document document, String xPathString) throws XPathExpressionException { - javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); - Node node = (Node) xPath.evaluate(xPathString, document.getDocumentElement(), XPathConstants.NODE); - return node; + } + + /** + * Creates the Supplemental Data Element Node. + * + * @param measureStratificationsNode stratifications Node for the measure + * @throws XPathExpressionException the x path expression exception + */ + private void createSupplementalDataElementNode(Node measureStratificationsNode) + throws XPathExpressionException { + Node supplementaDataElementsElement = findNode(originalDoc, XPATH_MEASURE_SD_ELEMENTS); + if (supplementaDataElementsElement == null) { + supplementaDataElementsElement = originalDoc.createElement("supplementalDataElements"); + ((Element) measureStratificationsNode.getParentNode()) + .insertBefore( + supplementaDataElementsElement, measureStratificationsNode.getNextSibling()); } - - /** - * Find node list. - * - * @param document the document - * @param xPathString the x path string - * @return the node list - * @throws XPathExpressionException the x path expression exception - */ - public NodeList findNodeList(Document document, String xPathString) throws XPathExpressionException { - javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); - XPathExpression expr = xPath.compile(xPathString); - return (NodeList) expr.evaluate(document, XPathConstants.NODESET); + // Create elementLookUp node + if (findNode(originalDoc, XPATH_MEASURE_ELEMENT_LOOKUP) == null) { + Element elementLookUpElement = originalDoc.createElement("elementLookUp"); + ((Element) supplementaDataElementsElement.getParentNode()) + .insertBefore(elementLookUpElement, supplementaDataElementsElement.getNextSibling()); } - - /** - * Gets the node count. - * - * @param document the document - * @param xPathString the x path string - * @return the node count - * @throws XPathExpressionException the x path expression exception - */ - public int getNodeCount(Document document, String xPathString) throws XPathExpressionException { - javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); - XPathExpression expr = xPath.compile(xPathString); - return ((Double) expr.evaluate(document, XPathConstants.NUMBER)).intValue(); + if (findNode(originalDoc, XPATH_MEASURE_SUBTREE_LOOKUP) == null) { + Element subTreeLookUpElement = originalDoc.createElement("subTreeLookUp"); + ((Element) supplementaDataElementsElement.getParentNode()) + .insertBefore(subTreeLookUpElement, supplementaDataElementsElement.getNextSibling()); } - - /** - * Gets the original doc. - * - * @return the originalDoc - */ - public Document getOriginalDoc() { - return originalDoc; + // create Measure Grouping node + if (findNode(originalDoc, XPATH_MEASURE_GROUPING) == null) { + Element measureGroupingElement = originalDoc.createElement("measureGrouping"); + ((Element) supplementaDataElementsElement.getParentNode()) + .insertBefore(measureGroupingElement, supplementaDataElementsElement.getNextSibling()); } - /** - * Sets the original doc. - * - * @param originalDoc the originalDoc to set - */ - public void setOriginalDoc(Document originalDoc) { - this.originalDoc = originalDoc; + Node riskAdjustmentVariablesElement = findNode(originalDoc, XPATH_MEASURE_RAV_ELEMENTS); + if (riskAdjustmentVariablesElement == null) { + riskAdjustmentVariablesElement = originalDoc.createElement("riskAdjustmentVariables"); + ((Element) supplementaDataElementsElement.getParentNode()) + .insertBefore( + riskAdjustmentVariablesElement, supplementaDataElementsElement.getNextSibling()); } - /** - * To camel case. - * - * @param name the name - * @return the string - */ - private static String toCamelCase(String name) { - String nameNew = name.toLowerCase(Locale.US); - String[] parts = nameNew.split(" "); - StringBuffer camelCaseString = new StringBuffer(parts[0].substring(0, 1).toLowerCase() - + parts[0].substring(1)); - for (int i = 1; i < parts.length; i++) { - camelCaseString.append(toProperCase(parts[i])); + log.debug("Original Doc: " + originalDoc.toString()); + } + + /** + * Calculates whether we appended a child node or not. + * + * @param scoreBasedNodes the score Base Node + * @param populationsNode the node for the measures population + * @return Boolean true: if we appended a child false: if we didn't append a child + */ + private boolean calculateChildAppend(List scoreBasedNodes, Node populationsNode) { + boolean childAppended = false; + for (String nodeName : scoreBasedNodes) { + boolean isNodePresent = false; + NodeList childNodes = populationsNode.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node childNode = childNodes.item(i); + String childNodeName = childNode.getNodeName(); + if (childNodeName.equals(nodeName)) { + isNodePresent = true; + break; } - return camelCaseString.toString(); + } + if (!isNodePresent) { + String displayName = constantsMap.get(nodeName); + Element mainChildElem = createTemplateNode(nodeName, displayName); + populationsNode.appendChild(mainChildElem); + childAppended = true; + } } - - /** - * To proper case. - * - * @param str the s - * @return the string - */ - private static String toProperCase(String str) { - return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase(); + return childAppended; + } + + /** + * Retrieves the Score Based nodes. + * + * @param scoringType the scoring type + * @return List the score based Nodes + */ + private List retrieveScoreBasedNodes(String scoringType) { + List scoreBasedNodes = new ArrayList(); + if (CONTINUOUS_VARIABLE.equalsIgnoreCase(scoringType)) { + scoreBasedNodes.add(INITIAL_POPULATIONS); + scoreBasedNodes.add(MEASURE_POPULATIONS); + scoreBasedNodes.add(MEASURE_POPULATION_EXCLUSIONS); + } else if (PROPORTION.equalsIgnoreCase(scoringType)) { + scoreBasedNodes.add(INITIAL_POPULATIONS); + scoreBasedNodes.add(NUMERATORS); + scoreBasedNodes.add(NUMERATOR_EXCLUSIONS); + scoreBasedNodes.add(DENOMINATORS); + scoreBasedNodes.add(DENOMINATOR_EXCLUSIONS); + scoreBasedNodes.add(DENOMINATOR_EXCEPTIONS); + } else if (RATIO.equalsIgnoreCase(scoringType)) { + scoreBasedNodes.add(INITIAL_POPULATIONS); + scoreBasedNodes.add(NUMERATORS); + scoreBasedNodes.add(NUMERATOR_EXCLUSIONS); + scoreBasedNodes.add(DENOMINATORS); + scoreBasedNodes.add(DENOMINATOR_EXCLUSIONS); + } else if (COHORT.equalsIgnoreCase(scoringType)) { + scoreBasedNodes.add(INITIAL_POPULATIONS); } - - /** - * Transform. - * - * @param node the node - * @return the string - */ - public String transform(Node node) { - return transform(node, false); + return scoreBasedNodes; + } + + /** + * This method will add a 'populations' node to the XML. It assumes that the 'measureDetails' node + * is already present in the XML Document and tries to add the 'populations' node after the + * 'measureDetails' node. + * + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + private Node addPopulationsNode() throws XPathExpressionException { + Element populationsElem = originalDoc.createElement("populations"); + populationsElem.setAttribute(DISPLAY_NAME, XmlProcessor.constantsMap.get("populations")); + Node measureNode = findNode(originalDoc, "/measure"); + Element measureElement = (Element) measureNode; + measureElement.insertBefore(populationsElem, measureNode.getFirstChild()); + return populationsElem; + } + + /** + * This method creates blank nodes for Elements like 'child elements of populations node, + * measureObservations node and stratifications node' The method will return the newly created + * Element. The called needs to add this Element to the appropriate parent node in the Document. + * + * @param nodeName the node name + * @param clauseDisplayName the clause display name + * @return the element + */ + private Element createTemplateNode(String nodeName, String clauseDisplayName) { + Element mainChildElem = originalDoc.createElement(nodeName); + mainChildElem.setAttribute(DISPLAY_NAME, constantsMap.get(nodeName)); + + Element clauseChildElem = originalDoc.createElement("clause"); + String dispName = constantsMap.get(clauseDisplayName); + clauseChildElem.setAttribute(DISPLAY_NAME, dispName + " 1"); + clauseChildElem.setAttribute(TYPE, toCamelCase(dispName)); + clauseChildElem.setAttribute(UUID_STRING, UUID.randomUUID().toString()); + mainChildElem.appendChild(clauseChildElem); + + mainChildElem.appendChild(clauseChildElem); + + return mainChildElem; + } + + /** + * Removes the from parent. + * + * @param node the node + */ + public void removeFromParent(Node node) { + if (node != null) { + Node parentNode = node.getParentNode(); + parentNode.removeChild(node); } - - /** - * Convert xml document to string. - * - * @param node the node - * @param isFormatted - * @return the string - */ - public String transform(Node node, boolean isFormatted) { - log.debug("In transform() method"); - Transformer tf; - Writer out = null; - try { - TransformerFactory transformerFactory = XMLUtility.getInstance().buildTransformerFactory(); - tf = transformerFactory.newTransformer(); - tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); - - if (isFormatted) { - tf.setOutputProperty(OutputKeys.INDENT, "yes"); - } - - tf.setOutputProperty(OutputKeys.STANDALONE, "yes"); - out = new StringWriter(); - tf.transform(new DOMSource(node), new StreamResult(out)); - } catch (TransformerFactoryConfigurationError | TransformerException e) { - log.error(e.getMessage(), e); - } - log.debug("Document object to ByteArray transformation complete"); - return out.toString(); + } + + /** + * Find node. + * + * @param document the document + * @param xPathString the x path string + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + public Node findNode(Document document, String xPathString) throws XPathExpressionException { + javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); + Node node = + (Node) xPath.evaluate(xPathString, document.getDocumentElement(), XPathConstants.NODE); + return node; + } + + /** + * Find node list. + * + * @param document the document + * @param xPathString the x path string + * @return the node list + * @throws XPathExpressionException the x path expression exception + */ + public NodeList findNodeList(Document document, String xPathString) + throws XPathExpressionException { + javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); + XPathExpression expr = xPath.compile(xPathString); + return (NodeList) expr.evaluate(document, XPathConstants.NODESET); + } + + /** + * Gets the node count. + * + * @param document the document + * @param xPathString the x path string + * @return the node count + * @throws XPathExpressionException the x path expression exception + */ + public int getNodeCount(Document document, String xPathString) throws XPathExpressionException { + javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); + XPathExpression expr = xPath.compile(xPathString); + return ((Double) expr.evaluate(document, XPathConstants.NUMBER)).intValue(); + } + + /** + * Gets the original doc. + * + * @return the originalDoc + */ + public Document getOriginalDoc() { + return originalDoc; + } + + /** + * Sets the original doc. + * + * @param originalDoc the originalDoc to set + */ + public void setOriginalDoc(Document originalDoc) { + this.originalDoc = originalDoc; + } + + /** + * To camel case. + * + * @param name the name + * @return the string + */ + private static String toCamelCase(String name) { + String nameNew = name.toLowerCase(Locale.US); + String[] parts = nameNew.split(" "); + StringBuffer camelCaseString = + new StringBuffer(parts[0].substring(0, 1).toLowerCase() + parts[0].substring(1)); + for (int i = 1; i < parts.length; i++) { + camelCaseString.append(toProperCase(parts[i])); } - - /** - * Takes the spaces out of the clauseName (attribute displayName in XML). - * - * @param xmlString the xml string - * @param xPathString the x path string - * @return the string - * @throws XPathExpressionException the x path expression exception - */ - public static String normalizeNodeForSpaces(String xmlString, String xPathString) throws XPathExpressionException { - XmlProcessor xmlProcessor = new XmlProcessor(xmlString); - Node node = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), xPathString); - if (node != null) { - String oldValue = node.getNodeValue(); - // Normalize by changing multiple spaces into one space - String newValue = oldValue.replaceAll("( )+", " "); - node.setNodeValue(newValue); - } - return xmlProcessor.transform(xmlProcessor.getOriginalDoc()); + return camelCaseString.toString(); + } + + /** + * To proper case. + * + * @param str the s + * @return the string + */ + private static String toProperCase(String str) { + return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase(); + } + + /** + * Transform. + * + * @param node the node + * @return the string + */ + public String transform(Node node) { + return transform(node, false); + } + + /** + * Convert xml document to string. + * + * @param node the node + * @param isFormatted + * @return the string + */ + public String transform(Node node, boolean isFormatted) { + log.debug("In transform() method"); + Transformer tf; + Writer out = null; + try { + TransformerFactory transformerFactory = XMLUtility.getInstance().buildTransformerFactory(); + tf = transformerFactory.newTransformer(); + tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + + if (isFormatted) { + tf.setOutputProperty(OutputKeys.INDENT, "yes"); + } + + tf.setOutputProperty(OutputKeys.STANDALONE, "yes"); + out = new StringWriter(); + tf.transform(new DOMSource(node), new StreamResult(out)); + } catch (TransformerFactoryConfigurationError | TransformerException e) { + log.error(e.getMessage(), e); } - - /** - * Utility method to go through the Node and its children (upto nth level) - * and remove all TEXT nodes. - * - * @param node the node - */ - public static void clean(Node node) { - NodeList childNodes = node.getChildNodes(); - - for (int n = childNodes.getLength() - 1; n >= 0; n--) { - Node child = childNodes.item(n); - short nodeType = child.getNodeType(); - - if (nodeType == Node.ELEMENT_NODE) { - clean(child); - } else if (nodeType == Node.TEXT_NODE) { - String trimmedNodeVal = child.getNodeValue().trim(); - if (trimmedNodeVal.length() == 0) { - node.removeChild(child); - } else { - child.setNodeValue(trimmedNodeVal); - } - } else if (nodeType == Node.COMMENT_NODE) { - node.removeChild(child); - } - } + log.debug("Document object to ByteArray transformation complete"); + return out.toString(); + } + + /** + * Takes the spaces out of the clauseName (attribute displayName in XML). + * + * @param xmlString the xml string + * @param xPathString the x path string + * @return the string + * @throws XPathExpressionException the x path expression exception + */ + public static String normalizeNodeForSpaces(String xmlString, String xPathString) + throws XPathExpressionException { + XmlProcessor xmlProcessor = new XmlProcessor(xmlString); + Node node = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), xPathString); + if (node != null) { + String oldValue = node.getNodeValue(); + // Normalize by changing multiple spaces into one space + String newValue = oldValue.replaceAll("( )+", " "); + node.setNodeValue(newValue); } - - public void updateCQLLibraryName(String libraryName) throws XPathExpressionException { - - Node cqlLibraryNode = findNode(originalDoc, "//cqlLookUp/library"); - - if (cqlLibraryNode != null) { - libraryName = cleanString(libraryName); - - cqlLibraryNode.setTextContent(libraryName); + return xmlProcessor.transform(xmlProcessor.getOriginalDoc()); + } + + /** + * Utility method to go through the Node and its children (upto nth level) and remove all TEXT + * nodes. + * + * @param node the node + */ + public static void clean(Node node) { + NodeList childNodes = node.getChildNodes(); + + for (int n = childNodes.getLength() - 1; n >= 0; n--) { + Node child = childNodes.item(n); + short nodeType = child.getNodeType(); + + if (nodeType == Node.ELEMENT_NODE) { + clean(child); + } else if (nodeType == Node.TEXT_NODE) { + String trimmedNodeVal = child.getNodeValue().trim(); + if (trimmedNodeVal.length() == 0) { + node.removeChild(child); + } else { + child.setNodeValue(trimmedNodeVal); } + } else if (nodeType == Node.COMMENT_NODE) { + node.removeChild(child); + } } + } - /** - * This method will take a String and remove all non-alphabet/non-numeric characters - * except underscore ("_") characters. - * - * @param originalString - * @return cleanedString - */ - private String cleanString(String originalString) { - originalString = originalString.replaceAll(" ", ""); - - String cleanedString = ""; - for (int i = 0; i < originalString.length(); i++) { - char c = originalString.charAt(i); - int intc = (int) c; + public void updateCQLLibraryName(String libraryName) throws XPathExpressionException { - if (c == '_' || (intc >= 48 && intc <= 57) || (intc >= 65 && intc <= 90) || (intc >= 97 && intc <= 122)) { + Node cqlLibraryNode = findNode(originalDoc, "//cqlLookUp/library"); - if (!(cleanedString.isEmpty() && Character.isDigit(c))) { - cleanedString = cleanedString + "" + c; - } - - } + if (cqlLibraryNode != null) { + libraryName = cleanString(libraryName); + cqlLibraryNode.setTextContent(libraryName); + } + } + + /** + * This method will take a String and remove all non-alphabet/non-numeric characters except + * underscore ("_") characters. + * + * @param originalString + * @return cleanedString + */ + private String cleanString(String originalString) { + originalString = originalString.replaceAll(" ", ""); + + String cleanedString = ""; + for (int i = 0; i < originalString.length(); i++) { + char c = originalString.charAt(i); + int intc = (int) c; + + if (c == '_' + || (intc >= 48 && intc <= 57) + || (intc >= 65 && intc <= 90) + || (intc >= 97 && intc <= 122)) { + + if (!(cleanedString.isEmpty() && Character.isDigit(c))) { + cleanedString = cleanedString + "" + c; } - - return cleanedString; + } } - /** - * Check for default parameter MeasurementPeriod. - * - * @return the list - */ - public List checkForDefaultParameters() { - List missingDefaultParameterList = new ArrayList(); - - if (originalDoc != null) { - try { - // Measurement Period - Node measurementPeriodNode = this.findNode(originalDoc, - "/measure/cqlLookUp//parameter[@name='" - + PARAMETER_MEASUREMENT_PERIOD + "']"); - if (measurementPeriodNode == null) { - missingDefaultParameterList.add(PARAMETER_MEASUREMENT_PERIOD); - } - - } catch (XPathExpressionException e) { - log.error(e.getMessage(), e); - } + return cleanedString; + } + + /** + * Check for default parameter MeasurementPeriod. + * + * @return the list + */ + public List checkForDefaultParameters() { + List missingDefaultParameterList = new ArrayList(); + + if (originalDoc != null) { + try { + // Measurement Period + Node measurementPeriodNode = + this.findNode( + originalDoc, + "/measure/cqlLookUp//parameter[@name='" + PARAMETER_MEASUREMENT_PERIOD + "']"); + if (measurementPeriodNode == null) { + missingDefaultParameterList.add(PARAMETER_MEASUREMENT_PERIOD); } - return missingDefaultParameterList; - } - public void removeUnusedDefaultCodes(List usedCodeList) { - try { - NodeList nodeList = findNodeList(getOriginalDoc(), XPATH_FOR_CODES); - List codeSystemOIDsToRemove = new ArrayList<>(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node currentNode = nodeList.item(i); - if (null != currentNode.getAttributes().getNamedItem(ATTRIBUTE_READ_ONLY)) { - String codeOID = currentNode.getAttributes().getNamedItem(ATTRIBUTE_CODE_OID).getNodeValue(); - Boolean readOnly = Boolean.parseBoolean(currentNode.getAttributes().getNamedItem(ATTRIBUTE_READ_ONLY).getNodeValue()); - - if (readOnly && (codeOID.equals(ConstantMessages.BIRTHDATE_OID) || codeOID.equals(ConstantMessages.DEAD_OID))) { - String codeName = currentNode.getAttributes().getNamedItem(ATTRIBUTE_CODE_NAME).getNodeValue(); - if (!usedCodeList.contains(codeName)) { - String codeSystemOID = currentNode.getAttributes().getNamedItem(ATTRIBUTE_CODE_SYSTEM_OID).getNodeValue(); - codeSystemOIDsToRemove.add(codeSystemOID); - Node parentNode = currentNode.getParentNode(); - parentNode.removeChild(currentNode); - } - } - } + } catch (XPathExpressionException e) { + log.error(e.getMessage(), e); + } + } + return missingDefaultParameterList; + } + + public void removeUnusedDefaultCodes(List usedCodeList) { + try { + NodeList nodeList = findNodeList(getOriginalDoc(), XPATH_FOR_CODES); + List codeSystemOIDsToRemove = new ArrayList<>(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node currentNode = nodeList.item(i); + if (null != currentNode.getAttributes().getNamedItem(ATTRIBUTE_READ_ONLY)) { + String codeOID = + currentNode.getAttributes().getNamedItem(ATTRIBUTE_CODE_OID).getNodeValue(); + Boolean readOnly = + Boolean.parseBoolean( + currentNode.getAttributes().getNamedItem(ATTRIBUTE_READ_ONLY).getNodeValue()); + + if (readOnly + && (codeOID.equals(ConstantMessages.BIRTHDATE_OID) + || codeOID.equals(ConstantMessages.DEAD_OID))) { + String codeName = + currentNode.getAttributes().getNamedItem(ATTRIBUTE_CODE_NAME).getNodeValue(); + if (!usedCodeList.contains(codeName)) { + String codeSystemOID = + currentNode + .getAttributes() + .getNamedItem(ATTRIBUTE_CODE_SYSTEM_OID) + .getNodeValue(); + codeSystemOIDsToRemove.add(codeSystemOID); + Node parentNode = currentNode.getParentNode(); + parentNode.removeChild(currentNode); } - removeUnusedCodeSystems(codeSystemOIDsToRemove); - } catch (XPathExpressionException e) { - log.error(e.getMessage(), e); + } } + } + removeUnusedCodeSystems(codeSystemOIDsToRemove); + } catch (XPathExpressionException e) { + log.error(e.getMessage(), e); } - - /** - * When drafting or cloning a measure or cql library, the version attribute should become an empty string in the valueset tag. - *

- * It is an empty string because MAT still needs to support the version attribute because valuesets that had a version in an already - * versioned measure should retain those values. - */ - public void clearValuesetVersionAttribute() { - try { - NodeList nodeList = findNodeList(getOriginalDoc(), XPATH_FOR_VALUESETS); - for (int i = 0; i < nodeList.getLength(); i++) { - Node valuesetNode = nodeList.item(i); - Node version = valuesetNode.getAttributes().getNamedItem("version"); - if (version != null) { - version.setNodeValue(""); - } - } - } catch (XPathExpressionException e) { - log.error(e.getMessage(), e); + } + + /** + * When drafting or cloning a measure or cql library, the version attribute should become an empty + * string in the valueset tag. + * + *

It is an empty string because MAT still needs to support the version attribute because + * valuesets that had a version in an already versioned measure should retain those values. + */ + public void clearValuesetVersionAttribute() { + try { + NodeList nodeList = findNodeList(getOriginalDoc(), XPATH_FOR_VALUESETS); + for (int i = 0; i < nodeList.getLength(); i++) { + Node valuesetNode = nodeList.item(i); + Node version = valuesetNode.getAttributes().getNamedItem("version"); + if (version != null) { + version.setNodeValue(""); } + } + } catch (XPathExpressionException e) { + log.error(e.getMessage(), e); } - - private void removeUnusedCodeSystems(List codeSystemOIDsToRemove) { - try { - NodeList nodeList = findNodeList(getOriginalDoc(), XPATH_FOR_CODES); - for (int i = 0; i < nodeList.getLength(); i++) { - Node currentNode = nodeList.item(i); - String codeSystemOID = currentNode.getAttributes().getNamedItem(ATTRIBUTE_CODE_SYSTEM_OID).getNodeValue(); - if (codeSystemOIDsToRemove.contains(codeSystemOID)) { - codeSystemOIDsToRemove.remove(codeSystemOIDsToRemove.indexOf(codeSystemOID)); - } - } - - for (String codeSystemOID : codeSystemOIDsToRemove) { - String codeSystemXPathString = "[@codeSystemOID =\"" + codeSystemOID + "\"]"; - Node codeSystemNode = findNode(getOriginalDoc(), codeSystemXPathString); - Node parentNode = codeSystemNode.getParentNode(); - parentNode.removeChild(codeSystemNode); - } - } catch (Exception e) { - log.error(e.getMessage(), e); + } + + private void removeUnusedCodeSystems(List codeSystemOIDsToRemove) { + try { + NodeList nodeList = findNodeList(getOriginalDoc(), XPATH_FOR_CODES); + for (int i = 0; i < nodeList.getLength(); i++) { + Node currentNode = nodeList.item(i); + String codeSystemOID = + currentNode.getAttributes().getNamedItem(ATTRIBUTE_CODE_SYSTEM_OID).getNodeValue(); + if (codeSystemOIDsToRemove.contains(codeSystemOID)) { + codeSystemOIDsToRemove.remove(codeSystemOIDsToRemove.indexOf(codeSystemOID)); } + } + + for (String codeSystemOID : codeSystemOIDsToRemove) { + String codeSystemXPathString = "[@codeSystemOID =\"" + codeSystemOID + "\"]"; + Node codeSystemNode = findNode(getOriginalDoc(), codeSystemXPathString); + Node parentNode = codeSystemNode.getParentNode(); + parentNode.removeChild(codeSystemNode); + } + } catch (Exception e) { + log.error(e.getMessage(), e); } + } } diff --git a/src/main/java/gov/cms/madie/hqmf/dto/MeasureExport.java b/src/main/java/gov/cms/madie/hqmf/dto/MeasureExport.java index 2d548d6..62da273 100644 --- a/src/main/java/gov/cms/madie/hqmf/dto/MeasureExport.java +++ b/src/main/java/gov/cms/madie/hqmf/dto/MeasureExport.java @@ -10,29 +10,29 @@ @Builder public class MeasureExport { - private String id; + private String id; - private String simpleXml; + private String simpleXml; - private Measure measure; + private Measure measure; - private String humanReadable; + private String humanReadable; - private String hqmf; + private String hqmf; - private String cql; + private String cql; - private String measureJson; + private String measureJson; - private String elmXml; + private String elmXml; - private String fhirIncludedLibsJson; + private String fhirIncludedLibsJson; - private XmlProcessor hqmfXmlProcessor; + private XmlProcessor hqmfXmlProcessor; - private XmlProcessor simpleXmlProcessor; + private XmlProcessor simpleXmlProcessor; - private XmlProcessor humanReadableProcessor; + private XmlProcessor humanReadableProcessor; - private String releaseVersion; + private String releaseVersion; } diff --git a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFClauseLogicGenerator.java b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFClauseLogicGenerator.java index 1aa181e..78d6981 100644 --- a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFClauseLogicGenerator.java +++ b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFClauseLogicGenerator.java @@ -26,3283 +26,3396 @@ import java.util.TreeMap; public class HQMFClauseLogicGenerator implements Generator { - private static final String GROUPER_CRITERIA = "grouperCriteria"; - private static final String CONJUNCTION_CODE = "conjunctionCode"; - private static final String LOCAL_VARIABLE_NAME = "localVariableName"; - private static final String CRITERIA_REFERENCE = "criteriaReference"; - - private static final String ROLE = "role"; - - private static final String PARTICIPATION = "participation"; - - private static final String EXCERPT = "excerpt"; - - private static final String SEQUENCE_NUMBER = "sequenceNumber"; - - private static final String GROUPER = "grouper"; - - private static final String ENTRY = "entry"; - - private static final String DATA_CRITERIA_SECTION = "dataCriteriaSection"; - - private Map subTreeNodeMap = new HashMap<>(); - - public MeasureExport measureExport; - - private static final Logger logger = LoggerFactory.getLogger(HQMFClauseLogicGenerator.class); - - /** - * MAP of Functional Ops NON Subset Type. - */ - private static final Map FUNCTIONAL_OPS_NON_SUBSET = new TreeMap<>( - String.CASE_INSENSITIVE_ORDER); - /** - * MAP of Functional Ops Subset Type. - */ - private static final Map FUNCTIONAL_OPS_SUBSET = new TreeMap<>( - String.CASE_INSENSITIVE_ORDER); - static { - FUNCTIONAL_OPS_NON_SUBSET.put(MatConstants.FIRST, "1"); - FUNCTIONAL_OPS_NON_SUBSET.put(MatConstants.SECOND, "2"); - FUNCTIONAL_OPS_NON_SUBSET.put(MatConstants.THIRD, "3"); - FUNCTIONAL_OPS_NON_SUBSET.put(MatConstants.FOURTH, "4"); - FUNCTIONAL_OPS_NON_SUBSET.put(MatConstants.FIFTH, "5"); - - FUNCTIONAL_OPS_SUBSET.put(MatConstants.MOST_RECENT, "QDM_LAST"); - FUNCTIONAL_OPS_SUBSET.put(MatConstants.COUNT, "QDM_SUM"); - FUNCTIONAL_OPS_SUBSET.put(MatConstants.MIN, "QDM_MIN"); - FUNCTIONAL_OPS_SUBSET.put(MatConstants.MAX, "QDM_MAX"); - FUNCTIONAL_OPS_SUBSET.put(MatConstants.SUM, "QDM_SUM"); - FUNCTIONAL_OPS_SUBSET.put(MatConstants.MEDIAN, "QDM_MEDIAN"); - FUNCTIONAL_OPS_SUBSET.put(MatConstants.AVG, "QDM_AVERAGE"); - - } - - /** The Constant populations. */ - private static final List POPULATION_NAME_LIST = new ArrayList<>(); - - static { - POPULATION_NAME_LIST.add("initialPopulation"); - POPULATION_NAME_LIST.add("denominator"); - POPULATION_NAME_LIST.add("denominatorExclusions"); - POPULATION_NAME_LIST.add("denominatorExceptions"); - POPULATION_NAME_LIST.add("numerator"); - POPULATION_NAME_LIST.add("numeratorExclusions"); - POPULATION_NAME_LIST.add("measurePopulation"); - POPULATION_NAME_LIST.add("measurePopulationExclusions"); - POPULATION_NAME_LIST.add("stratum"); - } - - /** The sub tree node in mo map. */ - Map subTreeNodeInMOMap = new HashMap<>(); - - /** The sub tree node in pop map. */ - Map subTreeNodeInPOPMap = new HashMap<>(); - - /** The sub tree node in RA map. */ - Map subTreeNodeInRAMap = new HashMap<>(); - - /** The Constant FUNCTIONAL_OP_RULES_IN_POP. */ - private static final Map> FUNCTIONAL_OP_RULES_IN_POP = new TreeMap<>( - String.CASE_INSENSITIVE_ORDER); - - /** The Constant FUNCTIONAL_OP_RULES_IN_MO. */ - private static final Map> FUNCTIONAL_OP_RULES_IN_MO = new TreeMap<>( - String.CASE_INSENSITIVE_ORDER); - - static { - FUNCTIONAL_OP_RULES_IN_POP.put("MEDIAN", getFunctionalOpFirstChild("MEDIAN")); - FUNCTIONAL_OP_RULES_IN_POP.put("AVG", getFunctionalOpFirstChild("AVG")); - FUNCTIONAL_OP_RULES_IN_POP.put("MAX", getFunctionalOpFirstChild("MAX")); - FUNCTIONAL_OP_RULES_IN_POP.put("MIN", getFunctionalOpFirstChild("MIN")); - FUNCTIONAL_OP_RULES_IN_POP.put("SUM", getFunctionalOpFirstChild("SUM")); - FUNCTIONAL_OP_RULES_IN_POP.put("COUNT", getFunctionalOpFirstChild("COUNT")); - FUNCTIONAL_OP_RULES_IN_POP.put("FIRST", getFunctionalOpFirstChild("FIRST")); - FUNCTIONAL_OP_RULES_IN_POP.put("SECOND", getFunctionalOpFirstChild("SECOND")); - FUNCTIONAL_OP_RULES_IN_POP.put("THIRD", getFunctionalOpFirstChild("THIRD")); - FUNCTIONAL_OP_RULES_IN_POP.put("FOURTH", getFunctionalOpFirstChild("FOURTH")); - FUNCTIONAL_OP_RULES_IN_POP.put("FIFTH", getFunctionalOpFirstChild("FIFTH")); - FUNCTIONAL_OP_RULES_IN_POP.put("MOST RECENT", getFunctionalOpFirstChild("MOST RECENT")); - FUNCTIONAL_OP_RULES_IN_POP.put("AGE AT", getFunctionalOpFirstChild("AGE AT")); - - /* Rules for Functions in Measure Observations */ - FUNCTIONAL_OP_RULES_IN_MO.put("MEDIAN", getFunctionalOpFirstChildInMO("MEDIAN")); - FUNCTIONAL_OP_RULES_IN_MO.put("AVERAGE", getFunctionalOpFirstChildInMO("AVERAGE")); - FUNCTIONAL_OP_RULES_IN_MO.put("MIN", getFunctionalOpFirstChildInMO("MIN")); - FUNCTIONAL_OP_RULES_IN_MO.put("SUM", getFunctionalOpFirstChildInMO("SUM")); - FUNCTIONAL_OP_RULES_IN_MO.put("COUNT", getFunctionalOpFirstChildInMO("COUNT")); - FUNCTIONAL_OP_RULES_IN_MO.put("DATETIMEDIFF", getFunctionalOpFirstChildInMO("DATETIMEDIFF")); - } - - @Override - public String generate(MeasureExport me) throws Exception { - measureExport = me; - createUsedSubTreeRefMap(); - generateSubTreeXML(); - return null; - } - - /** - * Generate sub tree xml. - * - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateSubTreeXML() throws XPathExpressionException { - String xpath = "/measure/subTreeLookUp/subTree[not(@instance)]"; - NodeList subTreeNodeList = measureExport.getSimpleXmlProcessor() - .findNodeList(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); - for (int i = 0; i < subTreeNodeList.getLength(); i++) { - Node subTreeNode = subTreeNodeList.item(i); - subTreeNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - String uuid = subTreeNode.getAttributes().getNamedItem(UUID).getNodeValue(); - if (subTreeNodeInPOPMap.containsKey(uuid) && subTreeNodeInMOMap.containsKey(uuid) - || subTreeNodeInPOPMap.containsKey(uuid) || subTreeNodeInRAMap.containsKey(uuid)) { - generateSubTreeXML(subTreeNode, false); - } - } - String xpathOccurrence = "/measure/subTreeLookUp/subTree[(@instance)]"; - NodeList occurrenceSubTreeNodeList = measureExport.getSimpleXmlProcessor() - .findNodeList(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpathOccurrence); - for (int i = 0; i < occurrenceSubTreeNodeList.getLength(); i++) { - Node subTreeNode = occurrenceSubTreeNodeList.item(i); - generateOccHQMF(subTreeNode); - } - } - - /** - * Generate sub tree xml. - * - * @param subTreeNode - * the sub tree node - * @param msrObsDateTimeDiffSubTree - * the msr obs date time diff sub tree - * @return the node - * @throws XPathExpressionException - * the x path expression exception - */ - protected Node generateSubTreeXML(Node subTreeNode, boolean msrObsDateTimeDiffSubTree) - throws XPathExpressionException { - - // If this is an empty or NULL clause, return right now. - if (subTreeNode == null || !subTreeNode.hasChildNodes()) { - return null; - } - - /* - If this is a Occurrence clause then we need to find the base clause and - generate HQMF for the base clause. Then we need to generate Occurrence HQMF - for the occurrence clause. - */ - if (subTreeNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - String baseClauseUUID = subTreeNode.getAttributes().getNamedItem(INSTANCE_OF).getNodeValue(); - String xpath = "/measure/subTreeLookUp/subTree[@uuid = '" + baseClauseUUID + "']"; - Node baseSubTreeNode = measureExport.getSimpleXmlProcessor() - .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); - generateSubTreeXML(baseSubTreeNode, false); - generateOccHQMF(subTreeNode); - } - - String subTreeUUID = subTreeNode.getAttributes().getNamedItem(UUID).getNodeValue(); - String clauseName = subTreeNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - Boolean isRav = isRiskAdjustmentVariable(subTreeUUID, clauseName); - - // Check the 'subTreeNodeMap' to make sure the clause isn't already generated. - if (subTreeNodeMap.containsKey(subTreeUUID) && !msrObsDateTimeDiffSubTree) { - logger.debug("HQMF for Clause " + clauseName + " is already generated. Skipping."); - return null; - } - - // get the first child of the subTreeNode - Node firstChild = subTreeNode.getFirstChild(); - String firstChildName = firstChild.getNodeName(); - logger.debug("Generating HQMF for clause:'" + clauseName + "' with first child named:'" + firstChildName + "'."); - - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - Element dataCriteriaSectionElem = (Element) hqmfXmlProcessor.getOriginalDoc() - .getElementsByTagName(DATA_CRITERIA_SECTION).item(0); - - if (isRav) { - Comment riskAdjustmentVariable = hqmfXmlProcessor.getOriginalDoc().createComment("Risk Adjustment Variable"); - dataCriteriaSectionElem.appendChild(riskAdjustmentVariable); - } - Node entryElement = null; - switch (firstChildName) { - case SET_OP: - entryElement = generateSetOpHQMF(firstChild, dataCriteriaSectionElem, clauseName); - break; - case ELEMENT_REF: - entryElement = generateElementRefHQMF(firstChild, dataCriteriaSectionElem, clauseName); - break; - case SUB_TREE_REF: - entryElement = generateSubTreeHQMF(firstChild, dataCriteriaSectionElem, clauseName); - break; - case RELATIONAL_OP: - entryElement = generateRelOpHQMF(firstChild, dataCriteriaSectionElem, clauseName); - break; - case FUNCTIONAL_OP: - entryElement = generateFunctionalOpHQMF(firstChild, dataCriteriaSectionElem, clauseName); - break; - default: - // Dont do anything - break; - } - if (isRav) { - Node temp = hqmfXmlProcessor.getOriginalDoc().createAttribute(RAV); - temp.setNodeValue("true"); - entryElement.getAttributes().setNamedItem(temp); - } - /* - The clause is generated now. Make an entry in the 'subTreeNodeMap' to keep - track of its generation. - */ - subTreeNodeMap.put(subTreeUUID, subTreeNode); - return entryElement; - - } - - /** - * This method is used to discover weither a given class name and UUID is a risk - * adjustment variable. - * - * @param subTreeUUID - * the sub tree uuid - * @param clauseName - * the clause name - * @return the boolean - */ - private Boolean isRiskAdjustmentVariable(String subTreeUUID, String clauseName) { - String xPath = "/measure/riskAdjustmentVariables/subTreeRef[@displayName=\"" + clauseName + "\" and @id='" - + subTreeUUID + "']"; - boolean isRiskAdjustmentVariable = false; - try { - Node riskAdjVarNode = measureExport.getSimpleXmlProcessor() - .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xPath); - if (riskAdjVarNode != null) { - isRiskAdjustmentVariable = true; - } - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - return isRiskAdjustmentVariable; - } - - /** - * Generate occ hqmf. - * - * @param subTreeNode - * the sub tree node - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateOccHQMF(Node subTreeNode) throws XPathExpressionException { - // If this is an empty or NULL clause, return right now. - if (subTreeNode == null || subTreeNode.getAttributes().getNamedItem(INSTANCE_OF) == null) { - return; - } - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - String occSubTreeUUID = subTreeNode.getAttributes().getNamedItem(UUID).getNodeValue(); - String qdmVariableSubTreeUUID = subTreeNode.getAttributes().getNamedItem(INSTANCE_OF).getNodeValue(); - String clauseName = subTreeNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - Boolean isRAV = isRiskAdjustmentVariable(qdmVariableSubTreeUUID, clauseName); - // Check the 'subTreeNodeMap' to make sure the occ clause isn't already generated. - if (subTreeNodeMap.containsKey(occSubTreeUUID)) { - logger.debug("HQMF for Occ Clause " + clauseName + " is already generated. Skipping."); - return; - } - - if (!subTreeNodeMap.containsKey(qdmVariableSubTreeUUID)) { - logger.debug("HQMF for Clause " + clauseName + " is not already generated. Skipping."); - return; - } - - String xpath = "/measure/subTreeLookUp/subTree[@uuid = '" + qdmVariableSubTreeUUID + "']"; - Node baseSubTreeNode = measureExport.getSimpleXmlProcessor() - .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); - Node baseFirstChild = baseSubTreeNode.getFirstChild(); - String baseExt = baseFirstChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - - Node firstChild = subTreeNode.getFirstChild(); - String firstChildName = firstChild.getNodeName(); - String ext = firstChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - // Local Variable Name. - String localVarName = clauseName.replace("$", "") + "_" + UUIDUtilClient.uuid(5); - String root = subTreeNode.getAttributes().getNamedItem(INSTANCE_OF).getNodeValue(); - // Check for Element Ref as first CHild. - if (firstChildName.equalsIgnoreCase(ELEMENT_REF)) { - ext = getElementRefExt(firstChild, measureExport.getSimpleXmlProcessor()); - baseExt = getElementRefExt(baseFirstChild, measureExport.getSimpleXmlProcessor()); - } else if (RELATIONAL_OP.equals(firstChildName) || FUNCTIONAL_OP.equals(firstChildName) - || SET_OP.equals(firstChildName)) { - ext += "_" + firstChild.getAttributes().getNamedItem(UUID).getNodeValue(); - baseExt += "_" + baseFirstChild.getAttributes().getNamedItem(UUID).getNodeValue(); - } - - if (FUNCTIONAL_OP.equals(firstChildName) && firstChild.getFirstChild() != null) { - Node functionChild = firstChild.getFirstChild(); - Node baseFunctionChild = baseFirstChild.getFirstChild(); - - if (functionChild != null) { - if (functionChild.getNodeName().equalsIgnoreCase(SUB_TREE_REF)) { - ext = functionChild.getAttributes().getNamedItem(ID).getNodeValue(); - baseExt = baseFunctionChild.getAttributes().getNamedItem(ID).getNodeValue(); - } else if (functionChild.getNodeName().equalsIgnoreCase(ELEMENT_REF)) { - ext = getElementRefExt(functionChild, measureExport.getSimpleXmlProcessor()); - baseExt = getElementRefExt(baseFunctionChild, measureExport.getSimpleXmlProcessor()); - } else { - ext = StringUtils.deleteWhitespace( - functionChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + "_" - + functionChild.getAttributes().getNamedItem(UUID).getNodeValue()) - .replaceAll(":", "_"); - baseExt = StringUtils.deleteWhitespace( - baseFunctionChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + "_" - + baseFunctionChild.getAttributes().getNamedItem(UUID).getNodeValue()) - .replaceAll(":", "_"); - } - } - } - - String isQdmVariable = subTreeNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - if (isQdmVariable.equalsIgnoreCase(TRUE)) { - ext = "qdm_var_" + StringUtils.deleteWhitespace(ext); - baseExt = "qdm_var_" + StringUtils.deleteWhitespace(baseExt); - localVarName = "qdm_var_" + StringUtils.deleteWhitespace(localVarName); - } - String extForOccurrenceNode = "occ" + subTreeNode.getAttributes().getNamedItem("instance").getNodeValue() - + "of_" + ext; - ext = StringUtils.deleteWhitespace(ext); - localVarName = StringUtils.deleteWhitespace(localVarName); - logger.debug("generateOccHQMF " + "//entry/*/id[@root='" + root + "'][@extension=\"" + baseExt + "\"]"); - - Node idNodeQDM = hqmfXmlProcessor.findNode(hqmfXmlProcessor.getOriginalDoc(), - "//entry/*/id[@root='" + root + "'][@extension=\"" + baseExt + "\"]"); - logger.debug("idNodeQDM == null?" + (idNodeQDM == null)); - - if (idNodeQDM != null) { - // Add code here which will create a replica of the entry elem of 'idNodeQDM' - // and assign it an extension - // which has "Occ_X" string in it. - Node cloneMainEntryNode = idNodeQDM.getParentNode().getParentNode().cloneNode(true); - Node cloneIDNode = findNode(cloneMainEntryNode, "ID"); - if (cloneMainEntryNode != null) { - Node localVariableNode = cloneMainEntryNode.getFirstChild(); - if (localVariableNode.getAttributes().getNamedItem("value") != null) { - localVariableNode.getAttributes().getNamedItem("value").setNodeValue(localVarName); - } - } - cloneIDNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(extForOccurrenceNode); - - Element dataCriteriaSectionElem = (Element) hqmfXmlProcessor.getOriginalDoc() - .getElementsByTagName(DATA_CRITERIA_SECTION).item(0); - - dataCriteriaSectionElem.appendChild(cloneMainEntryNode); - - Node parentNode = cloneIDNode.getParentNode().cloneNode(false); - if (isRAV) { - Comment RAComment = hqmfXmlProcessor.getOriginalDoc().createComment("Risk Adjustment Variable"); - dataCriteriaSectionElem.appendChild(RAComment); - } - Element entryElem = hqmfXmlProcessor.getOriginalDoc().createElement(ENTRY); - entryElem.setAttribute(TYPE_CODE, "DRIV"); - Element idElement = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - idElement.setAttribute(ROOT, subTreeNode.getAttributes().getNamedItem(UUID).getNodeValue()); - idElement.setAttribute(EXTENSION, extForOccurrenceNode); - parentNode.appendChild(idElement); - Element outboundRelElem = hqmfXmlProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); - outboundRelElem.setAttribute(TYPE_CODE, "OCCR"); - - Element criteriaRefElem = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - String refClassCodeValue = parentNode.getAttributes().getNamedItem(CLASS_CODE).getNodeValue(); - String refMoodValue = parentNode.getAttributes().getNamedItem(MOOD_CODE).getNodeValue(); - criteriaRefElem.setAttribute(CLASS_CODE, refClassCodeValue); - criteriaRefElem.setAttribute(MOOD_CODE, refMoodValue); - - Element idRelElem = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - idRelElem.setAttribute(ROOT, root); - idRelElem.setAttribute(EXTENSION, extForOccurrenceNode); - - criteriaRefElem.appendChild(idRelElem); - outboundRelElem.appendChild(criteriaRefElem); - parentNode.appendChild(outboundRelElem); - entryElem.appendChild(parentNode); - dataCriteriaSectionElem.appendChild(entryElem); - - subTreeNodeMap.put(occSubTreeUUID, subTreeNode); - } - } - - /** - * Generate functional op hqmf. - * - * @param functionalNode - * the functional node - * @param dataCriteriaSectionElem - * the data criteria section elem - * @param clauseName - * the clause name - * @return the node - * @throws XPathExpressionException - * the x path expression exception - */ - private Node generateFunctionalOpHQMF(Node functionalNode, Element dataCriteriaSectionElem, String clauseName) - throws XPathExpressionException { - Node node = null; - if (functionalNode.getChildNodes() != null) { - Node firstChildNode = functionalNode.getFirstChild(); - String firstChildName = firstChildNode.getNodeName(); - switch (firstChildName) { - case SET_OP: - String functionOpType = functionalNode.getAttributes().getNamedItem(TYPE).getNodeValue(); - if (FUNCTIONAL_OPS_NON_SUBSET.containsKey(functionOpType.toUpperCase()) - || FUNCTIONAL_OPS_SUBSET.containsKey(functionOpType.toUpperCase())) { - node = generateSetOpHQMF(firstChildNode, dataCriteriaSectionElem, clauseName); - } - break; - case ELEMENT_REF: - node = generateElementRefHQMF(firstChildNode, dataCriteriaSectionElem, clauseName); - break; - case RELATIONAL_OP: - node = generateRelOpHQMF(firstChildNode, dataCriteriaSectionElem, clauseName); - break; - case FUNCTIONAL_OP: - // findFunctionalOpChild(firstChildNode, dataCriteriaSectionElem); - break; - case SUB_TREE_REF: - node = generateSubTreeHQMFInFunctionalOp(firstChildNode, dataCriteriaSectionElem, clauseName); - break; - default: - // Dont do anything - break; - } - - String localVarName = clauseName; - - localVarName = localVarName.replace("$", ""); - Node parentNode = functionalNode.getParentNode(); - if (parentNode != null && parentNode.getNodeName().equalsIgnoreCase("subTree")) { - if (parentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { - String isQdmVariable = parentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - localVarName = localVarName.replace("$", ""); - localVarName = "qdm_var_" + localVarName; - } - } - localVarName = localVarName + "_" + UUIDUtilClient.uuid(5); - localVarName = StringUtils.deleteWhitespace(localVarName); - updateLocalVar(node, localVarName); - } - } - return node; - - } - - /** - * Method to generate HQMF for function Ops with first child as subTreeRef. In - * this case grouperCriteria will be generated for SubTreeRef with Excerpt entry - * inside it for functional Op. - * - * @param firstChildNode - * - SubTreeRef Node. - * @param dataCriteriaSectionElem - * - Data Criteria Element. - * @param clauseName - * the clause name - * @return the node - * @throws XPathExpressionException - * the x path expression exception - */ - private Node generateSubTreeHQMFInFunctionalOp(Node firstChildNode, Element dataCriteriaSectionElem, - String clauseName) throws XPathExpressionException { - Node parentNode = firstChildNode.getParentNode(); - - // temp node. - String subTreeUUID = firstChildNode.getAttributes().getNamedItem(ID).getNodeValue(); - String xpath = "/measure/subTreeLookUp/subTree[@uuid='" + subTreeUUID + "']"; - Node subTreeNode = measureExport.getSimpleXmlProcessor() - .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); - String firstChildNameOfSubTree = subTreeNode.getFirstChild().getNodeName(); - if (FUNCTIONAL_OP.equals(firstChildNameOfSubTree)) { - String firstChildNodeName = parentNode.getAttributes().getNamedItem(TYPE).getNodeValue(); - if (!SATISFIES_ALL.equalsIgnoreCase(firstChildNodeName) - || !SATISFIES_ANY.equalsIgnoreCase(firstChildNodeName) || !AGE_AT.equals(firstChildNodeName)) { - return null; - } - } - Element root = measureExport.getHqmfXmlProcessor().getOriginalDoc().createElement("temp"); - generateSubTreeHQMF(firstChildNode, root, clauseName); - Element entryElement = (Element) root.getFirstChild(); - Node firstChild = entryElement.getFirstChild(); - if ("localVariableName".equals(firstChild.getNodeName())) { - firstChild = firstChild.getNextSibling(); - } - Element excerpt = generateExcerptEntryForFunctionalNode(parentNode, null, measureExport.getHqmfXmlProcessor(), - entryElement); - if (excerpt != null) { - firstChild.appendChild(excerpt); - } - dataCriteriaSectionElem.appendChild(entryElement); - return entryElement; - } - - /** - * This will take care of the use case where a user can create a Clause with - * only one QDM elementRef inside it. We will make a copy of the original entry - * for QDM and update the id@root and id@extension for it. This will server as - * an entry for the Clause. - * - * @param elementRefNode - * the element ref node - * @param parentNode - * the parent node - * @param clauseName - * the clause name - * @return the node - * @throws XPathExpressionException - * the x path expression exception - */ - private Node generateElementRefHQMF(Node elementRefNode, Node parentNode, String clauseName) - throws XPathExpressionException { - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - Node node = null; - String ext = getElementRefExt(elementRefNode, measureExport.getSimpleXmlProcessor()); - String root = elementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - String localVariableName = clauseName; - Node idNodeQDM = hqmfXmlProcessor.findNode(hqmfXmlProcessor.getOriginalDoc(), - "//entry/*/id[@root='" + root + "'][@extension=\"" + ext + "\"]"); - if (idNodeQDM != null) { - Node entryElem = idNodeQDM.getParentNode().getParentNode().cloneNode(true); - Node newIdNode = getTagFromEntry(entryElem, ID); - - if (newIdNode == null) { - return null; - } - - String idroot = "0"; - Node parNode = elementRefNode.getParentNode(); - if (parNode != null && SUB_TREE.equals(parNode.getNodeName())) { - idroot = parNode.getAttributes().getNamedItem(UUID).getNodeValue(); - // Added logic to show qdm_variable in extension if clause is of qdm variable - // type. - String isQdmVariable = parNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - if (isQdmVariable.equalsIgnoreCase(TRUE)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (parNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" + parNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + "of_"; - } - if (occText != null) { - ext = occText + "qdm_var_" + ext; - } else { - ext = "qdm_var_" + ext; - localVariableName = "qdm_var_" + localVariableName; - } - } - localVariableName = localVariableName + "_" + UUIDUtilClient.uuid(5); - localVariableName = StringUtils.deleteWhitespace(localVariableName); - ((Element) newIdNode).setAttribute(ROOT, idroot); - ((Element) newIdNode).setAttribute(EXTENSION, ext); - Node localVariableNode = entryElem.getFirstChild(); - if (localVariableNode.getAttributes().getNamedItem("value") != null) { - localVariableNode.getAttributes().getNamedItem("value").setNodeValue(localVariableName); - } - - parentNode.appendChild(entryElem); - node = entryElem; - } else { - // if the the parentNode for ElementRef is other than SubTreeNode - Element excerptElement = null; - Node subTreeParentNode = checkIfSubTree(parNode); - if (subTreeParentNode != null) { - root = subTreeParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); - if (subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { - String isQdmVariable = subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) - .getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (subTreeParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" - + subTreeParentNode.getAttributes().getNamedItem("instance").getNodeValue() - + "of_"; - } - if (occText != null) { - ext = occText + "qdm_var_" + ext; - } else { - ext = "qdm_var_" + ext; - } - } - } - } else { - root = java.util.UUID.randomUUID().toString(); - } - - Node entryNodeForElementRef = idNodeQDM.getParentNode().getParentNode(); - Node clonedEntryNodeForElementRef = entryNodeForElementRef.cloneNode(true); - NodeList idChildNodeList = ((Element) clonedEntryNodeForElementRef).getElementsByTagName(ID); - if (idChildNodeList != null && idChildNodeList.getLength() > 0) { - Node idChildNode = idChildNodeList.item(0); - idChildNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); - idChildNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); - } - - Node firstChild = clonedEntryNodeForElementRef.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { - firstChild = firstChild.getNextSibling(); - } - // Added logic to show qdm_variable in extension if clause is of qdm variable - // type. - if (FUNCTIONAL_OP.equals(parNode.getNodeName())) { - excerptElement = generateExcerptEntryForFunctionalNode(parNode, elementRefNode, hqmfXmlProcessor, - clonedEntryNodeForElementRef); - } - - if (excerptElement != null) { - - firstChild.appendChild(excerptElement); - } - parentNode.appendChild(clonedEntryNodeForElementRef); - node = clonedEntryNodeForElementRef; - - } - updateLocalVar(node, ext); - } - - return node; - } - - /** - * This will take care of the use case where a user can create a Clause with - * only one child Clause inside it. If HQMF for the child clause is already - * generated, then since we have no way of referencing this child clause using - * directly, we are adding it to a default UNION grouper. - * - * If it isnt generated then we generate it and then add a criteriaRef to it - * inside a default UNION. - * - * @param subTreeRefNode - * the sub tree ref node - * @param parentNode - * the parent node - * @param clauseName - * the clause name - * @return the node - * @throws XPathExpressionException - * the x path expression exception - */ - private Node generateSubTreeHQMF(Node subTreeRefNode, Node parentNode, String clauseName) - throws XPathExpressionException { - - String subTreeUUID = subTreeRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - - /* - * Check if the Clause has already been generated. If it is not generated yet, - * then generate it by calling the 'generateSubTreeXML' method. - */ - if (!subTreeNodeMap.containsKey(subTreeUUID)) { - String xpath = "/measure/subTreeLookUp/subTree[@uuid='" + subTreeUUID + "']"; - Node subTreeNode = measureExport.getSimpleXmlProcessor() - .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); - generateSubTreeXML(subTreeNode, false); - } - - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - - // creating Entry Tag - Element entryElem = hqmfXmlProcessor.getOriginalDoc().createElement(ENTRY); - entryElem.setAttribute(TYPE_CODE, "DRIV"); - String root = java.util.UUID.randomUUID().toString(); - String ext = subTreeRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - String localVarName = clauseName; - localVarName = localVarName.replace("$", ""); - Node parNode = checkIfSubTree(subTreeRefNode.getParentNode()); - if (parNode != null) { - root = parNode.getAttributes().getNamedItem(UUID).getNodeValue(); - if (parNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { - String isQdmVariable = parNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (parNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" + parNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + "of_"; - } - if (occText != null) { - ext = occText + "qdm_var_" + ext; - } else { - ext = "qdm_var_" + ext; - localVarName = "qdm_var_" + localVarName; - } - } - } - } - - Node grouperElem = generateEmptyGrouper(hqmfXmlProcessor, root, ext); - - // generate comment - Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment( - "outBoundRelationship for " + subTreeRefNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - grouperElem.appendChild(comment); - - // generate outboundRelationship - Element outboundRelElem = generateEmptyOutboundElem(hqmfXmlProcessor); - Element conjunctionCodeElem = hqmfXmlProcessor.getOriginalDoc().createElement(CONJUNCTION_CODE); - conjunctionCodeElem.setAttribute(CODE, "OR"); - - outboundRelElem.appendChild(conjunctionCodeElem); - generateCritRefForNode(outboundRelElem, subTreeRefNode); - - grouperElem.appendChild(outboundRelElem); - - Element localVarElem = hqmfXmlProcessor.getOriginalDoc().createElement(LOCAL_VARIABLE_NAME); - localVarName = localVarName + "_" + UUIDUtilClient.uuid(5); - localVarName = StringUtils.deleteWhitespace(localVarName); - localVarElem.setAttribute(VALUE, localVarName); - entryElem.appendChild(localVarElem); - - entryElem.appendChild(grouperElem); - parentNode.appendChild(entryElem); - return entryElem; - - } - - /** - * This method wil generate HQMF code for setOp (UNION,INTERSECTION). - * - * @param setOpNode - * the set op node - * @param parentNode - * the parent node - * @param clauseName - * the clause name - * @return the node - * @throws XPathExpressionException - * the x path expression exception - */ - private Node generateSetOpHQMF(Node setOpNode, Node parentNode, String clauseName) throws XPathExpressionException { - - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - // DISPLAY NAME is used instead of type as it is in Title case. - String setOpType = setOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - String conjunctionType = "OR"; - - if ("union".equalsIgnoreCase(setOpType) || SATISFIES_ANY.equalsIgnoreCase(setOpType)) { - conjunctionType = "OR"; - } else if ("intersection".equalsIgnoreCase(setOpType) || SATISFIES_ALL.equalsIgnoreCase(setOpType)) { - conjunctionType = "AND"; - } - - // creating Entry Tag - Element entryElem = hqmfXmlProcessor.getOriginalDoc().createElement(ENTRY); - entryElem.setAttribute(TYPE_CODE, "DRIV"); - - // creating grouperCriteria element - String root = "0"; - // String ext = setOpType.toUpperCase(); - - String ext = setOpType + "_" + setOpNode.getAttributes().getNamedItem(UUID).getNodeValue(); - String localVariableName = clauseName + "_" + setOpNode.getAttributes().getNamedItem(UUID).getNodeValue(); - Node subTreeParentNode = checkIfSubTree(setOpNode.getParentNode()); - if (subTreeParentNode != null) { - root = subTreeParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); - if (subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { - String isQdmVariable = subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (subTreeParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" + subTreeParentNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() - + "of_"; - } - if (occText != null) { - ext = occText + "qdm_var_" + ext; - } else { - ext = "qdm_var_" + ext; - } - localVariableName = "qdm_var_" + localVariableName; - } - } - } else { - root = java.util.UUID.randomUUID().toString(); - } - - Node grouperElem = generateEmptyGrouper(hqmfXmlProcessor, root, ext); - Node templateIdNode = getTemplateIdForSatisfies(hqmfXmlProcessor, setOpType); - if (templateIdNode != null) { - grouperElem.insertBefore(templateIdNode, grouperElem.getFirstChild()); - } - - NodeList childNodes = setOpNode.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node childNode = childNodes.item(i); - String childName = childNode.getNodeName(); - if ("comment".equals(childName)) { - continue; - } - - // generate comment - Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment( - "outBoundRelationship for " + childNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - grouperElem.appendChild(comment); - - // generate outboundRelationship - Element outboundRelElem = generateEmptyOutboundElem(hqmfXmlProcessor); - Element conjunctionCodeElem = hqmfXmlProcessor.getOriginalDoc().createElement(CONJUNCTION_CODE); - conjunctionCodeElem.setAttribute(CODE, conjunctionType); - - outboundRelElem.appendChild(conjunctionCodeElem); - if (ELEMENT_REF.equals(childName) || SUB_TREE_REF.equals(childName)) { - generateCritRefForNode(outboundRelElem, childNode); - } else { - switch (childName) { - case SET_OP: - generateCritRefSetOp(parentNode, hqmfXmlProcessor, childNode, outboundRelElem, clauseName); - break; - case RELATIONAL_OP: - generateCritRefRelOp(parentNode, hqmfXmlProcessor, childNode, outboundRelElem, clauseName); - break; - case FUNCTIONAL_OP: - generateCritRefFunctionalOp(childNode, outboundRelElem, clauseName); - break; - - default: - // Dont do anything - break; - } - } - grouperElem.appendChild(outboundRelElem); - } - - // Added logic to show qdm_variable in extension if clause is of qdm variable - // type. - Node grouperEntryNode = grouperElem.cloneNode(true); - if (FUNCTIONAL_OP.equals(setOpNode.getParentNode().getNodeName())) { - Element excerptElement = generateExcerptEntryForFunctionalNode(setOpNode.getParentNode(), null, - hqmfXmlProcessor, grouperEntryNode); - // Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("excerpt - // for - // "+setOpNode.getParentNode().getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - // grouperElem.appendChild(comment); - grouperElem.appendChild(excerptElement); - } - Element localVarElem = hqmfXmlProcessor.getOriginalDoc().createElement(LOCAL_VARIABLE_NAME); - localVarElem.setAttribute(VALUE, StringUtils.deleteWhitespace(localVariableName)); - entryElem.appendChild(localVarElem); - - entryElem.appendChild(grouperElem); - parentNode.appendChild(entryElem); - - return entryElem; - } - - /** - * Generate crit ref functional op. - * - * @param childNode - * -Node - * @param outboundRelElem - * - outBoundElement - * @param clauseName - * the clause name - * @throws XPathExpressionException - * -Exception - */ - private void generateCritRefFunctionalOp(Node childNode, Element outboundRelElem, String clauseName) - throws XPathExpressionException { - Element dataCriteriaSectionElem = (Element) measureExport.getHqmfXmlProcessor().getOriginalDoc() - .getElementsByTagName(DATA_CRITERIA_SECTION).item(0); - Node entryNode = generateFunctionalOpHQMF(childNode, dataCriteriaSectionElem, clauseName); - if (entryNode != null && entryNode.getNodeName().equals(ENTRY)) { - Node fChild = entryNode.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(fChild.getNodeName())) { - fChild = fChild.getNextSibling(); - } - // create criteriaRef - Element criteriaReference = measureExport.getHqmfXmlProcessor().getOriginalDoc() - .createElement(CRITERIA_REFERENCE); - criteriaReference.setAttribute(CLASS_CODE, fChild.getAttributes().getNamedItem(CLASS_CODE).getNodeValue()); - criteriaReference.setAttribute(MOOD_CODE, fChild.getAttributes().getNamedItem(MOOD_CODE).getNodeValue()); - NodeList childNodeList = fChild.getChildNodes(); - for (int j = 0; j < childNodeList.getLength(); j++) { - Node entryChildNodes = childNodeList.item(j); - if (entryChildNodes.getNodeName().equalsIgnoreCase(ID)) { - Element id = measureExport.getHqmfXmlProcessor().getOriginalDoc().createElement(ID); - id.setAttribute(ROOT, entryChildNodes.getAttributes().getNamedItem(ROOT).getNodeValue()); - id.setAttribute(EXTENSION, entryChildNodes.getAttributes().getNamedItem(EXTENSION).getNodeValue()); - criteriaReference.appendChild(id); - outboundRelElem.appendChild(criteriaReference); - break; - } - } - } - } - - /** - * This method is used to create a tag for SATISFIES ALL/SATISFIES - * ANY functionalOps. These are functionalOp's but are converted to setOps and - * treated as Groupers. - * - * @param hqmfXmlProcessor - * the hqmf xml processor - * @param type - * the type - * @return the template id for satisfies - */ - private Node getTemplateIdForSatisfies(XmlProcessor hqmfXmlProcessor, String type) { - Node templateIdNode = null; - - if (SATISFIES_ALL.equalsIgnoreCase(type) || SATISFIES_ANY.equalsIgnoreCase(type)) { - templateIdNode = hqmfXmlProcessor.getOriginalDoc().createElement(TEMPLATE_ID); - Element itemNode = hqmfXmlProcessor.getOriginalDoc().createElement(ITEM); - - // initialize rootOID with the OID for SATISFIES ALL - String rootOID = "2.16.840.1.113883.10.20.28.3.109"; - // if we are dealing with SATISFIES ANY change the OID - if (SATISFIES_ANY.equalsIgnoreCase(type)) { - rootOID = "2.16.840.1.113883.10.20.28.3.108"; - } - itemNode.setAttribute(ROOT, rootOID); - - templateIdNode.appendChild(itemNode); - } - - return templateIdNode; - } - - /** - * Generate rel op hqmf. - * - * @param relOpNode - * the rel op node - * @param dataCriteriaSectionElem - * the data criteria section elem - * @param clauseName - * the clause name - * @return the node - * @throws XPathExpressionException - * the x path expression exception - */ - private Node generateRelOpHQMF(Node relOpNode, Node dataCriteriaSectionElem, String clauseName) - throws XPathExpressionException { - Node finalNode = null; - if (relOpNode.getChildNodes().getLength() == 2) { - Node lhsNode = relOpNode.getFirstChild(); - Node rhsNode = relOpNode.getLastChild(); - String lhsName = lhsNode.getNodeName(); - - // NamedNodeMap attribMap = relOpNode.getAttributes(); - // String relDisplayName = - // StringUtils.deleteWhitespace(attribMap.getNamedItem(DISPLAY_NAME).getNodeValue()); - // String relUUID = attribMap.getNamedItem(UUID).getNodeValue(); - // String localVarName = "localVar_"+relDisplayName+"_"+relUUID; - - String localVarName = clauseName; - Node parentNode = relOpNode.getParentNode(); - if (parentNode != null) { - if (parentNode.getNodeName().equalsIgnoreCase("subTree") && - parentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { - String isQdmVariable = parentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - localVarName = localVarName.replace("$", ""); - localVarName = "qdm_var_" + localVarName; - } - } - } - localVarName = localVarName + "_" + UUIDUtilClient.uuid(5); - localVarName = StringUtils.deleteWhitespace(localVarName); - if (ELEMENT_REF.equals(lhsName)) { - finalNode = getrelOpLHSQDM(relOpNode, dataCriteriaSectionElem, lhsNode, rhsNode, clauseName); - } else if (RELATIONAL_OP.equals(lhsName)) { - finalNode = getrelOpLHSRelOp(relOpNode, dataCriteriaSectionElem, lhsNode, rhsNode, clauseName); - Node relOpParentNode = relOpNode.getParentNode(); - if (relOpParentNode.getNodeName().equalsIgnoreCase(FUNCTIONAL_OP)) { - Element excerptElement = generateExcerptEntryForFunctionalNode(relOpNode.getParentNode(), lhsNode, - measureExport.getHqmfXmlProcessor(), finalNode); - if (excerptElement != null) { - Node firstNode = finalNode.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstNode.getNodeName())) { - firstNode = firstNode.getNextSibling(); - } - // Comment comment = - // measureExport.getHQMFXmlProcessor().getOriginalDoc().createComment("entry for - // "+relOpNode.getParentNode().getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - // firstNode.appendChild(comment); - firstNode.appendChild(excerptElement); - } - } - // return finalNode; - } else if (SET_OP.equals(lhsName)) { - finalNode = getrelOpLHSSetOp(relOpNode, dataCriteriaSectionElem, lhsNode, rhsNode, clauseName); - Node relOpParentNode = relOpNode.getParentNode(); - if (relOpParentNode.getNodeName().equalsIgnoreCase(FUNCTIONAL_OP)) { - Element excerptElement = generateExcerptEntryForFunctionalNode(relOpNode.getParentNode(), lhsNode, - measureExport.getHqmfXmlProcessor(), finalNode); - if (excerptElement != null) { - Node firstNode = finalNode.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstNode.getNodeName())) { - firstNode = firstNode.getNextSibling(); - } - // Comment comment = - // measureExport.getHQMFXmlProcessor().getOriginalDoc().createComment("entry for - // "+relOpNode.getParentNode().getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - // firstNode.appendChild(comment); - firstNode.appendChild(excerptElement); - } - } - // return finalNode; - } else if (SUB_TREE_REF.equals(lhsName) || FUNCTIONAL_OP.equalsIgnoreCase(lhsName)) { - Node functionalOpNodeWithChildQDM = checkLHSFunctionalOpWithChildQDM(lhsNode); - if (functionalOpNodeWithChildQDM != null) { - // Do something godawful here. - Node functionEntryNode = generateFunctionalOpHQMF(functionalOpNodeWithChildQDM, - (Element) dataCriteriaSectionElem, clauseName); - dataCriteriaSectionElem.appendChild(functionEntryNode); - finalNode = createSpecialGrouperForRelOp(relOpNode, functionEntryNode, rhsNode, - dataCriteriaSectionElem, clauseName); - } else if (FUNCTIONAL_OP.equalsIgnoreCase(lhsName)) { - finalNode = getFunctionalOpLHS(relOpNode, dataCriteriaSectionElem, lhsNode, rhsNode, clauseName); - } else { - finalNode = getrelOpLHSSubtree(relOpNode, dataCriteriaSectionElem, lhsNode, rhsNode, clauseName); - } - - } - // else if(FUNCTIONAL_OP.equalsIgnoreCase(lhsName)) { - // finalNode = getFunctionalOpLHS(relOpNode, dataCriteriaSectionElem, lhsNode, - // rhsNode, clauseName); - // } - if (parentNode.getNodeName().equalsIgnoreCase("subTree")) { - updateLocalVar(finalNode, localVarName); - } - } else { - logger.debug("Relational Op:" + relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() - + " does not have exactly 2 children. Skipping HQMF for it."); - } - return finalNode; - } - - /** - * When we have a case of "First:(Encounter,Performed:Inpatient) During - * Measurement Period"; we need to generate a entry with Grouper. - * - * @param relOpNode - * the rel op node - * @param functionEntryNode - * the function entry node - * @param rhsNode - * the rhs node - * @param dataCriteriaSectionElem - * the data criteria section elem - * @param clauseName - * the clause name - * @return the node - * @throws XPathExpressionException - * the x path expression exception - */ - private Node createSpecialGrouperForRelOp(Node relOpNode, Node functionEntryNode, Node rhsNode, - Node dataCriteriaSectionElem, String clauseName) throws XPathExpressionException { - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - - // creating Entry Tag - Element entryElem = hqmfXmlProcessor.getOriginalDoc().createElement(ENTRY); - entryElem.setAttribute(TYPE_CODE, "DRIV"); - - String localVariableName = relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - Element localVarElem = hqmfXmlProcessor.getOriginalDoc().createElement(LOCAL_VARIABLE_NAME); - localVariableName = localVariableName + "_" + UUIDUtilClient.uuid(5); - localVariableName = StringUtils.deleteWhitespace(localVariableName); - localVarElem.setAttribute(VALUE, localVariableName); - entryElem.appendChild(localVarElem); - - String root = relOpNode.getAttributes().getNamedItem(UUID).getNodeValue(); - String ext = StringUtils.deleteWhitespace(relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() - + "_" + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); - - Node grouperElem = generateEmptyGrouper(hqmfXmlProcessor, root, ext); - entryElem.appendChild(grouperElem); - - Node subTreeParentNode = checkIfSubTree(relOpNode.getParentNode()); - Node idNode = findNode(entryElem, "ID"); - if (idNode != null && subTreeParentNode != null) { - String idExtension = idNode.getAttributes().getNamedItem(EXTENSION).getNodeValue(); - String idRoot = idNode.getAttributes().getNamedItem(ROOT).getNodeValue(); - root = subTreeParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); - ext = StringUtils.deleteWhitespace(relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() - + "_" + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); - if (subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { - String isQdmVariable = subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (subTreeParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" + subTreeParentNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() - + "of_"; - } - if (occText != null) { - ext = occText + "qdm_var_" + ext; - } else { - ext = "qdm_var_" + ext; - } - } - } - idNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); - idNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); - // Updated Excerpt tag idNode root and extension. - // String hqmfXmlString = measureExport.getHQMFXmlProcessor().getOriginalXml(); - Node idNodeExcerpt = measureExport.getHqmfXmlProcessor().findNode( - measureExport.getHqmfXmlProcessor().getOriginalDoc(), - "//entry/*/excerpt/*/id[@root='" + idRoot + "'][@extension=\"" + idExtension + "\"]"); - if (idNodeExcerpt != null) { - idNodeExcerpt.getAttributes().getNamedItem(ROOT).setNodeValue(root); - idNodeExcerpt.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); - } - - } - - // Element temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, - // measureExport.getHQMFXmlProcessor()); - Element temporallyRelatedInfoNode = null; - if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { - temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, measureExport.getHqmfXmlProcessor()); - } else { - temporallyRelatedInfoNode = measureExport.getHqmfXmlProcessor().getOriginalDoc() - .createElement(OUTBOUND_RELATIONSHIP); - temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); - } - handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); - Node firstChild = entryElem.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { - firstChild = firstChild.getNextSibling(); - } - NodeList outBoundList = ((Element) firstChild).getElementsByTagName(OUTBOUND_RELATIONSHIP); - if (outBoundList != null && outBoundList.getLength() > 0) { - Node outBound = outBoundList.item(0); - firstChild.insertBefore(temporallyRelatedInfoNode, outBound); - } else { - NodeList excerptList = ((Element) firstChild).getElementsByTagName(EXCERPT); - if (excerptList != null && excerptList.getLength() > 0) { - Node excerptNode = excerptList.item(0); - firstChild.insertBefore(temporallyRelatedInfoNode, excerptNode); - } else { - firstChild.appendChild(temporallyRelatedInfoNode); - } - } - - // Add a outBound Relationship for the 'functionEntryNode' passed above. - Element outBoundForFunction = measureExport.getHqmfXmlProcessor().getOriginalDoc() - .createElement(OUTBOUND_RELATIONSHIP); - outBoundForFunction.setAttribute(TYPE_CODE, "COMP"); - Node idNodeForFunctionEntryNode = findNode(functionEntryNode, "ID"); - Node excerptNodeForFunctionEntryNode = findNode(functionEntryNode, "excerpt"); - Node idNodeInExcerptNode = findNode(excerptNodeForFunctionEntryNode, "id"); - String newExtension = StringUtils.deleteWhitespace(clauseName) + "_" - + idNodeForFunctionEntryNode.getAttributes().getNamedItem(EXTENSION).getNodeValue(); - - idNodeForFunctionEntryNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(newExtension); - idNodeInExcerptNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(newExtension); - - Node firstChildOfFunctionEntryElem = functionEntryNode.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstChildOfFunctionEntryElem.getNodeName())) { - firstChildOfFunctionEntryElem = firstChildOfFunctionEntryElem.getNextSibling(); - } - NamedNodeMap criteriaNodeAttributeMap = firstChildOfFunctionEntryElem.getAttributes(); - if (criteriaNodeAttributeMap.getNamedItem(CLASS_CODE) != null - && criteriaNodeAttributeMap.getNamedItem(MOOD_CODE) != null) { - // create criteriaRef - Element criteriaReference = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - criteriaReference.setAttribute(CLASS_CODE, - criteriaNodeAttributeMap.getNamedItem(CLASS_CODE).getNodeValue()); - criteriaReference.setAttribute(MOOD_CODE, - criteriaNodeAttributeMap.getNamedItem(MOOD_CODE).getNodeValue()); - - Node idNodeForFunctionEntryNode_Clone = idNodeForFunctionEntryNode.cloneNode(true); - criteriaReference.appendChild(idNodeForFunctionEntryNode_Clone); - - outBoundForFunction.appendChild(criteriaReference); - grouperElem.appendChild(outBoundForFunction); - } - dataCriteriaSectionElem.appendChild(entryElem); - return entryElem; - } - - /** - * This is to be called when you want to check If the node passed is a - * FunctionOp with it's child being an elementRef/QDM. If the node passed is a - * SubTree/Clause node then this will "recursively" look into the child of that - * SubTree/Clause node to see if that child is a FunctionOp with child being an - * elementRef/QDM. - * - * @param node - * the node - * @return the node - * @throws XPathExpressionException - * the x path expression exception - */ - private Node checkLHSFunctionalOpWithChildQDM(Node node) throws XPathExpressionException { - Node returnFunctionalNode = null; - - String nodeName = node.getNodeName(); - if (FUNCTIONAL_OP.equalsIgnoreCase(nodeName)) { - returnFunctionalNode = node; - /* - * Node childNode = node.getFirstChild(); if(childNode != null && - * ELEMENT_REF.equals(childNode.getNodeName())){ returnFunctionalNode = node; } - */ - } else if (SUB_TREE_REF.equals(nodeName)) { - String subTreeUUID = node.getAttributes().getNamedItem(ID).getNodeValue(); - - String xpath = "/measure/subTreeLookUp/subTree[@uuid='" + subTreeUUID + "']"; - Node subTreeNode = measureExport.getSimpleXmlProcessor() - .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); - - Node childNode = subTreeNode.getFirstChild(); - if (childNode != null) { - returnFunctionalNode = checkLHSFunctionalOpWithChildQDM(childNode); - } - } - return returnFunctionalNode; - } - - /** - * Gets the functional op lhs. - * - * @param relOpNode - * the rel op node - * @param dataCriteriaSectionElem - * the data criteria section elem - * @param lhsNode - * the lhs node - * @param rhsNode - * the rhs node - * @param clauseName - * the clause name - * @return the functional op lhs - * @throws XPathExpressionException - * the x path expression exception - */ - private Node getFunctionalOpLHS(Node relOpNode, Node dataCriteriaSectionElem, Node lhsNode, Node rhsNode, - String clauseName) throws XPathExpressionException { - Node entryNode = generateFunctionalOpHQMF(lhsNode, (Element) dataCriteriaSectionElem, clauseName); - - // Comment comment = - // measureExport.getHQMFXmlProcessor().getOriginalDoc().createComment("entry for - // "+relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - // dataCriteriaSectionElem.appendChild(comment); - if (entryNode != null) { - Node subTreeParentNode = checkIfSubTree(relOpNode.getParentNode()); - Node idNode = findNode(entryNode, "ID"); - if (idNode != null && subTreeParentNode != null) { - String idExtension = idNode.getAttributes().getNamedItem(EXTENSION).getNodeValue(); - String idRoot = idNode.getAttributes().getNamedItem(ROOT).getNodeValue(); - String root = subTreeParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); - String ext = StringUtils - .deleteWhitespace(relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + "_" - + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); - if (subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { - String isQdmVariable = subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (subTreeParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" + subTreeParentNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() - + "of_"; - } - if (occText != null) { - ext = occText + "qdm_var_" + ext; - } else { - ext = "qdm_var_" + ext; - } - } - } - idNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); - idNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); - // Updated Excerpt tag idNode root and extension. - // String hqmfXmlString = measureExport.getHQMFXmlProcessor().getOriginalXml(); - Node idNodeExcerpt = measureExport.getHqmfXmlProcessor().findNode( - measureExport.getHqmfXmlProcessor().getOriginalDoc(), - "//entry/*/excerpt/*/id[@root='" + idRoot + "'][@extension=\"" + idExtension + "\"]"); - if (idNodeExcerpt != null) { - idNodeExcerpt.getAttributes().getNamedItem(ROOT).setNodeValue(root); - idNodeExcerpt.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); - } - - } - - // Element temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, - // measureExport.getHQMFXmlProcessor()); - Element temporallyRelatedInfoNode = null; - if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { - temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, measureExport.getHqmfXmlProcessor()); - } else { - temporallyRelatedInfoNode = measureExport.getHqmfXmlProcessor().getOriginalDoc() - .createElement(OUTBOUND_RELATIONSHIP); - temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); - } - handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); - Node firstChild = entryNode.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { - firstChild = firstChild.getNextSibling(); - } - NodeList outBoundList = ((Element) firstChild).getElementsByTagName(OUTBOUND_RELATIONSHIP); - if (outBoundList != null && outBoundList.getLength() > 0) { - Node outBound = outBoundList.item(0); - firstChild.insertBefore(temporallyRelatedInfoNode, outBound); - } else { - NodeList excerptList = ((Element) firstChild).getElementsByTagName(EXCERPT); - if (excerptList != null && excerptList.getLength() > 0) { - Node excerptNode = excerptList.item(0); - firstChild.insertBefore(temporallyRelatedInfoNode, excerptNode); - } else { - firstChild.appendChild(temporallyRelatedInfoNode); - } - } - dataCriteriaSectionElem.appendChild(entryNode); - } - /* - * else{ Comment commnt = measureExport.getHQMFXmlProcessor().getOriginalDoc(). - * createComment("CHECK:Could not find an entry for functionalOp:"+lhsNode. - * getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - * dataCriteriaSectionElem.appendChild(commnt); } - */ - return entryNode; - } - - /** - * Find node. - * - * @param criteriaNodeInEntry - * the criteria node in entry - * @param nodeName - * the node name - * @return idNode - */ - private Node findNode(Node criteriaNodeInEntry, String nodeName) { - Node idNode = null; - for (int i = 0; i < criteriaNodeInEntry.getChildNodes().getLength(); i++) { - Node childNode = criteriaNodeInEntry.getChildNodes().item(i); - String childNodeName = childNode.getNodeName(); - if (childNodeName.contains("Criteria")) { - NodeList criteriaChildNodes = childNode.getChildNodes(); - for (int j = 0; j < criteriaChildNodes.getLength(); j++) { - Node criteriaChildNode = criteriaChildNodes.item(j); - if (nodeName.equalsIgnoreCase(criteriaChildNode.getNodeName())) { - idNode = criteriaChildNode; - break; - } - } - break; - } - } - return idNode; - } - - /** - * Gets the rel op lhs subtree. - * - * @param relOpNode - * the rel op node - * @param dataCriteriaSectionElem - * the data criteria section elem - * @param lhsNode - * the lhs node - * @param rhsNode - * the rhs node - * @param clauseName - * the clause name - * @return the rel op lhs subtree - */ - private Node getrelOpLHSSubtree(Node relOpNode, Node dataCriteriaSectionElem, Node lhsNode, Node rhsNode, - String clauseName) { - - try { - String subTreeUUID = lhsNode.getAttributes().getNamedItem(ID).getNodeValue(); - String root = subTreeUUID; - - Node relOpParentNode = relOpNode.getParentNode(); - - String xpath = "/measure/subTreeLookUp/subTree[@uuid='" + subTreeUUID + "']"; - Node subTreeNode = measureExport.getSimpleXmlProcessor() - .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); - if (subTreeNode != null) { - /** - * Check if the Clause has already been generated. If it is not generated yet, - * then generate it by calling the 'generateSubTreeXML' method. - */ - - if (!subTreeNodeMap.containsKey(subTreeUUID)) { - generateSubTreeXML(subTreeNode, false); - } - String isQdmVariable = subTreeNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - Node firstChild = subTreeNode.getFirstChild(); - String firstChildName = firstChild.getNodeName(); - - String ext = StringUtils - .deleteWhitespace(firstChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - if (FUNCTIONAL_OP.equals(firstChildName) || RELATIONAL_OP.equals(firstChildName) - || SET_OP.equals(firstChildName)) { - ext += "_" + firstChild.getAttributes().getNamedItem(UUID).getNodeValue(); - } - - if (ELEMENT_REF.equals(firstChildName)) { - ext = getElementRefExt(firstChild, measureExport.getSimpleXmlProcessor()); - } else if (FUNCTIONAL_OP.equals(firstChildName)) { - if (firstChild.getFirstChild() != null) { - Node functionChild = firstChild.getFirstChild(); - if (functionChild != null) { - if (functionChild.getNodeName().equalsIgnoreCase(SUB_TREE_REF)) { - ext = functionChild.getAttributes().getNamedItem(ID).getNodeValue(); - } else if (functionChild.getNodeName().equalsIgnoreCase(ELEMENT_REF)) { - ext = getElementRefExt(functionChild, measureExport.getSimpleXmlProcessor()); - } else { - ext = StringUtils - .deleteWhitespace(functionChild.getAttributes().getNamedItem(DISPLAY_NAME) - .getNodeValue() + "_" - + functionChild.getAttributes().getNamedItem(UUID).getNodeValue()) - .replaceAll(":", "_"); - } - } - } - } - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (subTreeNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" + subTreeNode.getAttributes().getNamedItem("instance").getNodeValue() + "of_"; - } - if (occText != null) { - ext = occText + "qdm_var_" + ext; - } else { - ext = "qdm_var_" + ext; - } - } - - Node idNodeQDM = measureExport.getHqmfXmlProcessor().findNode( - measureExport.getHqmfXmlProcessor().getOriginalDoc(), - "//entry/*/id[@root='" + root + "'][@extension=\"" + ext + "\"]"); - if (idNodeQDM != null) { - String newExt = StringUtils - .deleteWhitespace(relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + "_" - + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); - if (relOpParentNode != null && SUB_TREE.equals(relOpParentNode.getNodeName())) { - root = relOpParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); - Node qdmVarNode = relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE); - if (qdmVarNode != null) { - String isQdmVar = relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVar)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (relOpParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" - + relOpParentNode.getAttributes().getNamedItem("instance").getNodeValue() - + "of_"; - } - if (occText != null) { - newExt = occText + "qdm_var_" + newExt; - } else { - newExt = "qdm_var_" + newExt; - } - } - } - } else { - Node tempParentNode = checkIfParentSubTree(relOpParentNode); - if (tempParentNode != null) { - root = tempParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); - } - } - - Node parent = idNodeQDM.getParentNode(); - Node isOcc = subTreeNode.getAttributes().getNamedItem(INSTANCE_OF); - Node newEntryNode = null; - - if (TRUE.equals(isQdmVariable) && isOcc == null) { - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - // creating Entry Tag - Element entryElem = hqmfXmlProcessor.getOriginalDoc().createElement(ENTRY); - entryElem.setAttribute(TYPE_CODE, "DRIV"); - // create empty grouperCriteria - Node grouperElem = generateEmptyGrouper(hqmfXmlProcessor, root, newExt); - - // generate outboundRelationship - Element outboundRelElem = generateEmptyOutboundElem(hqmfXmlProcessor); - - NamedNodeMap attribMap = parent.getAttributes(); - String classCode = attribMap.getNamedItem(CLASS_CODE).getNodeValue(); - String moodCode = attribMap.getNamedItem(MOOD_CODE).getNodeValue(); - - // create criteriaRef - Element criteriaReference = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - criteriaReference.setAttribute(CLASS_CODE, classCode); - criteriaReference.setAttribute(MOOD_CODE, moodCode); - - Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - id.setAttribute(ROOT, subTreeUUID); - id.setAttribute(EXTENSION, ext); - - criteriaReference.appendChild(id); - outboundRelElem.appendChild(criteriaReference); - - Element localVarElem = hqmfXmlProcessor.getOriginalDoc().createElement(LOCAL_VARIABLE_NAME); - localVarElem.setAttribute(VALUE, ext); - entryElem.appendChild(localVarElem); - - grouperElem.appendChild(outboundRelElem); - entryElem.appendChild(grouperElem); - - newEntryNode = entryElem; - } else { - Node entryNodeForSubTree = idNodeQDM.getParentNode().getParentNode(); - newEntryNode = entryNodeForSubTree.cloneNode(true); - - NodeList idChildNodeList = ((Element) newEntryNode).getElementsByTagName(ID); - if (idChildNodeList != null && idChildNodeList.getLength() > 0) { - Node idChildNode = idChildNodeList.item(0); - idChildNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(newExt); - idChildNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); - } - } - - // Element temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, - // measureExport.getHQMFXmlProcessor()); - Element temporallyRelatedInfoNode = null; - if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { - temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, - measureExport.getHqmfXmlProcessor()); - } else { - temporallyRelatedInfoNode = measureExport.getHqmfXmlProcessor().getOriginalDoc() - .createElement(OUTBOUND_RELATIONSHIP); - temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); - } - - handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); - - Node firstNode = newEntryNode.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstNode.getNodeName())) { - firstNode = firstNode.getNextSibling(); - } - NodeList outBoundList = ((Element) firstNode).getElementsByTagName(OUTBOUND_RELATIONSHIP); - if (outBoundList != null && outBoundList.getLength() > 0) { - Node outBound = outBoundList.item(0); - firstNode.insertBefore(temporallyRelatedInfoNode, outBound); - } else { - firstNode.appendChild(temporallyRelatedInfoNode); - } - // Entry for Functional Op. - if (FUNCTIONAL_OP.equals(relOpParentNode.getNodeName())) { - Element excerptElement = generateExcerptEntryForFunctionalNode(relOpParentNode, lhsNode, - measureExport.getHqmfXmlProcessor(), firstNode.getParentNode()); - if (excerptElement != null) { - // Comment comment = - // measureExport.getHQMFXmlProcessor().getOriginalDoc().createComment("entry for - // "+relOpParentNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - // firstNode.appendChild(comment); - firstNode.appendChild(excerptElement); - } - } - // create comment node - // Comment comment = - // measureExport.getHQMFXmlProcessor().getOriginalDoc().createComment("entry for - // "+relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - // dataCriteriaSectionElem.appendChild(comment); - dataCriteriaSectionElem.appendChild(newEntryNode); - return newEntryNode; - - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** - * Gets the rel op lhs set op. - * - * @param relOpNode - * the rel op node - * @param dataCriteriaSectionElem - * the data criteria section elem - * @param lhsNode - * the lhs node - * @param rhsNode - * the rhs node - * @param clauseName - * the clause name - * @return the rel op lhs set op - */ - private Node getrelOpLHSSetOp(Node relOpNode, Node dataCriteriaSectionElem, Node lhsNode, Node rhsNode, - String clauseName) { - - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - // Node relOpParentNode = relOpNode.getParentNode(); - - try { - Node setOpEntryNode = generateSetOpHQMF(lhsNode, dataCriteriaSectionElem, clauseName); - // Element temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, - // hqmfXmlProcessor); - Node relOpParentNode = checkIfSubTree(relOpNode.getParentNode()); - if (relOpParentNode != null) { - NodeList idChildNodeList = ((Element) setOpEntryNode).getElementsByTagName(ID); - if (idChildNodeList != null && idChildNodeList.getLength() > 0) { - Node idChildNode = idChildNodeList.item(0); - String root = relOpParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); - String ext = StringUtils - .deleteWhitespace(relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + "_" - + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); - if (relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { - String isQdmVariable = relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE) - .getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (relOpParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" + relOpParentNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() - + "of_"; - } - if (occText != null) { - ext = occText + "qdm_var_" + ext; - } else { - ext = "qdm_var_" + ext; - } - } - - } - idChildNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); - idChildNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); - } - } - Element temporallyRelatedInfoNode = null; - if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { - temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, hqmfXmlProcessor); - } else { - temporallyRelatedInfoNode = hqmfXmlProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); - temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); - } - handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); - - Node firstChild = setOpEntryNode.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { - firstChild = firstChild.getNextSibling(); - } - NodeList outBoundList = ((Element) firstChild).getElementsByTagName(OUTBOUND_RELATIONSHIP); - if (outBoundList != null && outBoundList.getLength() > 0) { - Node outBound = outBoundList.item(0); - firstChild.insertBefore(temporallyRelatedInfoNode, outBound); - } else { - firstChild.appendChild(temporallyRelatedInfoNode); - } - - // create comment node - // Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("entry for - // "+relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - // dataCriteriaSectionElem.appendChild(comment); - dataCriteriaSectionElem.appendChild(setOpEntryNode); - return setOpEntryNode; - - } catch (Exception e) { - e.printStackTrace(); - } - - return null; - } - - /** - * Gets the rel op lhs rel op. - * - * @param relOpNode - * the rel op node - * @param dataCriteriaSectionElem - * the data criteria section elem - * @param lhsNode - * the lhs node - * @param rhsNode - * the rhs node - * @param clauseName - * the clause name - * @return the rel op lhs rel op - * @throws XPathExpressionException - * the x path expression exception - */ - private Node getrelOpLHSRelOp(Node relOpNode, Node dataCriteriaSectionElem, Node lhsNode, Node rhsNode, - String clauseName) throws XPathExpressionException { - - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - // Node relOpParentNode = relOpNode.getParentNode(); - - try { - Node relOpEntryNode = generateRelOpHQMF(lhsNode, dataCriteriaSectionElem, clauseName); - /* - * Element temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, - * hqmfXmlProcessor); - */ - - Node relOpParentNode = checkIfSubTree(relOpNode.getParentNode()); - - if (relOpParentNode != null) { - NodeList idChildNodeList = ((Element) relOpEntryNode).getElementsByTagName(ID); - - if (idChildNodeList != null && idChildNodeList.getLength() > 0) { - Node idChildNode = idChildNodeList.item(0); - String root = relOpParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); - String ext = StringUtils - .deleteWhitespace(relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + "_" - + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); - if (relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { - String isQdmVariable = relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE) - .getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (relOpParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" - + relOpParentNode.getAttributes().getNamedItem("instance").getNodeValue() - + "of_"; - } - if (occText != null) { - ext = occText + "qdm_var_" + ext; - } else { - ext = "qdm_var_" + ext; - } - } - } - idChildNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); - idChildNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); - } - } - Element temporallyRelatedInfoNode = null; - if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { - temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, hqmfXmlProcessor); - } else { - temporallyRelatedInfoNode = hqmfXmlProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); - temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); - } - - handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); - - Node firstChild = relOpEntryNode.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { - firstChild = firstChild.getNextSibling(); - } - NodeList outBoundList = ((Element) firstChild).getElementsByTagName(OUTBOUND_RELATIONSHIP); - if (outBoundList != null && outBoundList.getLength() > 0) { - Node outBound = outBoundList.item(0); - firstChild.insertBefore(temporallyRelatedInfoNode, outBound); - } else { - firstChild.appendChild(temporallyRelatedInfoNode); - } - // create comment node - // Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("entry for - // "+relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - // dataCriteriaSectionElem.appendChild(comment); - dataCriteriaSectionElem.appendChild(relOpEntryNode); - return relOpEntryNode; - - } catch (Exception e) { - e.printStackTrace(); - } - - return null; - } - - /** - * Gets the rel op lhsqdm. - * - * @param relOpNode - * the rel op node - * @param dataCriteriaSectionElem - * the data criteria section elem - * @param lhsNode - * the lhs node - * @param rhsNode - * the rhs node - * @param clauseName - * the clause name - * @return the rel op lhsqdm - * @throws XPathExpressionException - * the x path expression exception - */ - private Node getrelOpLHSQDM(Node relOpNode, Node dataCriteriaSectionElem, Node lhsNode, Node rhsNode, - String clauseName) throws XPathExpressionException { - - String ext = getElementRefExt(lhsNode, measureExport.getSimpleXmlProcessor()); - String root = lhsNode.getAttributes().getNamedItem(ID).getNodeValue(); - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - Node relOpParentNode = relOpNode.getParentNode(); - Element excerptElement = null; - Node idNodeQDM = hqmfXmlProcessor.findNode(hqmfXmlProcessor.getOriginalDoc(), - "//entry/*/id[@root='" + root + "'][@extension=\"" + ext + "\"]"); - - if (relOpParentNode != null && idNodeQDM != null) { - ext = StringUtils.deleteWhitespace(relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + "_" - + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); - Node subTreeParentNode = checkIfSubTree(relOpParentNode); - if (subTreeParentNode != null) { - root = subTreeParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); - if (subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { - String isQdmVariable = subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); - if (TRUE.equalsIgnoreCase(isQdmVariable)) { - String occText = null; - // Handled Occurrence Of QDM Variable. - if (relOpParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { - occText = "occ" + relOpParentNode.getAttributes().getNamedItem("instance").getNodeValue() - + "of_"; - } - if (occText != null) { - ext = occText + "qdm_var_" + ext; - } else { - ext = "qdm_var_" + ext; - } - } - } - } - - Node entryNodeForElementRef = idNodeQDM.getParentNode().getParentNode(); - Node clonedEntryNodeForElementRef = entryNodeForElementRef.cloneNode(true); - /* - * Element localVarName = (Element) - * ((Element)clonedEntryNodeForElementRef).getElementsByTagName( - * "localVariableName").item(0); - * localVarName.setAttribute(VALUE,findSubTreeDisplayName(lhsNode)); - */ - NodeList idChildNodeList = ((Element) clonedEntryNodeForElementRef).getElementsByTagName(ID); - updateLocalVar(clonedEntryNodeForElementRef, ext); - if (idChildNodeList != null && idChildNodeList.getLength() > 0) { - Node idChildNode = idChildNodeList.item(0); - idChildNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); - idChildNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); - } - - // Added logic to show qdm_variable in extension if clause is of qdm variable - // type. - if (FUNCTIONAL_OP.equals(relOpParentNode.getNodeName())) { - excerptElement = generateExcerptEntryForFunctionalNode(relOpParentNode, lhsNode, hqmfXmlProcessor, - clonedEntryNodeForElementRef); - } - Element temporallyRelatedInfoNode = null; - if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { - temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, hqmfXmlProcessor); - generateTemporalAttribute(hqmfXmlProcessor, lhsNode, temporallyRelatedInfoNode, - clonedEntryNodeForElementRef, true); - } else { - temporallyRelatedInfoNode = hqmfXmlProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); - temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); - } - handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); - Node firstChild = clonedEntryNodeForElementRef.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { - firstChild = firstChild.getNextSibling(); - } - NodeList outBoundList = ((Element) firstChild).getElementsByTagName(OUTBOUND_RELATIONSHIP); - if (outBoundList != null && outBoundList.getLength() > 0) { - Node outBound = outBoundList.item(0); - firstChild.insertBefore(temporallyRelatedInfoNode, outBound); - } else { - firstChild.appendChild(temporallyRelatedInfoNode); - } - - if (excerptElement != null) { - // Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("excerpt - // for - // "+relOpParentNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - // firstChild.appendChild(comment); - firstChild.appendChild(excerptElement); - } - // create comment node - // Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("entry for - // "+relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - // dataCriteriaSectionElem.appendChild(comment); - dataCriteriaSectionElem.appendChild(clonedEntryNodeForElementRef); - return clonedEntryNodeForElementRef; - } - return null; - } - - /** - * Handle rel op rhs. - * - * @param rhsNode - * the rhs node - * @param temporallyRelatedInfoNode - * the temporally related info node - * @param clauseName - * the clause name - * @throws XPathExpressionException - * the x path expression exception - */ - private void handleRelOpRHS(Node rhsNode, Element temporallyRelatedInfoNode, String clauseName) throws XPathExpressionException { - - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - String rhsName = rhsNode.getNodeName(); - Node dataCritSectionNode = hqmfXmlProcessor.findNode(temporallyRelatedInfoNode.getOwnerDocument(), - "//dataCriteriaSection"); - - if (ELEMENT_REF.equals(rhsName)) { - Node entryNode = generateCritRefElementRef(temporallyRelatedInfoNode, rhsNode, - measureExport.getHqmfXmlProcessor()); - generateTemporalAttribute(hqmfXmlProcessor, rhsNode, temporallyRelatedInfoNode, entryNode, false); - } else if (SUB_TREE_REF.equals(rhsName)) { - generateCritRefForNode(temporallyRelatedInfoNode, rhsNode); - } else { - switch (rhsName) { - case SET_OP: - generateCritRefSetOp(dataCritSectionNode, hqmfXmlProcessor, rhsNode, temporallyRelatedInfoNode, - clauseName); - break; - case RELATIONAL_OP: - generateRelOpHQMF(rhsNode, temporallyRelatedInfoNode, clauseName); - Node lastChild = temporallyRelatedInfoNode.getLastChild(); - if (lastChild.getNodeName().equals(ENTRY)) { - temporallyRelatedInfoNode.removeChild(lastChild); - - Node fChild = lastChild.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(fChild.getNodeName())) { - fChild = fChild.getNextSibling(); - } - - Node criteriaNode = fChild; - // temporallyRelatedInfoNode.appendChild(criteriaNode); - dataCritSectionNode.appendChild(lastChild); - // create criteriaRef - Element criteriaReference = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - criteriaReference.setAttribute(CLASS_CODE, - criteriaNode.getAttributes().getNamedItem(CLASS_CODE).getNodeValue()); - criteriaReference.setAttribute(MOOD_CODE, - criteriaNode.getAttributes().getNamedItem(MOOD_CODE).getNodeValue()); - - NodeList childNodeList = criteriaNode.getChildNodes(); - for (int i = 0; i < childNodeList.getLength(); i++) { - Node childNode = childNodeList.item(i); - if (childNode.getNodeName().equalsIgnoreCase(ID)) { - Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - id.setAttribute(ROOT, childNode.getAttributes().getNamedItem(ROOT).getNodeValue()); - id.setAttribute(EXTENSION, - childNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); - criteriaReference.appendChild(id); - temporallyRelatedInfoNode.appendChild(criteriaReference); - break; - } - } - - NodeList childTemporalNodeList = ((Element) criteriaNode) - .getElementsByTagName("temporallyRelatedInformation"); - if (childTemporalNodeList != null && childTemporalNodeList.getLength() > 0) { - Node childTemporalNode = childTemporalNodeList.item(0); - Node temporalInfoNode = childTemporalNode.getFirstChild(); - // find sourceAttribute - NodeList childs = temporalInfoNode.getChildNodes(); - for (int c = 0; c < childs.getLength(); c++) { - Node child = childs.item(c); - String childName = child.getNodeName(); - if ("qdm:sourceAttribute".equals(childName)) { - Node cloneAttNode = child.cloneNode(true); - temporallyRelatedInfoNode.getFirstChild().appendChild(cloneAttNode); - hqmfXmlProcessor.getOriginalDoc().renameNode(cloneAttNode, "", "qdm:targetAttribute"); - break; - } - } - } - } - break; - case FUNCTIONAL_OP: - Node entryNode = generateFunctionalOpHQMF(rhsNode, (Element) dataCritSectionNode, clauseName); - if (entryNode != null && entryNode.getNodeName().equals(ENTRY)) { - Node fChild = entryNode.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(fChild.getNodeName())) { - fChild = fChild.getNextSibling(); - } - // create criteriaRef - Element criteriaReference = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - criteriaReference.setAttribute(CLASS_CODE, - fChild.getAttributes().getNamedItem(CLASS_CODE).getNodeValue()); - criteriaReference.setAttribute(MOOD_CODE, - fChild.getAttributes().getNamedItem(MOOD_CODE).getNodeValue()); - NodeList childNodeList = fChild.getChildNodes(); - for (int i = 0; i < childNodeList.getLength(); i++) { - Node childNode = childNodeList.item(i); - if (childNode.getNodeName().equalsIgnoreCase(ID)) { - Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - id.setAttribute(ROOT, childNode.getAttributes().getNamedItem(ROOT).getNodeValue()); - id.setAttribute(EXTENSION, - childNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); - criteriaReference.appendChild(id); - temporallyRelatedInfoNode.appendChild(criteriaReference); - break; - } - } - } - break; - default: - // Dont do anything - break; - } - } - } - - /** - * Generate temporal attribute. - * - * @param hqmfXmlProcessor - * the hqmf xml processor - * @param rhsNode - * the rhs node - * @param temporallyRelatedInfoNode - * the temporally related info node - * @param entryNode - * the entry node - * @param isSource - * the is source - * @return the node - */ - private Node generateTemporalAttribute(XmlProcessor hqmfXmlProcessor, Node rhsNode, - Element temporallyRelatedInfoNode, Node entryNode, boolean isSource) { - if (entryNode != null) { - Element entryElement = (Element) entryNode; - - if (!rhsNode.hasChildNodes()) { - return null; - } else { - Node child = rhsNode.getFirstChild(); - if (!"attribute".equals(child.getNodeName())) { - return null; - } - - String value = child.getAttributes().getNamedItem(NAME).getNodeValue(); - List validAttribNames = new ArrayList<>(); - validAttribNames.add("incision datetime"); - validAttribNames.add("facility location arrival datetime"); - validAttribNames.add("facility location departure datetime"); - validAttribNames.add("recorded datetime"); - validAttribNames.add("signed datetime"); - validAttribNames.add("start datetime"); - validAttribNames.add("stop datetime"); - if (!validAttribNames.contains(value)) { - return null; - } - if ("start datetime".equals(value) || "stop datetime".equals(value)) { - String dataType = rhsNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - if (!dataType.endsWith("Order")) { - return null; - } - } - - // create sourceAttribute/targetAttribute - String attribName = "qdm:sourceAttribute"; - if (!isSource) { - attribName = "qdm:targetAttribute"; - } - Element attribute = hqmfXmlProcessor.getOriginalDoc().createElement(attribName); - attribute.setAttribute(NAME, value); - String boundValue = "effectiveTime.low"; - - if ("incision datetime".equals(value)) { - NodeList nodeList = entryElement.getElementsByTagName(OUTBOUND_RELATIONSHIP); - if (nodeList != null && nodeList.getLength() > 0) { - // Always get the last outBoundRelationShip tag, because this is the one - // which will represent the - Node outBoundNode = nodeList.item(nodeList.getLength() - 1); - Node criteriaNode = outBoundNode.getFirstChild(); - - NodeList idNodeList = ((Element) criteriaNode).getElementsByTagName(ID); - if (idNodeList != null && idNodeList.getLength() > 0) { - Node idNode = idNodeList.item(0); - Element qdmId = hqmfXmlProcessor.getOriginalDoc().createElement("qdm:id"); - qdmId.setAttribute(ROOT, idNode.getAttributes().getNamedItem(ROOT).getNodeValue()); - qdmId.setAttribute(EXTENSION, - idNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); - attribute.appendChild(qdmId); - } - } - } else { - NodeList nodeList = entryElement.getElementsByTagName(PARTICIPATION); - if (nodeList != null && nodeList.getLength() > 0) { - // Always get the last outBoundRelationShip tag, because this is the one - // which will represent the - Node participationNode = nodeList.item(nodeList.getLength() - 1); - Node roleNode = ((Element) participationNode).getElementsByTagName(ROLE).item(0); - NodeList idNodeList = ((Element) roleNode).getElementsByTagName(ID); - if (idNodeList != null && idNodeList.getLength() > 0) { - Node idNode = idNodeList.item(0); - Node itemNode = idNode.getFirstChild(); - Element qdmId = hqmfXmlProcessor.getOriginalDoc().createElement("qdm:id"); - qdmId.setAttribute(ROOT, itemNode.getAttributes().getNamedItem(ROOT).getNodeValue()); - qdmId.setAttribute(EXTENSION, - itemNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); - attribute.appendChild(qdmId); - - if ("facility location departure datetime".equals(value) || "stop datetime".equals(value) - || "signed datetime".equals(value) || "recorded datetime".equals(value)) { - boundValue = "effectiveTime.high"; - } - } - } - } - attribute.setAttribute("bound", boundValue); - Node temporalInformation = temporallyRelatedInfoNode.getFirstChild(); - if (temporallyRelatedInfoNode.getElementsByTagName("qdm:delta").item(0) != null) { - Node qdmDeltaNode = temporallyRelatedInfoNode.getElementsByTagName("qdm:delta").item(0); - temporalInformation.insertBefore(attribute, qdmDeltaNode); - } else { - temporalInformation.appendChild(attribute); - } - - return attribute; - } - } - return null; - } - - /** - * Generate Excerpt for Functional Op used with timing/Relationship. - * - * @param functionalOpNode - * the functional op node - * @param lhsNode - * the lhs node - * @param hqmfXmlProcessor - * the hqmf xml processor - * @param clonedNodeToAppendExcerpt - * the cloned node to append excerpt - * @return the element - * @throws XPathExpressionException - * the x path expression exception - */ - private Element generateExcerptEntryForFunctionalNode(Node functionalOpNode, Node lhsNode, - XmlProcessor hqmfXmlProcessor, Node clonedNodeToAppendExcerpt) throws XPathExpressionException { - Element excerptElement = hqmfXmlProcessor.getOriginalDoc().createElement(EXCERPT); - String functionalOpName = functionalOpNode.getAttributes().getNamedItem(TYPE).getNodeValue(); - Element criteriaElement = null; - if (FUNCTIONAL_OPS_NON_SUBSET.containsKey(functionalOpName)) { - Element sequenceElement = hqmfXmlProcessor.getOriginalDoc().createElement(SEQUENCE_NUMBER); - sequenceElement.setAttribute(VALUE, FUNCTIONAL_OPS_NON_SUBSET.get(functionalOpName.toUpperCase())); - excerptElement.appendChild(sequenceElement); - if (clonedNodeToAppendExcerpt != null) { - if (clonedNodeToAppendExcerpt.getNodeName().contains(GROUPER)) { - criteriaElement = generateCriteriaElementForSetOpExcerpt(hqmfXmlProcessor, - clonedNodeToAppendExcerpt); - excerptElement.appendChild(criteriaElement); - } else { - NodeList entryChildNodes = clonedNodeToAppendExcerpt.getChildNodes(); - criteriaElement = generateCriteriaElementForExcerpt(hqmfXmlProcessor, entryChildNodes); - excerptElement.appendChild(criteriaElement); - } - } - } else if (FUNCTIONAL_OPS_SUBSET.containsKey(functionalOpName)) { - NamedNodeMap attributeMap = functionalOpNode.getAttributes(); - if (clonedNodeToAppendExcerpt.getNodeName().contains(GROUPER)) { - criteriaElement = generateCriteriaElementForSetOpExcerpt(hqmfXmlProcessor, clonedNodeToAppendExcerpt); - excerptElement.appendChild(criteriaElement); - } else { - NodeList entryChildNodes = clonedNodeToAppendExcerpt.getChildNodes(); - criteriaElement = generateCriteriaElementForExcerpt(hqmfXmlProcessor, entryChildNodes); - excerptElement.appendChild(criteriaElement); - } - if (clonedNodeToAppendExcerpt != null) { - - if ("count".equalsIgnoreCase(functionalOpName)) { - - createRepeatNumberTagForCountFuncttion(hqmfXmlProcessor, attributeMap, criteriaElement); - Element qdmSubSetElement = hqmfXmlProcessor.getOriginalDoc().createElement("qdm:subsetCode"); - qdmSubSetElement.setAttribute(CODE, FUNCTIONAL_OPS_SUBSET.get(functionalOpName.toUpperCase())); - Element subSetCodeElement = hqmfXmlProcessor.getOriginalDoc().createElement("subsetCode"); - subSetCodeElement.setAttribute(CODE, "SUM"); - - excerptElement.appendChild(subSetCodeElement); - excerptElement.appendChild(qdmSubSetElement); - excerptElement.appendChild(criteriaElement); - } else { - if (attributeMap.getNamedItem(OPERATOR_TYPE) != null && lhsNode != null) { - String lhsNodeType = lhsNode.getNodeName(); - if (ELEMENT_REF.equalsIgnoreCase(lhsNodeType)) { - String qdmUUID = lhsNode.getAttributes().getNamedItem(ID).getNodeValue(); - String xPath = "/measure/elementLookUp/qdm[@uuid ='" + qdmUUID + "']"; - Node node = measureExport.getSimpleXmlProcessor() - .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xPath); - if (node != null && lhsNode.hasChildNodes()) { - Node qdmNode = node.cloneNode(true); - Node attributeNode = lhsNode.getFirstChild().cloneNode(true); - attributeNode.setUserData(ATTRIBUTE_NAME, - attributeNode.getAttributes().getNamedItem(NAME).getNodeValue(), null); - attributeNode.setUserData(ATTRIBUTE_MODE, - attributeMap.getNamedItem(OPERATOR_TYPE).getNodeValue(), null); - attributeNode.setUserData(ATTRIBUTE_UUID, - attributeNode.getAttributes().getNamedItem(ATTR_UUID).getNodeValue(), null); - Element attributeElement = (Element) attributeNode; - - attributeElement.setAttribute(MODE, - attributeMap.getNamedItem(OPERATOR_TYPE).getNodeValue()); - if (attributeElement.getAttributes().getNamedItem(ATTR_DATE) != null) { - attributeNode.setUserData(ATTRIBUTE_DATE, - attributeMap.getNamedItem(QUANTITY).getNodeValue(), null); - } else { - attributeElement.setAttribute(COMPARISON_VALUE, - attributeMap.getNamedItem(QUANTITY).getNodeValue()); - } - if (attributeMap.getNamedItem(UNIT) != null) { - attributeElement.setAttribute(UNIT, attributeMap.getNamedItem(UNIT).getNodeValue()); - } else { - if (attributeElement.getAttributes().getNamedItem(UNIT) != null) { - attributeElement.removeAttribute(UNIT); - } - } - attributeNode = attributeElement; - - // HQMFDataCriteriaElementGenerator hqmfDataCriteriaElementGenerator = new - // HQMFDataCriteriaElementGenerator(); - // hqmfDataCriteriaElementGenerator.generateAttributeTagForFunctionalOp(measureExport,qdmNode, - // criteriaElement, attributeNode); - HQMFAttributeGenerator attributeGenerator = new HQMFAttributeGenerator(); - attributeGenerator.generateAttributeTagForFunctionalOp(measureExport, qdmNode, - criteriaElement, attributeNode); - } - } - } - Element qdmSubSetElement = hqmfXmlProcessor.getOriginalDoc().createElement("qdm:subsetCode"); - qdmSubSetElement.setAttribute(CODE, FUNCTIONAL_OPS_SUBSET.get(functionalOpName.toUpperCase())); - - if ("sum".equalsIgnoreCase(functionalOpName)) { - Element subSetCodeElement = hqmfXmlProcessor.getOriginalDoc().createElement("subsetCode"); - subSetCodeElement.setAttribute(CODE, "SUM"); - excerptElement.appendChild(subSetCodeElement); - } - excerptElement.appendChild(qdmSubSetElement); - excerptElement.appendChild(criteriaElement); - } - } - } - - return excerptElement; - } - - /** - * Check if parent sub tree. - * - * @param parentNode - * the parent node - * @return the node - */ - protected Node checkIfParentSubTree(Node parentNode) { - Node returnNode = null; - if (parentNode != null) { - String parentName = parentNode.getNodeName(); - if (SUB_TREE.equals(parentName)) { - returnNode = parentNode; - } else { - returnNode = checkIfParentSubTree(parentNode.getParentNode()); - } - } - - return returnNode; - } - - /** - * Generates RepeatNumber tags for Count Function. - * - * @param hqmfXmlProcessor - * - XmlProcessor. - * @param attributeMap - * - NamedNodeMap. - * @param criteriaElement - * - Element. - */ - private void createRepeatNumberTagForCountFuncttion(XmlProcessor hqmfXmlProcessor, NamedNodeMap attributeMap, - Element criteriaElement) { - Element repeatNumberElement = hqmfXmlProcessor.getOriginalDoc().createElement("repeatNumber"); - Element lowNode = hqmfXmlProcessor.getOriginalDoc().createElement("low"); - Element highNode = hqmfXmlProcessor.getOriginalDoc().createElement("high"); - if (attributeMap.getNamedItem(OPERATOR_TYPE) != null) { - String operatorType = attributeMap.getNamedItem(OPERATOR_TYPE).getNodeValue(); - String quantity = attributeMap.getNamedItem(QUANTITY).getNodeValue(); - if (operatorType.startsWith("Greater Than")) { - lowNode.setAttribute(VALUE, quantity); - highNode.setAttribute(NULL_FLAVOR, "PINF"); - if ("Greater Than or Equal To".equals(operatorType)) { - repeatNumberElement.setAttribute("lowClosed", TRUE); - } - } else if ("Equal To".equals(operatorType)) { - repeatNumberElement.setAttribute("lowClosed", TRUE); - repeatNumberElement.setAttribute("highClosed", TRUE); - lowNode.setAttribute(VALUE, quantity); - highNode.setAttribute(VALUE, quantity); - } else if (operatorType.startsWith("Less Than")) { - repeatNumberElement.setAttribute("lowClosed", TRUE); - lowNode.setAttribute(VALUE, "0"); - highNode.setAttribute(VALUE, quantity); - if ("Less Than or Equal To".equals(operatorType)) { - repeatNumberElement.setAttribute("highClosed", TRUE); - } - } - repeatNumberElement.appendChild(lowNode); - repeatNumberElement.appendChild(highNode); - criteriaElement.appendChild(repeatNumberElement); - } - } - - /** - * Generate criteria element for excerpt. - * - * @param hqmfXmlProcessor - * the hqmf xml processor - * @param entryChildNodes - * the entry child nodes - * @return the element - */ - private Element generateCriteriaElementForExcerpt(XmlProcessor hqmfXmlProcessor, NodeList entryChildNodes) { - Element criteriaElement = null; - for (int i = 0; i < entryChildNodes.getLength(); i++) { - Node childNode = entryChildNodes.item(i); - String childNodeName = childNode.getNodeName(); - if (childNodeName.contains("Criteria")) { - criteriaElement = hqmfXmlProcessor.getOriginalDoc().createElement(childNodeName); - criteriaElement.setAttribute(CLASS_CODE, - childNode.getAttributes().getNamedItem(CLASS_CODE).getNodeValue()); - criteriaElement.setAttribute(MOOD_CODE, - childNode.getAttributes().getNamedItem(MOOD_CODE).getNodeValue()); - NodeList criteriaChildNodes = childNode.getChildNodes(); - for (int j = 0; j < criteriaChildNodes.getLength(); j++) { - Node criteriaChildNode = criteriaChildNodes.item(j); - if (ID.equalsIgnoreCase(criteriaChildNode.getNodeName())) { - Element idElement = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - idElement.setAttribute(ROOT, - criteriaChildNode.getAttributes().getNamedItem(ROOT).getNodeValue()); - idElement.setAttribute(EXTENSION, - criteriaChildNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); - criteriaElement.appendChild(idElement); - break; - } - } - - break; - } - } - return criteriaElement; - } - - /** - * Generate criteria element for set op excerpt. - * - * @param hqmfXmlProcessor - * the hqmf xml processor - * @param clonedNodeToAppendExcerpt - * the cloned node to append excerpt - * @return the element - */ - private Element generateCriteriaElementForSetOpExcerpt(XmlProcessor hqmfXmlProcessor, - Node clonedNodeToAppendExcerpt) { - Element criteriaElement = null; - for (int i = 0; i < clonedNodeToAppendExcerpt.getChildNodes().getLength(); i++) { - Node childNode = clonedNodeToAppendExcerpt.getChildNodes().item(i); - if (ID.equalsIgnoreCase(childNode.getNodeName())) { - Node criteriaNode = generateEmptyGrouper(hqmfXmlProcessor, - childNode.getAttributes().getNamedItem(ROOT).getNodeValue(), - childNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); - criteriaElement = (Element) criteriaNode; - break; - } - } - return criteriaElement; - } - - /** - * Creates the base temporal node. - * - * @param relOpNode - * the rel op node - * @param hqmfXmlProcessor - * the hqmf xml processor - * @return the element - */ - private Element createBaseTemporalNode(Node relOpNode, XmlProcessor hqmfXmlProcessor) { - - NamedNodeMap attribMap = relOpNode.getAttributes(); - Element temporallyRelatedInfoNode = hqmfXmlProcessor.getOriginalDoc() - .createElement("temporallyRelatedInformation"); - temporallyRelatedInfoNode.setAttribute(TYPE_CODE, attribMap.getNamedItem(TYPE).getNodeValue().toUpperCase()); - - Element temporalInfoNode = hqmfXmlProcessor.getOriginalDoc().createElement("qdm:temporalInformation"); - String precisionUnit = "min"; // use min by default - - if (attribMap.getNamedItem(OPERATOR_TYPE) != null) { - String operatorType = attribMap.getNamedItem(OPERATOR_TYPE).getNodeValue(); - String quantity = attribMap.getNamedItem(QUANTITY).getNodeValue(); - String unit = attribMap.getNamedItem(UNIT).getNodeValue(); - - if ("seconds".equals(unit)) { - precisionUnit = "s"; - unit = "s"; - } else if ("hours".equals(unit)) { - unit = "h"; - } else if ("minutes".equals(unit)) { - unit = "min"; - } else { - precisionUnit = "d"; - if ("days".equals(unit)) { - unit = "d"; - } else if ("weeks".equals(unit)) { - unit = "wk"; - } else if ("months".equals(unit)) { - unit = "mo"; - } else if ("years".equals(unit)) { - unit = "a"; - } - } - - Element deltaNode = hqmfXmlProcessor.getOriginalDoc().createElement("qdm:delta"); - Element lowNode = hqmfXmlProcessor.getOriginalDoc().createElement("low"); - lowNode.setAttribute(UNIT, unit); - - Element highNode = hqmfXmlProcessor.getOriginalDoc().createElement("high"); - highNode.setAttribute(UNIT, unit); - - if (operatorType.startsWith("Greater Than")) { - lowNode.setAttribute(VALUE, quantity); - highNode.removeAttribute(UNIT); - highNode.setAttribute(NULL_FLAVOR, "PINF"); - if ("Greater Than or Equal To".equals(operatorType)) { - deltaNode.setAttribute("lowClosed", TRUE); - } - } else if ("Equal To".equals(operatorType)) { - deltaNode.setAttribute("lowClosed", TRUE); - deltaNode.setAttribute("highClosed", TRUE); - lowNode.setAttribute(VALUE, quantity); - highNode.setAttribute(VALUE, quantity); - } else if (operatorType.startsWith("Less Than")) { - deltaNode.setAttribute("lowClosed", TRUE); - lowNode.setAttribute(VALUE, "0"); - highNode.setAttribute(VALUE, quantity); - if ("Less Than or Equal To".equals(operatorType)) { - deltaNode.setAttribute("highClosed", TRUE); - } - } - deltaNode.appendChild(lowNode); - deltaNode.appendChild(highNode); - temporalInfoNode.appendChild(deltaNode); - } - temporalInfoNode.setAttribute("precisionUnit", precisionUnit); - temporallyRelatedInfoNode.appendChild(temporalInfoNode); - return temporallyRelatedInfoNode; - } - - /** - * Generate crit ref rel op. - * - * @param parentNode - * the parent node - * @param hqmfXmlProcessor - * the hqmf xml processor - * @param childNode - * the child node - * @param outboundRelElem - * the outbound rel elem - * @param clauseName - * the clause name - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateCritRefRelOp(Node parentNode, XmlProcessor hqmfXmlProcessor, Node childNode, - Node outboundRelElem, String clauseName) throws XPathExpressionException { - Node relOpEntryNode = generateRelOpHQMF(childNode, parentNode, clauseName); - - if (relOpEntryNode != null) { - Node idNode = getTagFromEntry(relOpEntryNode, ID); - // Node critNode = relOpEntryNode.getFirstChild(); - // NodeList nodeList = ((Element)critNode).getElementsByTagName(ID); - // if(nodeList != null && nodeList.getLength() > 0){ - if (idNode != null) { - // Node idNode = nodeList.item(0); - NamedNodeMap idAttribMap = idNode.getAttributes(); - String idRoot = idAttribMap.getNamedItem(ROOT).getNodeValue(); - String idExt = idAttribMap.getNamedItem(EXTENSION).getNodeValue(); - - Node parent = idNode.getParentNode(); - - NamedNodeMap attribMap = parent.getAttributes(); - String classCode = attribMap.getNamedItem(CLASS_CODE).getNodeValue(); - String moodCode = attribMap.getNamedItem(MOOD_CODE).getNodeValue(); - - // create criteriaRef - Element criteriaReference = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - criteriaReference.setAttribute(CLASS_CODE, classCode); - criteriaReference.setAttribute(MOOD_CODE, moodCode); - - Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - id.setAttribute(ROOT, idRoot); - id.setAttribute(EXTENSION, idExt); - - criteriaReference.appendChild(id); - outboundRelElem.appendChild(criteriaReference); - } - } - } - - /** - * Generate crit ref set op. - * - * @param parentNode - * the parent node - * @param hqmfXmlProcessor - * the hqmf xml processor - * @param childNode - * the child node - * @param outboundRelElem - * the outbound rel elem - * @param clauseName - * the clause name - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateCritRefSetOp(Node parentNode, XmlProcessor hqmfXmlProcessor, Node childNode, - Node outboundRelElem, String clauseName) throws XPathExpressionException { - - Node setOpEntry = generateSetOpHQMF(childNode, parentNode, clauseName); - NodeList childList = setOpEntry.getChildNodes(); - for (int j = 0; j < childList.getLength(); j++) { - Node child = childList.item(j); - if (GROUPER_CRITERIA.equals(child.getNodeName())) { - NodeList idChildList = ((Element) child).getElementsByTagName(ID); - if (idChildList.getLength() > 0) { - Node idChild = idChildList.item(0); - NamedNodeMap attribMap = idChild.getAttributes(); - String idRoot = attribMap.getNamedItem(ROOT).getNodeValue(); - String idExt = attribMap.getNamedItem(EXTENSION).getNodeValue(); - - // create criteriaRef - Element criteriaReference = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - criteriaReference.setAttribute(CLASS_CODE, "GROUPER"); - criteriaReference.setAttribute(MOOD_CODE, "EVN"); - - Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - id.setAttribute(ROOT, idRoot); - id.setAttribute(EXTENSION, idExt); - - criteriaReference.appendChild(id); - outboundRelElem.appendChild(criteriaReference); - } - } - } - } - - /** - * Generate crit ref for node. - * - * @param outboundRelElem - * the outbound rel elem - * @param childNode - * the child node - * @throws XPathExpressionException - * the x path expression exception - */ - private void generateCritRefForNode(Node outboundRelElem, Node childNode) - throws XPathExpressionException { - XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); - String childName = childNode.getNodeName(); - - switch (childName) { - case ELEMENT_REF: - generateCritRefElementRef(outboundRelElem, childNode, hqmfXmlProcessor); - break; - case SUB_TREE_REF: - generateCritRefCQLDefine(outboundRelElem, childNode, hqmfXmlProcessor, true); - break; - - default: - break; - } - - } - - /** - * This method will basically create a with - * classCode='GROUPER' and moodCode='EVN' and have the tag pointing to the - * for the referenced subTree/clause. - * - * @param outboundRelElem - * the outbound rel elem - * @param subTreeRefNode - * the sub tree ref node - * @param hqmfXmlProcessor - * the hqmf xml processor - * @throws XPathExpressionException - * the x path expression exception - */ - protected void generateCritRefCQLDefine(Node outboundRelElem, Node subTreeRefNode, XmlProcessor hqmfXmlProcessor) - throws XPathExpressionException { - generateCritRefCQLDefine(outboundRelElem, subTreeRefNode, hqmfXmlProcessor, false); - } - - /** - * This method will basically create a with - * classCode='GROUPER' and moodCode='EVN' and have the tag pointing to the - * for the referenced subTree/clause. - * - * @param outboundRelElem - * the outbound rel elem - * @param cqlDefineNode - * the sub tree ref node - * @param hqmfXmlProcessor - * the hqmf xml processor - * @param checkExisting - * check in the map if already existing - * @throws XPathExpressionException - * the x path expression exception - */ - - protected void generateCritRefCQLDefine(Node outboundRelElem, Node cqlDefineNode, XmlProcessor hqmfXmlProcessor, - boolean checkExisting) throws XPathExpressionException { - - String cqlDefUUID = cqlDefineNode.getAttributes().getNamedItem(UUID).getNodeValue(); - - String xpath = "/measure/cqlLookUp//definition[@id='" + cqlDefUUID + "']"; - Node definitionNode = measureExport.getSimpleXmlProcessor() - .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); - if (definitionNode != null) { - String defineName = definitionNode.getAttributes().getNamedItem("name").getNodeValue(); - Node cqlUUIDNode = measureExport.getSimpleXmlProcessor().findNode( - measureExport.getSimpleXmlProcessor().getOriginalDoc(), "/measure/measureDetails/cqlUUID"); - Node cqlLibraryNode = measureExport.getSimpleXmlProcessor() - .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), "/measure/cqlLookUp/library"); - if (cqlUUIDNode != null && cqlLibraryNode != null) { - String uuid = cqlUUIDNode.getTextContent(); - String libraryName = cqlLibraryNode.getTextContent(); - String ext = libraryName + ".\"" + defineName + "\""; - // create criteriaRef - Element criteriaReference = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - criteriaReference.setAttribute(CLASS_CODE, "OBS"); - criteriaReference.setAttribute(MOOD_CODE, "EVN"); - - Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - id.setAttribute(ROOT, uuid); - id.setAttribute(EXTENSION, ext); - - criteriaReference.appendChild(id); - outboundRelElem.appendChild(criteriaReference); - } - } - } - - /** - * Generate crit ref element ref. - * - * @param outboundRelElem - * the outbound rel elem - * @param elementRefNode - * the element ref node - * @param hqmfXmlProcessor - * the hqmf xml processor - * @return the node - * @throws XPathExpressionException - * the x path expression exception - */ - private Node generateCritRefElementRef(Node outboundRelElem, Node elementRefNode, XmlProcessor hqmfXmlProcessor) - throws XPathExpressionException { - String ext = getElementRefExt(elementRefNode, measureExport.getSimpleXmlProcessor()); - String root = elementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - Node idNodeQDM = hqmfXmlProcessor.findNode(hqmfXmlProcessor.getOriginalDoc(), - "//entry/*/id[@root=\"" + root + "\"][@extension=\"" + ext + "\"]"); - if (idNodeQDM != null) { - Node parent = idNodeQDM.getParentNode(); - if (parent != null) { - NamedNodeMap attribMap = parent.getAttributes(); - String classCode = attribMap.getNamedItem(CLASS_CODE).getNodeValue(); - String moodCode = attribMap.getNamedItem(MOOD_CODE).getNodeValue(); - - // create criteriaRef - Element criteriaReference = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - criteriaReference.setAttribute(CLASS_CODE, classCode); - criteriaReference.setAttribute(MOOD_CODE, moodCode); - - Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - id.setAttribute(ROOT, root); - id.setAttribute(EXTENSION, ext); - - criteriaReference.appendChild(id); - outboundRelElem.appendChild(criteriaReference); - // return element - return parent.getParentNode(); - } - } else { - // check if this is a measurement period - String displayName = elementRefNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - if ("Measurement Period : Timing Element".equals(displayName)) { - // create criteriaRef - Element criteriaReference = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - criteriaReference.setAttribute(CLASS_CODE, "OBS"); - criteriaReference.setAttribute(MOOD_CODE, "EVN"); - - Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - id.setAttribute(ROOT, elementRefNode.getAttributes().getNamedItem(ID).getNodeValue()); - id.setAttribute(EXTENSION, "measureperiod"); - - criteriaReference.appendChild(id); - outboundRelElem.appendChild(criteriaReference); - } - } - return null; - } - - /** - * Generate item count element ref. - * - * @param me - * the me - * @param populationTypeCriteriaElement - * the population type criteria element - * @param elementRefNode - * the element ref node - * @param hqmfXmlProcessor - * the hqmf xml processor - * @throws XPathExpressionException - * the x path expression exception - */ - public void generateItemCountElementRef(MeasureExport me, Element populationTypeCriteriaElement, - Node elementRefNode, XmlProcessor hqmfXmlProcessor) throws XPathExpressionException { - String ext = getElementRefExt(elementRefNode, me.getSimpleXmlProcessor()); - String root = elementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - Node idNodeQDM = hqmfXmlProcessor.findNode(hqmfXmlProcessor.getOriginalDoc(), - "//entry/*/id[@root='" + root + "'][@extension=\"" + ext + "\"]"); - if (idNodeQDM != null) { - Node parent = idNodeQDM.getParentNode(); - if (parent != null) { - String classCode = parent.getAttributes().getNamedItem("classCode").getNodeValue(); - String moodCode = parent.getAttributes().getNamedItem("moodCode").getNodeValue(); - // item count Criteria Ref for Measure Observations - if ("measureObservationDefinition".equals(populationTypeCriteriaElement.getNodeName())) { - Element componentOfElem = hqmfXmlProcessor.getOriginalDoc().createElement("componentOf"); - componentOfElem.setAttribute(TYPE_CODE, "COMP"); - Element criteriaRef = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); - criteriaRef.setAttribute(CLASS_CODE, classCode); - criteriaRef.setAttribute(MOOD_CODE, moodCode); - Element idElement = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - idElement.setAttribute(ROOT, root); - idElement.setAttribute(EXTENSION, ext); - criteriaRef.appendChild(idElement); - componentOfElem.appendChild(criteriaRef); - Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("Item Count "); - populationTypeCriteriaElement.appendChild(comment); - populationTypeCriteriaElement.appendChild(componentOfElem); - } else { // item count Criteria Ref for Populations - // create component for ItemCount ElmentRef - Element componentElem = hqmfXmlProcessor.getOriginalDoc().createElement("component"); - componentElem.setAttribute(TYPE_CODE, "COMP"); - Element measureAttrElem = hqmfXmlProcessor.getOriginalDoc().createElement("measureAttribute"); - componentElem.appendChild(measureAttrElem); - Element codeElem = hqmfXmlProcessor.getOriginalDoc().createElement("code"); - codeElem.setAttribute(CODE, "ITMCNT"); - codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.5.4"); - codeElem.setAttribute(CODE_SYSTEM_NAME, "HL7 Observation Value"); - Element displayNameElem = hqmfXmlProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - displayNameElem.setAttribute(VALUE, "Items to count"); - codeElem.appendChild(displayNameElem); - Element valueElem = hqmfXmlProcessor.getOriginalDoc().createElement(VALUE); - valueElem.setAttribute("xsi:type", "II"); - valueElem.setAttribute(ROOT, root); - valueElem.setAttribute(EXTENSION, ext); - measureAttrElem.appendChild(codeElem); - measureAttrElem.appendChild(valueElem); - populationTypeCriteriaElement.appendChild(componentElem); - } - } - } - } - - /** - * Gets the element ref ext. - * - * @param elementRefNode - * the element ref node - * @param simpleXmlProcessor - * the simple xml processor - * @return the element ref ext - * @throws XPathExpressionException - * the x path expression exception - */ - private String getElementRefExt(Node elementRefNode, XmlProcessor simpleXmlProcessor) - throws XPathExpressionException { - String extension = ""; - if (elementRefNode.hasChildNodes()) { - Node childNode = elementRefNode.getFirstChild(); - if ("attribute".equals(childNode.getNodeName())) { - extension = childNode.getAttributes().getNamedItem(ATTR_UUID).getNodeValue(); - } - } else { - String id = elementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - Node qdmNode = simpleXmlProcessor.findNode(simpleXmlProcessor.getOriginalDoc(), - "/measure/elementLookUp/qdm[@uuid='" + id + "']"); - if (qdmNode != null) { - String dataType = qdmNode.getAttributes().getNamedItem(DATATYPE).getNodeValue(); - String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); - extension = qdmName + "_" + dataType; - if (qdmNode.getAttributes().getNamedItem(INSTANCE) != null) { - extension = qdmNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + "_" + extension; - } - } - } - return StringUtils.deleteWhitespace(extension); - } - - /** - * Generate empty grouper. - * - * @param hqmfXmlProcessor - * the hqmf xml processor - * @param root - * the root - * @param ext - * the ext - * @return the node - */ - private Node generateEmptyGrouper(XmlProcessor hqmfXmlProcessor, String root, String ext) { - Element grouperElem = hqmfXmlProcessor.getOriginalDoc().createElement(GROUPER_CRITERIA); - grouperElem.setAttribute(CLASS_CODE, "GROUPER"); - grouperElem.setAttribute(MOOD_CODE, "EVN"); - - Element idElem = hqmfXmlProcessor.getOriginalDoc().createElement(ID); - idElem.setAttribute(ROOT, root); - idElem.setAttribute(EXTENSION, StringUtils.deleteWhitespace(ext)); - - grouperElem.appendChild(idElem); - - return grouperElem; - } - - /** - * Generate empty outbound elem. - * - * @param hqmfXmlProcessor - * the hqmf xml processor - * @return the element - */ - private Element generateEmptyOutboundElem(XmlProcessor hqmfXmlProcessor) { - Element outboundRelElem = hqmfXmlProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); - outboundRelElem.setAttribute(TYPE_CODE, "COMP"); - return outboundRelElem; - } - - /** - * Gets the tag from entry. - * - * @param entryElem - * the entry elem - * @param tagName - * the tag name - * @return the tag from entry - */ - private Node getTagFromEntry(Node entryElem, String tagName) { - - String entryElemName = entryElem.getNodeName(); - if (ENTRY.equals(entryElemName)) { - Node firstChild = entryElem.getFirstChild(); - if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { - NodeList nodeList = ((Element) firstChild.getNextSibling()).getElementsByTagName(tagName); - if (nodeList != null && nodeList.getLength() > 0) { - return nodeList.item(0); - } - } else { - NodeList nodeList = ((Element) firstChild).getElementsByTagName(tagName); - if (nodeList != null && nodeList.getLength() > 0) { - return nodeList.item(0); - } - } - } - return null; - } - - /** - * Check If the parentNode is a SUB_TREE node. Or else, if parent is a - * 'functionalOp' then recursively check if the parentNode's parent is a - * 'subTree'. If yes, then return true. - * - * @param parentNode - * the parent node - * @return boolean - */ - private Node checkIfSubTree(Node parentNode) { - Node returnNode = null; - if (parentNode != null) { - String parentName = parentNode.getNodeName(); - if (SUB_TREE.equals(parentName)) { - returnNode = parentNode; - } else if (FUNCTIONAL_OP.equals(parentName)) { - returnNode = checkIfSubTree(parentNode.getParentNode()); - } - } - return returnNode; - } - - /** - * Gets the firt child list. - * - * @param function - * the function - * @return the firt child list - */ - public static List getFunctionalOpFirstChild(String function) { - List childList = new ArrayList<>(); - if (AGE_AT.equalsIgnoreCase(function)) { - childList.add(SUB_TREE_REF); - childList.add(RELATIONAL_OP); - childList.add(FUNCTIONAL_OP); - childList.add(ELEMENT_REF); - } else { - childList.add(ELEMENT_REF); - childList.add(SET_OP); - childList.add(SUB_TREE_REF); - childList.add(RELATIONAL_OP); - } - return childList; - } - - /** - * Gets the aggregate and instance function childs. - * - * @param typeChild - * the type child - * @return the aggregate and instance function childs - */ - public static List getAggregateAndInstanceFunctionChilds(String typeChild) { - List aggregateList = new ArrayList<>(); - aggregateList.add("FIRST"); - aggregateList.add("SECOND"); - aggregateList.add("THIRD"); - aggregateList.add("FOURTH"); - aggregateList.add("FIFTH"); - aggregateList.add("MOST RECENT"); - if ("AGGREGATE".equals(typeChild)) { - aggregateList.add("DATETIMEDIFF"); - } - return aggregateList; - } - - /** - * Gets the functional op first child in mo. - * - * @param function - * the function - * @return the functional op first child in mo - */ - public static List getFunctionalOpFirstChildInMO(String function) { - List childList = new ArrayList<>(); - if ("DATETIMEDIFF".equalsIgnoreCase(function)) { - childList.add(ELEMENT_REF); - childList.add(SUB_TREE_REF); - childList.add(RELATIONAL_OP); - childList.addAll(getAggregateAndInstanceFunctionChilds("INSTANCE")); - } else { - childList.addAll(getFunctionalOpFirstChild(function)); - childList.addAll(getAggregateAndInstanceFunctionChilds("AGGREGATE")); - } - return childList; - } - - /** - * Check for used Used sub tree ref Node map in Populations and Meausre - * Observations. - */ - private void createUsedSubTreeRefMap() { - - XmlProcessor simpleXmlProcessor = measureExport.getSimpleXmlProcessor(); - String typeXpathString = ""; - List usedSubTreeRefIdsPop = new ArrayList<>(); - List usedSubTreeRefIdsMO = new ArrayList<>(); - List usedSubTreeRefIDsRA = new ArrayList<>(); - for (String typeString : POPULATION_NAME_LIST) { - typeXpathString += "@type = '" + typeString + "' or"; - } - typeXpathString = typeXpathString.substring(0, typeXpathString.lastIndexOf(" or")); - String xpathForSubTreeInPOPClause = "/measure/measureGrouping//clause[" + typeXpathString + "]//subTreeRef/@id"; - String xpathForSubTreeInMOClause = "/measure/measureGrouping//clause[@type='measureObservation']//subTreeRef/@id"; - String xpathForSubTreeInRAClause = "/measure//riskAdjustmentVariables/subTreeRef/@id"; - try { - - // creating used Subtree Red Map in Populations - NodeList populationsSubTreeNode = simpleXmlProcessor.findNodeList(simpleXmlProcessor.getOriginalDoc(), - xpathForSubTreeInPOPClause); - for (int i = 0; i < populationsSubTreeNode.getLength(); i++) { - String uuid = populationsSubTreeNode.item(i).getNodeValue(); - uuid = checkIfQDMVarInstanceIsPresent(uuid, simpleXmlProcessor); - if (!usedSubTreeRefIdsPop.contains(uuid)) { - usedSubTreeRefIdsPop.add(uuid); - } - } - usedSubTreeRefIdsPop = checkUnUsedSubTreeRef(simpleXmlProcessor, usedSubTreeRefIdsPop); - for (String uuid : usedSubTreeRefIdsPop) { - Node subTreeNode = createUsedSubTreeRefMap(simpleXmlProcessor, uuid); - subTreeNodeInPOPMap.put(uuid, subTreeNode); - } - - // creating used Subtree Red Map in Measure Observations - NodeList measureObsSubTreeNode = simpleXmlProcessor.findNodeList(simpleXmlProcessor.getOriginalDoc(), - xpathForSubTreeInMOClause); - for (int i = 0; i < measureObsSubTreeNode.getLength(); i++) { - String uuid = measureObsSubTreeNode.item(i).getNodeValue(); - uuid = checkIfQDMVarInstanceIsPresent(uuid, simpleXmlProcessor); - if (!usedSubTreeRefIdsMO.contains(uuid)) { - usedSubTreeRefIdsMO.add(uuid); - } - } - usedSubTreeRefIdsMO = checkUnUsedSubTreeRef(simpleXmlProcessor, usedSubTreeRefIdsMO); - for (String uuid : usedSubTreeRefIdsMO) { - Node subTreeNode = createUsedSubTreeRefMap(simpleXmlProcessor, uuid); - subTreeNodeInMOMap.put(uuid, subTreeNode); - } - // creating used Subtree Red in Risk Adjustment - NodeList riskAdjSubTreeNode = simpleXmlProcessor.findNodeList(simpleXmlProcessor.getOriginalDoc(), - xpathForSubTreeInRAClause); - for (int i = 0; i < riskAdjSubTreeNode.getLength(); i++) { - String uuid = riskAdjSubTreeNode.item(i).getNodeValue(); - uuid = checkIfQDMVarInstanceIsPresent(uuid, simpleXmlProcessor); - if (!usedSubTreeRefIDsRA.contains(uuid)) { - usedSubTreeRefIDsRA.add(uuid); - } - } - usedSubTreeRefIDsRA = checkUnUsedSubTreeRef(simpleXmlProcessor, usedSubTreeRefIDsRA); - for (String uuid : usedSubTreeRefIDsRA) { - Node subTreeNode = createUsedSubTreeRefMap(simpleXmlProcessor, uuid); - subTreeNodeInRAMap.put(uuid, subTreeNode); - } - - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - - /** - * Creates the used sub tree ref map. - * - * @param simpleXmlProcessor - * the simple xml processor - * @param uuid - * the uuid - * @return the node - */ - private Node createUsedSubTreeRefMap(XmlProcessor simpleXmlProcessor, String uuid) { - String xpathforUsedSubTreeMap = "/measure/subTreeLookUp/subTree[@uuid='" + uuid + "']"; - Node subTreeNode = null; - try { - subTreeNode = simpleXmlProcessor.findNode(simpleXmlProcessor.getOriginalDoc(), xpathforUsedSubTreeMap); - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - return subTreeNode; - } - - /** - * Check un used sub tree ref. - * - * @param xmlProcessor - * the xml processor - * @param usedSubTreeRefIds - * the used sub tree ref ids - * @return the list - */ - private List checkUnUsedSubTreeRef(XmlProcessor xmlProcessor, List usedSubTreeRefIds) { - - List allSubTreeRefIds = new ArrayList<>(); - NodeList subTreeRefIdsNodeList; - javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); - try { - subTreeRefIdsNodeList = xmlProcessor.findNodeList(xmlProcessor.getOriginalDoc(), - "/measure//subTreeRef/@id"); - - for (int i = 0; i < subTreeRefIdsNodeList.getLength(); i++) { - Node SubTreeRefIdAttributeNode = subTreeRefIdsNodeList.item(i); - if (!allSubTreeRefIds.contains(SubTreeRefIdAttributeNode.getNodeValue())) { - allSubTreeRefIds.add(SubTreeRefIdAttributeNode.getNodeValue()); - } - } - allSubTreeRefIds.removeAll(usedSubTreeRefIds); - - for (int i = 0; i < usedSubTreeRefIds.size(); i++) { - for (int j = 0; j < allSubTreeRefIds.size(); j++) { - Node usedSubTreeRefNode = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), - "/measure/subTreeLookUp/subTree[@uuid='" + usedSubTreeRefIds.get(i) + "']//subTreeRef[@id='" - + allSubTreeRefIds.get(j) + "']"); - if (usedSubTreeRefNode != null) { - - String subTreeUUID = usedSubTreeRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - String XPATH_IS_INSTANCE_OF = "//subTree [boolean(@instanceOf)]/@uuid ='" + subTreeUUID + "'"; - boolean isOccurrenceNode = (Boolean) xPath.evaluate(XPATH_IS_INSTANCE_OF, - xmlProcessor.getOriginalDoc(), XPathConstants.BOOLEAN); - if (isOccurrenceNode) { - String XPATH_PARENT_UUID = "//subTree [@uuid ='" + subTreeUUID + "']/@instanceOf"; - String parentUUID = (String) xPath.evaluate(XPATH_PARENT_UUID, - xmlProcessor.getOriginalDoc(), XPathConstants.STRING); - if (!usedSubTreeRefIds.contains(parentUUID)) { - usedSubTreeRefIds.add(parentUUID); - } - - } - if (!usedSubTreeRefIds.contains(allSubTreeRefIds.get(j))) { - - usedSubTreeRefIds.add(allSubTreeRefIds.get(j)); - } - } - } - - } - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - return usedSubTreeRefIds; - } - - /** - * Validate sub tree ref in pop. - * - * @param subTreeNode - * the sub tree node - * @param functionalOpNode - * the functional op node - * @return true, if successful - */ - public boolean validateSubTreeRefInPOP(Node subTreeNode, Node functionalOpNode) { - if (subTreeNodeInPOPMap.get(subTreeNode.getAttributes().getNamedItem(UUID).getNodeValue()) != null) { - String firstChildName = functionalOpNode.getFirstChild().getNodeName(); - String functionalOpType = functionalOpNode.getAttributes().getNamedItem(TYPE).getNodeValue(); - List childsList = FUNCTIONAL_OP_RULES_IN_POP.get(functionalOpType); - if (childsList.contains(firstChildName)) { - return true; - } - } - return false; - } - - /** - * Utility method which will try to find the tag "localVariableName" and set the - * given string value to its VALUE attribute. - * - * @param node - * the node - * @param localVarName - * the local var name - */ - private void updateLocalVar(Node node, String localVarName) { - if (node == null) { - return; - } - NodeList localVarNodeList = ((Element) node).getElementsByTagName(LOCAL_VARIABLE_NAME); - if (localVarNodeList != null && localVarNodeList.getLength() > 0) { - Element localVar = (Element) localVarNodeList.item(0); - localVar.setAttribute(VALUE, localVarName); - } - } - - /** - * Check if qdm var instance is present. - * - * @param usedSubtreeRefId - * the used subtree ref id - * @param xmlProcessor - * the xml processor - * @return the string - */ - private String checkIfQDMVarInstanceIsPresent(String usedSubtreeRefId, XmlProcessor xmlProcessor) { - - String XPATH_INSTANCE_QDM_VAR = "/measure/subTreeLookUp/subTree[@uuid='" + usedSubtreeRefId + "']/@instance"; - String XPATH_INSTANCE_OF_QDM_VAR = "/measure/subTreeLookUp/subTree[@uuid='" + usedSubtreeRefId - + "']/@instanceOf"; - try { - Node nodesSDE_SubTree = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), XPATH_INSTANCE_QDM_VAR); - if (nodesSDE_SubTree != null) { - Node nodesSDE_SubTreeInstance = xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), - XPATH_INSTANCE_OF_QDM_VAR); - usedSubtreeRefId = nodesSDE_SubTreeInstance.getNodeValue(); - } - - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - - return usedSubtreeRefId; - } - - /** - * Gets the sub tree node map. - * - * @return the subTreeNodeMap - */ - public Map getSubTreeNodeMap() { - return subTreeNodeMap; - } - - /** - * Sets the sub tree node map. - * - * @param subTreeNodeMap - * the subTreeNodeMap to set - */ - public void setSubTreeNodeMap(Map subTreeNodeMap) { - this.subTreeNodeMap = subTreeNodeMap; - } - - /** - * Gets the measure export. - * - * @return the measureExport - */ - public MeasureExport getMeasureExport() { - return measureExport; - } - - /** - * Sets the measure export. - * - * @param measureExport - * the measureExport to set - */ - public void setMeasureExport(MeasureExport measureExport) { - this.measureExport = measureExport; - } - - /** - * Gets the sub tree node in mo map. - * - * @return the subTreeNodeInMOMap - */ - public Map getSubTreeNodeInMOMap() { - return subTreeNodeInMOMap; - } - - /** - * Sets the sub tree node in mo map. - * - * @param subTreeNodeInMOMap - * the subTreeNodeInMOMap to set - */ - public void setSubTreeNodeInMOMap(Map subTreeNodeInMOMap) { - this.subTreeNodeInMOMap = subTreeNodeInMOMap; - } - - /** - * Gets the sub tree node in ra map. - * - * @return the subTreeNodeInMOMap - */ - public Map getSubTreeNodeInRAMap() { - return subTreeNodeInRAMap; - } - - /** - * Sets the sub tree node in ra map. - * - * @param subTreeNodeInRAMap - * the sub tree node in ra map - */ - public void setSubTreeNodeInRAMap(Map subTreeNodeInRAMap) { - this.subTreeNodeInRAMap = subTreeNodeInRAMap; - } - - /** - * Gets the sub tree node in pop map. - * - * @return the subTreeNodeInPOPMap - */ - public Map getSubTreeNodeInPOPMap() { - return subTreeNodeInPOPMap; - } - - /** - * Sets the sub tree node in pop map. - * - * @param subTreeNodeInPOPMap - * the subTreeNodeInPOPMap to set - */ - public void setSubTreeNodeInPOPMap(Map subTreeNodeInPOPMap) { - this.subTreeNodeInPOPMap = subTreeNodeInPOPMap; - } + private static final String GROUPER_CRITERIA = "grouperCriteria"; + private static final String CONJUNCTION_CODE = "conjunctionCode"; + private static final String LOCAL_VARIABLE_NAME = "localVariableName"; + private static final String CRITERIA_REFERENCE = "criteriaReference"; + + private static final String ROLE = "role"; + + private static final String PARTICIPATION = "participation"; + + private static final String EXCERPT = "excerpt"; + + private static final String SEQUENCE_NUMBER = "sequenceNumber"; + + private static final String GROUPER = "grouper"; + + private static final String ENTRY = "entry"; + + private static final String DATA_CRITERIA_SECTION = "dataCriteriaSection"; + + private Map subTreeNodeMap = new HashMap<>(); + + public MeasureExport measureExport; + + private static final Logger logger = LoggerFactory.getLogger(HQMFClauseLogicGenerator.class); + + /** MAP of Functional Ops NON Subset Type. */ + private static final Map FUNCTIONAL_OPS_NON_SUBSET = + new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + /** MAP of Functional Ops Subset Type. */ + private static final Map FUNCTIONAL_OPS_SUBSET = + new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + static { + FUNCTIONAL_OPS_NON_SUBSET.put(MatConstants.FIRST, "1"); + FUNCTIONAL_OPS_NON_SUBSET.put(MatConstants.SECOND, "2"); + FUNCTIONAL_OPS_NON_SUBSET.put(MatConstants.THIRD, "3"); + FUNCTIONAL_OPS_NON_SUBSET.put(MatConstants.FOURTH, "4"); + FUNCTIONAL_OPS_NON_SUBSET.put(MatConstants.FIFTH, "5"); + + FUNCTIONAL_OPS_SUBSET.put(MatConstants.MOST_RECENT, "QDM_LAST"); + FUNCTIONAL_OPS_SUBSET.put(MatConstants.COUNT, "QDM_SUM"); + FUNCTIONAL_OPS_SUBSET.put(MatConstants.MIN, "QDM_MIN"); + FUNCTIONAL_OPS_SUBSET.put(MatConstants.MAX, "QDM_MAX"); + FUNCTIONAL_OPS_SUBSET.put(MatConstants.SUM, "QDM_SUM"); + FUNCTIONAL_OPS_SUBSET.put(MatConstants.MEDIAN, "QDM_MEDIAN"); + FUNCTIONAL_OPS_SUBSET.put(MatConstants.AVG, "QDM_AVERAGE"); + } + + /** The Constant populations. */ + private static final List POPULATION_NAME_LIST = new ArrayList<>(); + + static { + POPULATION_NAME_LIST.add("initialPopulation"); + POPULATION_NAME_LIST.add("denominator"); + POPULATION_NAME_LIST.add("denominatorExclusions"); + POPULATION_NAME_LIST.add("denominatorExceptions"); + POPULATION_NAME_LIST.add("numerator"); + POPULATION_NAME_LIST.add("numeratorExclusions"); + POPULATION_NAME_LIST.add("measurePopulation"); + POPULATION_NAME_LIST.add("measurePopulationExclusions"); + POPULATION_NAME_LIST.add("stratum"); + } + + /** The sub tree node in mo map. */ + Map subTreeNodeInMOMap = new HashMap<>(); + + /** The sub tree node in pop map. */ + Map subTreeNodeInPOPMap = new HashMap<>(); + + /** The sub tree node in RA map. */ + Map subTreeNodeInRAMap = new HashMap<>(); + + /** The Constant FUNCTIONAL_OP_RULES_IN_POP. */ + private static final Map> FUNCTIONAL_OP_RULES_IN_POP = + new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + /** The Constant FUNCTIONAL_OP_RULES_IN_MO. */ + private static final Map> FUNCTIONAL_OP_RULES_IN_MO = + new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + static { + FUNCTIONAL_OP_RULES_IN_POP.put("MEDIAN", getFunctionalOpFirstChild("MEDIAN")); + FUNCTIONAL_OP_RULES_IN_POP.put("AVG", getFunctionalOpFirstChild("AVG")); + FUNCTIONAL_OP_RULES_IN_POP.put("MAX", getFunctionalOpFirstChild("MAX")); + FUNCTIONAL_OP_RULES_IN_POP.put("MIN", getFunctionalOpFirstChild("MIN")); + FUNCTIONAL_OP_RULES_IN_POP.put("SUM", getFunctionalOpFirstChild("SUM")); + FUNCTIONAL_OP_RULES_IN_POP.put("COUNT", getFunctionalOpFirstChild("COUNT")); + FUNCTIONAL_OP_RULES_IN_POP.put("FIRST", getFunctionalOpFirstChild("FIRST")); + FUNCTIONAL_OP_RULES_IN_POP.put("SECOND", getFunctionalOpFirstChild("SECOND")); + FUNCTIONAL_OP_RULES_IN_POP.put("THIRD", getFunctionalOpFirstChild("THIRD")); + FUNCTIONAL_OP_RULES_IN_POP.put("FOURTH", getFunctionalOpFirstChild("FOURTH")); + FUNCTIONAL_OP_RULES_IN_POP.put("FIFTH", getFunctionalOpFirstChild("FIFTH")); + FUNCTIONAL_OP_RULES_IN_POP.put("MOST RECENT", getFunctionalOpFirstChild("MOST RECENT")); + FUNCTIONAL_OP_RULES_IN_POP.put("AGE AT", getFunctionalOpFirstChild("AGE AT")); + + /* Rules for Functions in Measure Observations */ + FUNCTIONAL_OP_RULES_IN_MO.put("MEDIAN", getFunctionalOpFirstChildInMO("MEDIAN")); + FUNCTIONAL_OP_RULES_IN_MO.put("AVERAGE", getFunctionalOpFirstChildInMO("AVERAGE")); + FUNCTIONAL_OP_RULES_IN_MO.put("MIN", getFunctionalOpFirstChildInMO("MIN")); + FUNCTIONAL_OP_RULES_IN_MO.put("SUM", getFunctionalOpFirstChildInMO("SUM")); + FUNCTIONAL_OP_RULES_IN_MO.put("COUNT", getFunctionalOpFirstChildInMO("COUNT")); + FUNCTIONAL_OP_RULES_IN_MO.put("DATETIMEDIFF", getFunctionalOpFirstChildInMO("DATETIMEDIFF")); + } + + @Override + public String generate(MeasureExport me) throws Exception { + measureExport = me; + createUsedSubTreeRefMap(); + generateSubTreeXML(); + return null; + } + + /** + * Generate sub tree xml. + * + * @throws XPathExpressionException the x path expression exception + */ + private void generateSubTreeXML() throws XPathExpressionException { + String xpath = "/measure/subTreeLookUp/subTree[not(@instance)]"; + NodeList subTreeNodeList = + measureExport + .getSimpleXmlProcessor() + .findNodeList(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); + for (int i = 0; i < subTreeNodeList.getLength(); i++) { + Node subTreeNode = subTreeNodeList.item(i); + subTreeNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + String uuid = subTreeNode.getAttributes().getNamedItem(UUID).getNodeValue(); + if (subTreeNodeInPOPMap.containsKey(uuid) && subTreeNodeInMOMap.containsKey(uuid) + || subTreeNodeInPOPMap.containsKey(uuid) + || subTreeNodeInRAMap.containsKey(uuid)) { + generateSubTreeXML(subTreeNode, false); + } + } + String xpathOccurrence = "/measure/subTreeLookUp/subTree[(@instance)]"; + NodeList occurrenceSubTreeNodeList = + measureExport + .getSimpleXmlProcessor() + .findNodeList(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpathOccurrence); + for (int i = 0; i < occurrenceSubTreeNodeList.getLength(); i++) { + Node subTreeNode = occurrenceSubTreeNodeList.item(i); + generateOccHQMF(subTreeNode); + } + } + + /** + * Generate sub tree xml. + * + * @param subTreeNode the sub tree node + * @param msrObsDateTimeDiffSubTree the msr obs date time diff sub tree + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + protected Node generateSubTreeXML(Node subTreeNode, boolean msrObsDateTimeDiffSubTree) + throws XPathExpressionException { + + // If this is an empty or NULL clause, return right now. + if (subTreeNode == null || !subTreeNode.hasChildNodes()) { + return null; + } + + /* + If this is a Occurrence clause then we need to find the base clause and + generate HQMF for the base clause. Then we need to generate Occurrence HQMF + for the occurrence clause. + */ + if (subTreeNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + String baseClauseUUID = subTreeNode.getAttributes().getNamedItem(INSTANCE_OF).getNodeValue(); + String xpath = "/measure/subTreeLookUp/subTree[@uuid = '" + baseClauseUUID + "']"; + Node baseSubTreeNode = + measureExport + .getSimpleXmlProcessor() + .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); + generateSubTreeXML(baseSubTreeNode, false); + generateOccHQMF(subTreeNode); + } + + String subTreeUUID = subTreeNode.getAttributes().getNamedItem(UUID).getNodeValue(); + String clauseName = subTreeNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + Boolean isRav = isRiskAdjustmentVariable(subTreeUUID, clauseName); + + // Check the 'subTreeNodeMap' to make sure the clause isn't already generated. + if (subTreeNodeMap.containsKey(subTreeUUID) && !msrObsDateTimeDiffSubTree) { + logger.debug("HQMF for Clause " + clauseName + " is already generated. Skipping."); + return null; + } + + // get the first child of the subTreeNode + Node firstChild = subTreeNode.getFirstChild(); + String firstChildName = firstChild.getNodeName(); + logger.debug( + "Generating HQMF for clause:'" + + clauseName + + "' with first child named:'" + + firstChildName + + "'."); + + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + Element dataCriteriaSectionElem = + (Element) + hqmfXmlProcessor.getOriginalDoc().getElementsByTagName(DATA_CRITERIA_SECTION).item(0); + + if (isRav) { + Comment riskAdjustmentVariable = + hqmfXmlProcessor.getOriginalDoc().createComment("Risk Adjustment Variable"); + dataCriteriaSectionElem.appendChild(riskAdjustmentVariable); + } + Node entryElement = null; + switch (firstChildName) { + case SET_OP: + entryElement = generateSetOpHQMF(firstChild, dataCriteriaSectionElem, clauseName); + break; + case ELEMENT_REF: + entryElement = generateElementRefHQMF(firstChild, dataCriteriaSectionElem, clauseName); + break; + case SUB_TREE_REF: + entryElement = generateSubTreeHQMF(firstChild, dataCriteriaSectionElem, clauseName); + break; + case RELATIONAL_OP: + entryElement = generateRelOpHQMF(firstChild, dataCriteriaSectionElem, clauseName); + break; + case FUNCTIONAL_OP: + entryElement = generateFunctionalOpHQMF(firstChild, dataCriteriaSectionElem, clauseName); + break; + default: + // Dont do anything + break; + } + if (isRav) { + Node temp = hqmfXmlProcessor.getOriginalDoc().createAttribute(RAV); + temp.setNodeValue("true"); + entryElement.getAttributes().setNamedItem(temp); + } + /* + The clause is generated now. Make an entry in the 'subTreeNodeMap' to keep + track of its generation. + */ + subTreeNodeMap.put(subTreeUUID, subTreeNode); + return entryElement; + } + + /** + * This method is used to discover weither a given class name and UUID is a risk adjustment + * variable. + * + * @param subTreeUUID the sub tree uuid + * @param clauseName the clause name + * @return the boolean + */ + private Boolean isRiskAdjustmentVariable(String subTreeUUID, String clauseName) { + String xPath = + "/measure/riskAdjustmentVariables/subTreeRef[@displayName=\"" + + clauseName + + "\" and @id='" + + subTreeUUID + + "']"; + boolean isRiskAdjustmentVariable = false; + try { + Node riskAdjVarNode = + measureExport + .getSimpleXmlProcessor() + .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xPath); + if (riskAdjVarNode != null) { + isRiskAdjustmentVariable = true; + } + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + return isRiskAdjustmentVariable; + } + + /** + * Generate occ hqmf. + * + * @param subTreeNode the sub tree node + * @throws XPathExpressionException the x path expression exception + */ + private void generateOccHQMF(Node subTreeNode) throws XPathExpressionException { + // If this is an empty or NULL clause, return right now. + if (subTreeNode == null || subTreeNode.getAttributes().getNamedItem(INSTANCE_OF) == null) { + return; + } + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + String occSubTreeUUID = subTreeNode.getAttributes().getNamedItem(UUID).getNodeValue(); + String qdmVariableSubTreeUUID = + subTreeNode.getAttributes().getNamedItem(INSTANCE_OF).getNodeValue(); + String clauseName = subTreeNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + Boolean isRAV = isRiskAdjustmentVariable(qdmVariableSubTreeUUID, clauseName); + // Check the 'subTreeNodeMap' to make sure the occ clause isn't already generated. + if (subTreeNodeMap.containsKey(occSubTreeUUID)) { + logger.debug("HQMF for Occ Clause " + clauseName + " is already generated. Skipping."); + return; + } + + if (!subTreeNodeMap.containsKey(qdmVariableSubTreeUUID)) { + logger.debug("HQMF for Clause " + clauseName + " is not already generated. Skipping."); + return; + } + + String xpath = "/measure/subTreeLookUp/subTree[@uuid = '" + qdmVariableSubTreeUUID + "']"; + Node baseSubTreeNode = + measureExport + .getSimpleXmlProcessor() + .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); + Node baseFirstChild = baseSubTreeNode.getFirstChild(); + String baseExt = baseFirstChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + + Node firstChild = subTreeNode.getFirstChild(); + String firstChildName = firstChild.getNodeName(); + String ext = firstChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + // Local Variable Name. + String localVarName = clauseName.replace("$", "") + "_" + UUIDUtilClient.uuid(5); + String root = subTreeNode.getAttributes().getNamedItem(INSTANCE_OF).getNodeValue(); + // Check for Element Ref as first CHild. + if (firstChildName.equalsIgnoreCase(ELEMENT_REF)) { + ext = getElementRefExt(firstChild, measureExport.getSimpleXmlProcessor()); + baseExt = getElementRefExt(baseFirstChild, measureExport.getSimpleXmlProcessor()); + } else if (RELATIONAL_OP.equals(firstChildName) + || FUNCTIONAL_OP.equals(firstChildName) + || SET_OP.equals(firstChildName)) { + ext += "_" + firstChild.getAttributes().getNamedItem(UUID).getNodeValue(); + baseExt += "_" + baseFirstChild.getAttributes().getNamedItem(UUID).getNodeValue(); + } + + if (FUNCTIONAL_OP.equals(firstChildName) && firstChild.getFirstChild() != null) { + Node functionChild = firstChild.getFirstChild(); + Node baseFunctionChild = baseFirstChild.getFirstChild(); + + if (functionChild != null) { + if (functionChild.getNodeName().equalsIgnoreCase(SUB_TREE_REF)) { + ext = functionChild.getAttributes().getNamedItem(ID).getNodeValue(); + baseExt = baseFunctionChild.getAttributes().getNamedItem(ID).getNodeValue(); + } else if (functionChild.getNodeName().equalsIgnoreCase(ELEMENT_REF)) { + ext = getElementRefExt(functionChild, measureExport.getSimpleXmlProcessor()); + baseExt = getElementRefExt(baseFunctionChild, measureExport.getSimpleXmlProcessor()); + } else { + ext = + StringUtils.deleteWhitespace( + functionChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + "_" + + functionChild.getAttributes().getNamedItem(UUID).getNodeValue()) + .replaceAll(":", "_"); + baseExt = + StringUtils.deleteWhitespace( + baseFunctionChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + "_" + + baseFunctionChild.getAttributes().getNamedItem(UUID).getNodeValue()) + .replaceAll(":", "_"); + } + } + } + + String isQdmVariable = subTreeNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (isQdmVariable.equalsIgnoreCase(TRUE)) { + ext = "qdm_var_" + StringUtils.deleteWhitespace(ext); + baseExt = "qdm_var_" + StringUtils.deleteWhitespace(baseExt); + localVarName = "qdm_var_" + StringUtils.deleteWhitespace(localVarName); + } + String extForOccurrenceNode = + "occ" + subTreeNode.getAttributes().getNamedItem("instance").getNodeValue() + "of_" + ext; + ext = StringUtils.deleteWhitespace(ext); + localVarName = StringUtils.deleteWhitespace(localVarName); + logger.debug( + "generateOccHQMF " + "//entry/*/id[@root='" + root + "'][@extension=\"" + baseExt + "\"]"); + + Node idNodeQDM = + hqmfXmlProcessor.findNode( + hqmfXmlProcessor.getOriginalDoc(), + "//entry/*/id[@root='" + root + "'][@extension=\"" + baseExt + "\"]"); + logger.debug("idNodeQDM == null?" + (idNodeQDM == null)); + + if (idNodeQDM != null) { + // Add code here which will create a replica of the entry elem of 'idNodeQDM' + // and assign it an extension + // which has "Occ_X" string in it. + Node cloneMainEntryNode = idNodeQDM.getParentNode().getParentNode().cloneNode(true); + Node cloneIDNode = findNode(cloneMainEntryNode, "ID"); + if (cloneMainEntryNode != null) { + Node localVariableNode = cloneMainEntryNode.getFirstChild(); + if (localVariableNode.getAttributes().getNamedItem("value") != null) { + localVariableNode.getAttributes().getNamedItem("value").setNodeValue(localVarName); + } + } + cloneIDNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(extForOccurrenceNode); + + Element dataCriteriaSectionElem = + (Element) + hqmfXmlProcessor.getOriginalDoc().getElementsByTagName(DATA_CRITERIA_SECTION).item(0); + + dataCriteriaSectionElem.appendChild(cloneMainEntryNode); + + Node parentNode = cloneIDNode.getParentNode().cloneNode(false); + if (isRAV) { + Comment RAComment = + hqmfXmlProcessor.getOriginalDoc().createComment("Risk Adjustment Variable"); + dataCriteriaSectionElem.appendChild(RAComment); + } + Element entryElem = hqmfXmlProcessor.getOriginalDoc().createElement(ENTRY); + entryElem.setAttribute(TYPE_CODE, "DRIV"); + Element idElement = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + idElement.setAttribute(ROOT, subTreeNode.getAttributes().getNamedItem(UUID).getNodeValue()); + idElement.setAttribute(EXTENSION, extForOccurrenceNode); + parentNode.appendChild(idElement); + Element outboundRelElem = + hqmfXmlProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); + outboundRelElem.setAttribute(TYPE_CODE, "OCCR"); + + Element criteriaRefElem = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + String refClassCodeValue = parentNode.getAttributes().getNamedItem(CLASS_CODE).getNodeValue(); + String refMoodValue = parentNode.getAttributes().getNamedItem(MOOD_CODE).getNodeValue(); + criteriaRefElem.setAttribute(CLASS_CODE, refClassCodeValue); + criteriaRefElem.setAttribute(MOOD_CODE, refMoodValue); + + Element idRelElem = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + idRelElem.setAttribute(ROOT, root); + idRelElem.setAttribute(EXTENSION, extForOccurrenceNode); + + criteriaRefElem.appendChild(idRelElem); + outboundRelElem.appendChild(criteriaRefElem); + parentNode.appendChild(outboundRelElem); + entryElem.appendChild(parentNode); + dataCriteriaSectionElem.appendChild(entryElem); + + subTreeNodeMap.put(occSubTreeUUID, subTreeNode); + } + } + + /** + * Generate functional op hqmf. + * + * @param functionalNode the functional node + * @param dataCriteriaSectionElem the data criteria section elem + * @param clauseName the clause name + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + private Node generateFunctionalOpHQMF( + Node functionalNode, Element dataCriteriaSectionElem, String clauseName) + throws XPathExpressionException { + Node node = null; + if (functionalNode.getChildNodes() != null) { + Node firstChildNode = functionalNode.getFirstChild(); + String firstChildName = firstChildNode.getNodeName(); + switch (firstChildName) { + case SET_OP: + String functionOpType = functionalNode.getAttributes().getNamedItem(TYPE).getNodeValue(); + if (FUNCTIONAL_OPS_NON_SUBSET.containsKey(functionOpType.toUpperCase()) + || FUNCTIONAL_OPS_SUBSET.containsKey(functionOpType.toUpperCase())) { + node = generateSetOpHQMF(firstChildNode, dataCriteriaSectionElem, clauseName); + } + break; + case ELEMENT_REF: + node = generateElementRefHQMF(firstChildNode, dataCriteriaSectionElem, clauseName); + break; + case RELATIONAL_OP: + node = generateRelOpHQMF(firstChildNode, dataCriteriaSectionElem, clauseName); + break; + case FUNCTIONAL_OP: + // findFunctionalOpChild(firstChildNode, dataCriteriaSectionElem); + break; + case SUB_TREE_REF: + node = + generateSubTreeHQMFInFunctionalOp( + firstChildNode, dataCriteriaSectionElem, clauseName); + break; + default: + // Dont do anything + break; + } + + String localVarName = clauseName; + + localVarName = localVarName.replace("$", ""); + Node parentNode = functionalNode.getParentNode(); + if (parentNode != null && parentNode.getNodeName().equalsIgnoreCase("subTree")) { + if (parentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { + String isQdmVariable = + parentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + localVarName = localVarName.replace("$", ""); + localVarName = "qdm_var_" + localVarName; + } + } + localVarName = localVarName + "_" + UUIDUtilClient.uuid(5); + localVarName = StringUtils.deleteWhitespace(localVarName); + updateLocalVar(node, localVarName); + } + } + return node; + } + + /** + * Method to generate HQMF for function Ops with first child as subTreeRef. In this case + * grouperCriteria will be generated for SubTreeRef with Excerpt entry inside it for functional + * Op. + * + * @param firstChildNode - SubTreeRef Node. + * @param dataCriteriaSectionElem - Data Criteria Element. + * @param clauseName the clause name + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + private Node generateSubTreeHQMFInFunctionalOp( + Node firstChildNode, Element dataCriteriaSectionElem, String clauseName) + throws XPathExpressionException { + Node parentNode = firstChildNode.getParentNode(); + + // temp node. + String subTreeUUID = firstChildNode.getAttributes().getNamedItem(ID).getNodeValue(); + String xpath = "/measure/subTreeLookUp/subTree[@uuid='" + subTreeUUID + "']"; + Node subTreeNode = + measureExport + .getSimpleXmlProcessor() + .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); + String firstChildNameOfSubTree = subTreeNode.getFirstChild().getNodeName(); + if (FUNCTIONAL_OP.equals(firstChildNameOfSubTree)) { + String firstChildNodeName = parentNode.getAttributes().getNamedItem(TYPE).getNodeValue(); + if (!SATISFIES_ALL.equalsIgnoreCase(firstChildNodeName) + || !SATISFIES_ANY.equalsIgnoreCase(firstChildNodeName) + || !AGE_AT.equals(firstChildNodeName)) { + return null; + } + } + Element root = measureExport.getHqmfXmlProcessor().getOriginalDoc().createElement("temp"); + generateSubTreeHQMF(firstChildNode, root, clauseName); + Element entryElement = (Element) root.getFirstChild(); + Node firstChild = entryElement.getFirstChild(); + if ("localVariableName".equals(firstChild.getNodeName())) { + firstChild = firstChild.getNextSibling(); + } + Element excerpt = + generateExcerptEntryForFunctionalNode( + parentNode, null, measureExport.getHqmfXmlProcessor(), entryElement); + if (excerpt != null) { + firstChild.appendChild(excerpt); + } + dataCriteriaSectionElem.appendChild(entryElement); + return entryElement; + } + + /** + * This will take care of the use case where a user can create a Clause with only one QDM + * elementRef inside it. We will make a copy of the original entry for QDM and update the id@root + * and id@extension for it. This will server as an entry for the Clause. + * + * @param elementRefNode the element ref node + * @param parentNode the parent node + * @param clauseName the clause name + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + private Node generateElementRefHQMF(Node elementRefNode, Node parentNode, String clauseName) + throws XPathExpressionException { + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + Node node = null; + String ext = getElementRefExt(elementRefNode, measureExport.getSimpleXmlProcessor()); + String root = elementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + String localVariableName = clauseName; + Node idNodeQDM = + hqmfXmlProcessor.findNode( + hqmfXmlProcessor.getOriginalDoc(), + "//entry/*/id[@root='" + root + "'][@extension=\"" + ext + "\"]"); + if (idNodeQDM != null) { + Node entryElem = idNodeQDM.getParentNode().getParentNode().cloneNode(true); + Node newIdNode = getTagFromEntry(entryElem, ID); + + if (newIdNode == null) { + return null; + } + + String idroot = "0"; + Node parNode = elementRefNode.getParentNode(); + if (parNode != null && SUB_TREE.equals(parNode.getNodeName())) { + idroot = parNode.getAttributes().getNamedItem(UUID).getNodeValue(); + // Added logic to show qdm_variable in extension if clause is of qdm variable + // type. + String isQdmVariable = parNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (isQdmVariable.equalsIgnoreCase(TRUE)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (parNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = "occ" + parNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + "of_"; + } + if (occText != null) { + ext = occText + "qdm_var_" + ext; + } else { + ext = "qdm_var_" + ext; + localVariableName = "qdm_var_" + localVariableName; + } + } + localVariableName = localVariableName + "_" + UUIDUtilClient.uuid(5); + localVariableName = StringUtils.deleteWhitespace(localVariableName); + ((Element) newIdNode).setAttribute(ROOT, idroot); + ((Element) newIdNode).setAttribute(EXTENSION, ext); + Node localVariableNode = entryElem.getFirstChild(); + if (localVariableNode.getAttributes().getNamedItem("value") != null) { + localVariableNode.getAttributes().getNamedItem("value").setNodeValue(localVariableName); + } + + parentNode.appendChild(entryElem); + node = entryElem; + } else { + // if the the parentNode for ElementRef is other than SubTreeNode + Element excerptElement = null; + Node subTreeParentNode = checkIfSubTree(parNode); + if (subTreeParentNode != null) { + root = subTreeParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); + if (subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { + String isQdmVariable = + subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (subTreeParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = + "occ" + + subTreeParentNode.getAttributes().getNamedItem("instance").getNodeValue() + + "of_"; + } + if (occText != null) { + ext = occText + "qdm_var_" + ext; + } else { + ext = "qdm_var_" + ext; + } + } + } + } else { + root = java.util.UUID.randomUUID().toString(); + } + + Node entryNodeForElementRef = idNodeQDM.getParentNode().getParentNode(); + Node clonedEntryNodeForElementRef = entryNodeForElementRef.cloneNode(true); + NodeList idChildNodeList = + ((Element) clonedEntryNodeForElementRef).getElementsByTagName(ID); + if (idChildNodeList != null && idChildNodeList.getLength() > 0) { + Node idChildNode = idChildNodeList.item(0); + idChildNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); + idChildNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); + } + + Node firstChild = clonedEntryNodeForElementRef.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { + firstChild = firstChild.getNextSibling(); + } + // Added logic to show qdm_variable in extension if clause is of qdm variable + // type. + if (FUNCTIONAL_OP.equals(parNode.getNodeName())) { + excerptElement = + generateExcerptEntryForFunctionalNode( + parNode, elementRefNode, hqmfXmlProcessor, clonedEntryNodeForElementRef); + } + + if (excerptElement != null) { + + firstChild.appendChild(excerptElement); + } + parentNode.appendChild(clonedEntryNodeForElementRef); + node = clonedEntryNodeForElementRef; + } + updateLocalVar(node, ext); + } + + return node; + } + + /** + * This will take care of the use case where a user can create a Clause with only one child Clause + * inside it. If HQMF for the child clause is already generated, then since we have no way of + * referencing this child clause using directly, we are adding it to a + * default UNION grouper. + * + *

If it isnt generated then we generate it and then add a criteriaRef to it inside a default + * UNION. + * + * @param subTreeRefNode the sub tree ref node + * @param parentNode the parent node + * @param clauseName the clause name + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + private Node generateSubTreeHQMF(Node subTreeRefNode, Node parentNode, String clauseName) + throws XPathExpressionException { + + String subTreeUUID = subTreeRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + + /* + * Check if the Clause has already been generated. If it is not generated yet, + * then generate it by calling the 'generateSubTreeXML' method. + */ + if (!subTreeNodeMap.containsKey(subTreeUUID)) { + String xpath = "/measure/subTreeLookUp/subTree[@uuid='" + subTreeUUID + "']"; + Node subTreeNode = + measureExport + .getSimpleXmlProcessor() + .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); + generateSubTreeXML(subTreeNode, false); + } + + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + + // creating Entry Tag + Element entryElem = hqmfXmlProcessor.getOriginalDoc().createElement(ENTRY); + entryElem.setAttribute(TYPE_CODE, "DRIV"); + String root = java.util.UUID.randomUUID().toString(); + String ext = subTreeRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + String localVarName = clauseName; + localVarName = localVarName.replace("$", ""); + Node parNode = checkIfSubTree(subTreeRefNode.getParentNode()); + if (parNode != null) { + root = parNode.getAttributes().getNamedItem(UUID).getNodeValue(); + if (parNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { + String isQdmVariable = parNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (parNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = "occ" + parNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + "of_"; + } + if (occText != null) { + ext = occText + "qdm_var_" + ext; + } else { + ext = "qdm_var_" + ext; + localVarName = "qdm_var_" + localVarName; + } + } + } + } + + Node grouperElem = generateEmptyGrouper(hqmfXmlProcessor, root, ext); + + // generate comment + Comment comment = + hqmfXmlProcessor + .getOriginalDoc() + .createComment( + "outBoundRelationship for " + + subTreeRefNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + grouperElem.appendChild(comment); + + // generate outboundRelationship + Element outboundRelElem = generateEmptyOutboundElem(hqmfXmlProcessor); + Element conjunctionCodeElem = hqmfXmlProcessor.getOriginalDoc().createElement(CONJUNCTION_CODE); + conjunctionCodeElem.setAttribute(CODE, "OR"); + + outboundRelElem.appendChild(conjunctionCodeElem); + generateCritRefForNode(outboundRelElem, subTreeRefNode); + + grouperElem.appendChild(outboundRelElem); + + Element localVarElem = hqmfXmlProcessor.getOriginalDoc().createElement(LOCAL_VARIABLE_NAME); + localVarName = localVarName + "_" + UUIDUtilClient.uuid(5); + localVarName = StringUtils.deleteWhitespace(localVarName); + localVarElem.setAttribute(VALUE, localVarName); + entryElem.appendChild(localVarElem); + + entryElem.appendChild(grouperElem); + parentNode.appendChild(entryElem); + return entryElem; + } + + /** + * This method wil generate HQMF code for setOp (UNION,INTERSECTION). + * + * @param setOpNode the set op node + * @param parentNode the parent node + * @param clauseName the clause name + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + private Node generateSetOpHQMF(Node setOpNode, Node parentNode, String clauseName) + throws XPathExpressionException { + + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + // DISPLAY NAME is used instead of type as it is in Title case. + String setOpType = setOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + String conjunctionType = "OR"; + + if ("union".equalsIgnoreCase(setOpType) || SATISFIES_ANY.equalsIgnoreCase(setOpType)) { + conjunctionType = "OR"; + } else if ("intersection".equalsIgnoreCase(setOpType) + || SATISFIES_ALL.equalsIgnoreCase(setOpType)) { + conjunctionType = "AND"; + } + + // creating Entry Tag + Element entryElem = hqmfXmlProcessor.getOriginalDoc().createElement(ENTRY); + entryElem.setAttribute(TYPE_CODE, "DRIV"); + + // creating grouperCriteria element + String root = "0"; + // String ext = setOpType.toUpperCase(); + + String ext = setOpType + "_" + setOpNode.getAttributes().getNamedItem(UUID).getNodeValue(); + String localVariableName = + clauseName + "_" + setOpNode.getAttributes().getNamedItem(UUID).getNodeValue(); + Node subTreeParentNode = checkIfSubTree(setOpNode.getParentNode()); + if (subTreeParentNode != null) { + root = subTreeParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); + if (subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { + String isQdmVariable = + subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (subTreeParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = + "occ" + + subTreeParentNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + + "of_"; + } + if (occText != null) { + ext = occText + "qdm_var_" + ext; + } else { + ext = "qdm_var_" + ext; + } + localVariableName = "qdm_var_" + localVariableName; + } + } + } else { + root = java.util.UUID.randomUUID().toString(); + } + + Node grouperElem = generateEmptyGrouper(hqmfXmlProcessor, root, ext); + Node templateIdNode = getTemplateIdForSatisfies(hqmfXmlProcessor, setOpType); + if (templateIdNode != null) { + grouperElem.insertBefore(templateIdNode, grouperElem.getFirstChild()); + } + + NodeList childNodes = setOpNode.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node childNode = childNodes.item(i); + String childName = childNode.getNodeName(); + if ("comment".equals(childName)) { + continue; + } + + // generate comment + Comment comment = + hqmfXmlProcessor + .getOriginalDoc() + .createComment( + "outBoundRelationship for " + + childNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + grouperElem.appendChild(comment); + + // generate outboundRelationship + Element outboundRelElem = generateEmptyOutboundElem(hqmfXmlProcessor); + Element conjunctionCodeElem = + hqmfXmlProcessor.getOriginalDoc().createElement(CONJUNCTION_CODE); + conjunctionCodeElem.setAttribute(CODE, conjunctionType); + + outboundRelElem.appendChild(conjunctionCodeElem); + if (ELEMENT_REF.equals(childName) || SUB_TREE_REF.equals(childName)) { + generateCritRefForNode(outboundRelElem, childNode); + } else { + switch (childName) { + case SET_OP: + generateCritRefSetOp( + parentNode, hqmfXmlProcessor, childNode, outboundRelElem, clauseName); + break; + case RELATIONAL_OP: + generateCritRefRelOp( + parentNode, hqmfXmlProcessor, childNode, outboundRelElem, clauseName); + break; + case FUNCTIONAL_OP: + generateCritRefFunctionalOp(childNode, outboundRelElem, clauseName); + break; + + default: + // Dont do anything + break; + } + } + grouperElem.appendChild(outboundRelElem); + } + + // Added logic to show qdm_variable in extension if clause is of qdm variable + // type. + Node grouperEntryNode = grouperElem.cloneNode(true); + if (FUNCTIONAL_OP.equals(setOpNode.getParentNode().getNodeName())) { + Element excerptElement = + generateExcerptEntryForFunctionalNode( + setOpNode.getParentNode(), null, hqmfXmlProcessor, grouperEntryNode); + // Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("excerpt + // for + // "+setOpNode.getParentNode().getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + // grouperElem.appendChild(comment); + grouperElem.appendChild(excerptElement); + } + Element localVarElem = hqmfXmlProcessor.getOriginalDoc().createElement(LOCAL_VARIABLE_NAME); + localVarElem.setAttribute(VALUE, StringUtils.deleteWhitespace(localVariableName)); + entryElem.appendChild(localVarElem); + + entryElem.appendChild(grouperElem); + parentNode.appendChild(entryElem); + + return entryElem; + } + + /** + * Generate crit ref functional op. + * + * @param childNode -Node + * @param outboundRelElem - outBoundElement + * @param clauseName the clause name + * @throws XPathExpressionException -Exception + */ + private void generateCritRefFunctionalOp( + Node childNode, Element outboundRelElem, String clauseName) throws XPathExpressionException { + Element dataCriteriaSectionElem = + (Element) + measureExport + .getHqmfXmlProcessor() + .getOriginalDoc() + .getElementsByTagName(DATA_CRITERIA_SECTION) + .item(0); + Node entryNode = generateFunctionalOpHQMF(childNode, dataCriteriaSectionElem, clauseName); + if (entryNode != null && entryNode.getNodeName().equals(ENTRY)) { + Node fChild = entryNode.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(fChild.getNodeName())) { + fChild = fChild.getNextSibling(); + } + // create criteriaRef + Element criteriaReference = + measureExport.getHqmfXmlProcessor().getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaReference.setAttribute( + CLASS_CODE, fChild.getAttributes().getNamedItem(CLASS_CODE).getNodeValue()); + criteriaReference.setAttribute( + MOOD_CODE, fChild.getAttributes().getNamedItem(MOOD_CODE).getNodeValue()); + NodeList childNodeList = fChild.getChildNodes(); + for (int j = 0; j < childNodeList.getLength(); j++) { + Node entryChildNodes = childNodeList.item(j); + if (entryChildNodes.getNodeName().equalsIgnoreCase(ID)) { + Element id = measureExport.getHqmfXmlProcessor().getOriginalDoc().createElement(ID); + id.setAttribute(ROOT, entryChildNodes.getAttributes().getNamedItem(ROOT).getNodeValue()); + id.setAttribute( + EXTENSION, entryChildNodes.getAttributes().getNamedItem(EXTENSION).getNodeValue()); + criteriaReference.appendChild(id); + outboundRelElem.appendChild(criteriaReference); + break; + } + } + } + } + + /** + * This method is used to create a tag for SATISFIES ALL/SATISFIES ANY functionalOps. + * These are functionalOp's but are converted to setOps and treated as Groupers. + * + * @param hqmfXmlProcessor the hqmf xml processor + * @param type the type + * @return the template id for satisfies + */ + private Node getTemplateIdForSatisfies(XmlProcessor hqmfXmlProcessor, String type) { + Node templateIdNode = null; + + if (SATISFIES_ALL.equalsIgnoreCase(type) || SATISFIES_ANY.equalsIgnoreCase(type)) { + templateIdNode = hqmfXmlProcessor.getOriginalDoc().createElement(TEMPLATE_ID); + Element itemNode = hqmfXmlProcessor.getOriginalDoc().createElement(ITEM); + + // initialize rootOID with the OID for SATISFIES ALL + String rootOID = "2.16.840.1.113883.10.20.28.3.109"; + // if we are dealing with SATISFIES ANY change the OID + if (SATISFIES_ANY.equalsIgnoreCase(type)) { + rootOID = "2.16.840.1.113883.10.20.28.3.108"; + } + itemNode.setAttribute(ROOT, rootOID); + + templateIdNode.appendChild(itemNode); + } + + return templateIdNode; + } + + /** + * Generate rel op hqmf. + * + * @param relOpNode the rel op node + * @param dataCriteriaSectionElem the data criteria section elem + * @param clauseName the clause name + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + private Node generateRelOpHQMF(Node relOpNode, Node dataCriteriaSectionElem, String clauseName) + throws XPathExpressionException { + Node finalNode = null; + if (relOpNode.getChildNodes().getLength() == 2) { + Node lhsNode = relOpNode.getFirstChild(); + Node rhsNode = relOpNode.getLastChild(); + String lhsName = lhsNode.getNodeName(); + + // NamedNodeMap attribMap = relOpNode.getAttributes(); + // String relDisplayName = + // StringUtils.deleteWhitespace(attribMap.getNamedItem(DISPLAY_NAME).getNodeValue()); + // String relUUID = attribMap.getNamedItem(UUID).getNodeValue(); + // String localVarName = "localVar_"+relDisplayName+"_"+relUUID; + + String localVarName = clauseName; + Node parentNode = relOpNode.getParentNode(); + if (parentNode != null) { + if (parentNode.getNodeName().equalsIgnoreCase("subTree") + && parentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { + String isQdmVariable = + parentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + localVarName = localVarName.replace("$", ""); + localVarName = "qdm_var_" + localVarName; + } + } + } + localVarName = localVarName + "_" + UUIDUtilClient.uuid(5); + localVarName = StringUtils.deleteWhitespace(localVarName); + if (ELEMENT_REF.equals(lhsName)) { + finalNode = + getrelOpLHSQDM(relOpNode, dataCriteriaSectionElem, lhsNode, rhsNode, clauseName); + } else if (RELATIONAL_OP.equals(lhsName)) { + finalNode = + getrelOpLHSRelOp(relOpNode, dataCriteriaSectionElem, lhsNode, rhsNode, clauseName); + Node relOpParentNode = relOpNode.getParentNode(); + if (relOpParentNode.getNodeName().equalsIgnoreCase(FUNCTIONAL_OP)) { + Element excerptElement = + generateExcerptEntryForFunctionalNode( + relOpNode.getParentNode(), + lhsNode, + measureExport.getHqmfXmlProcessor(), + finalNode); + if (excerptElement != null) { + Node firstNode = finalNode.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstNode.getNodeName())) { + firstNode = firstNode.getNextSibling(); + } + // Comment comment = + // measureExport.getHQMFXmlProcessor().getOriginalDoc().createComment("entry for + // "+relOpNode.getParentNode().getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + // firstNode.appendChild(comment); + firstNode.appendChild(excerptElement); + } + } + // return finalNode; + } else if (SET_OP.equals(lhsName)) { + finalNode = + getrelOpLHSSetOp(relOpNode, dataCriteriaSectionElem, lhsNode, rhsNode, clauseName); + Node relOpParentNode = relOpNode.getParentNode(); + if (relOpParentNode.getNodeName().equalsIgnoreCase(FUNCTIONAL_OP)) { + Element excerptElement = + generateExcerptEntryForFunctionalNode( + relOpNode.getParentNode(), + lhsNode, + measureExport.getHqmfXmlProcessor(), + finalNode); + if (excerptElement != null) { + Node firstNode = finalNode.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstNode.getNodeName())) { + firstNode = firstNode.getNextSibling(); + } + // Comment comment = + // measureExport.getHQMFXmlProcessor().getOriginalDoc().createComment("entry for + // "+relOpNode.getParentNode().getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + // firstNode.appendChild(comment); + firstNode.appendChild(excerptElement); + } + } + // return finalNode; + } else if (SUB_TREE_REF.equals(lhsName) || FUNCTIONAL_OP.equalsIgnoreCase(lhsName)) { + Node functionalOpNodeWithChildQDM = checkLHSFunctionalOpWithChildQDM(lhsNode); + if (functionalOpNodeWithChildQDM != null) { + // Do something godawful here. + Node functionEntryNode = + generateFunctionalOpHQMF( + functionalOpNodeWithChildQDM, (Element) dataCriteriaSectionElem, clauseName); + dataCriteriaSectionElem.appendChild(functionEntryNode); + finalNode = + createSpecialGrouperForRelOp( + relOpNode, functionEntryNode, rhsNode, dataCriteriaSectionElem, clauseName); + } else if (FUNCTIONAL_OP.equalsIgnoreCase(lhsName)) { + finalNode = + getFunctionalOpLHS(relOpNode, dataCriteriaSectionElem, lhsNode, rhsNode, clauseName); + } else { + finalNode = + getrelOpLHSSubtree(relOpNode, dataCriteriaSectionElem, lhsNode, rhsNode, clauseName); + } + } + // else if(FUNCTIONAL_OP.equalsIgnoreCase(lhsName)) { + // finalNode = getFunctionalOpLHS(relOpNode, dataCriteriaSectionElem, lhsNode, + // rhsNode, clauseName); + // } + if (parentNode.getNodeName().equalsIgnoreCase("subTree")) { + updateLocalVar(finalNode, localVarName); + } + } else { + logger.debug( + "Relational Op:" + + relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + " does not have exactly 2 children. Skipping HQMF for it."); + } + return finalNode; + } + + /** + * When we have a case of "First:(Encounter,Performed:Inpatient) During Measurement Period"; we + * need to generate a entry with Grouper. + * + * @param relOpNode the rel op node + * @param functionEntryNode the function entry node + * @param rhsNode the rhs node + * @param dataCriteriaSectionElem the data criteria section elem + * @param clauseName the clause name + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + private Node createSpecialGrouperForRelOp( + Node relOpNode, + Node functionEntryNode, + Node rhsNode, + Node dataCriteriaSectionElem, + String clauseName) + throws XPathExpressionException { + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + + // creating Entry Tag + Element entryElem = hqmfXmlProcessor.getOriginalDoc().createElement(ENTRY); + entryElem.setAttribute(TYPE_CODE, "DRIV"); + + String localVariableName = relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + Element localVarElem = hqmfXmlProcessor.getOriginalDoc().createElement(LOCAL_VARIABLE_NAME); + localVariableName = localVariableName + "_" + UUIDUtilClient.uuid(5); + localVariableName = StringUtils.deleteWhitespace(localVariableName); + localVarElem.setAttribute(VALUE, localVariableName); + entryElem.appendChild(localVarElem); + + String root = relOpNode.getAttributes().getNamedItem(UUID).getNodeValue(); + String ext = + StringUtils.deleteWhitespace( + relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + "_" + + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); + + Node grouperElem = generateEmptyGrouper(hqmfXmlProcessor, root, ext); + entryElem.appendChild(grouperElem); + + Node subTreeParentNode = checkIfSubTree(relOpNode.getParentNode()); + Node idNode = findNode(entryElem, "ID"); + if (idNode != null && subTreeParentNode != null) { + String idExtension = idNode.getAttributes().getNamedItem(EXTENSION).getNodeValue(); + String idRoot = idNode.getAttributes().getNamedItem(ROOT).getNodeValue(); + root = subTreeParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); + ext = + StringUtils.deleteWhitespace( + relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + "_" + + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); + if (subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { + String isQdmVariable = + subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (subTreeParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = + "occ" + + subTreeParentNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + + "of_"; + } + if (occText != null) { + ext = occText + "qdm_var_" + ext; + } else { + ext = "qdm_var_" + ext; + } + } + } + idNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); + idNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); + // Updated Excerpt tag idNode root and extension. + // String hqmfXmlString = measureExport.getHQMFXmlProcessor().getOriginalXml(); + Node idNodeExcerpt = + measureExport + .getHqmfXmlProcessor() + .findNode( + measureExport.getHqmfXmlProcessor().getOriginalDoc(), + "//entry/*/excerpt/*/id[@root='" + + idRoot + + "'][@extension=\"" + + idExtension + + "\"]"); + if (idNodeExcerpt != null) { + idNodeExcerpt.getAttributes().getNamedItem(ROOT).setNodeValue(root); + idNodeExcerpt.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); + } + } + + // Element temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, + // measureExport.getHQMFXmlProcessor()); + Element temporallyRelatedInfoNode = null; + if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { + temporallyRelatedInfoNode = + createBaseTemporalNode(relOpNode, measureExport.getHqmfXmlProcessor()); + } else { + temporallyRelatedInfoNode = + measureExport.getHqmfXmlProcessor().getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); + temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); + } + handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); + Node firstChild = entryElem.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { + firstChild = firstChild.getNextSibling(); + } + NodeList outBoundList = ((Element) firstChild).getElementsByTagName(OUTBOUND_RELATIONSHIP); + if (outBoundList != null && outBoundList.getLength() > 0) { + Node outBound = outBoundList.item(0); + firstChild.insertBefore(temporallyRelatedInfoNode, outBound); + } else { + NodeList excerptList = ((Element) firstChild).getElementsByTagName(EXCERPT); + if (excerptList != null && excerptList.getLength() > 0) { + Node excerptNode = excerptList.item(0); + firstChild.insertBefore(temporallyRelatedInfoNode, excerptNode); + } else { + firstChild.appendChild(temporallyRelatedInfoNode); + } + } + + // Add a outBound Relationship for the 'functionEntryNode' passed above. + Element outBoundForFunction = + measureExport.getHqmfXmlProcessor().getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); + outBoundForFunction.setAttribute(TYPE_CODE, "COMP"); + Node idNodeForFunctionEntryNode = findNode(functionEntryNode, "ID"); + Node excerptNodeForFunctionEntryNode = findNode(functionEntryNode, "excerpt"); + Node idNodeInExcerptNode = findNode(excerptNodeForFunctionEntryNode, "id"); + String newExtension = + StringUtils.deleteWhitespace(clauseName) + + "_" + + idNodeForFunctionEntryNode.getAttributes().getNamedItem(EXTENSION).getNodeValue(); + + idNodeForFunctionEntryNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(newExtension); + idNodeInExcerptNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(newExtension); + + Node firstChildOfFunctionEntryElem = functionEntryNode.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstChildOfFunctionEntryElem.getNodeName())) { + firstChildOfFunctionEntryElem = firstChildOfFunctionEntryElem.getNextSibling(); + } + NamedNodeMap criteriaNodeAttributeMap = firstChildOfFunctionEntryElem.getAttributes(); + if (criteriaNodeAttributeMap.getNamedItem(CLASS_CODE) != null + && criteriaNodeAttributeMap.getNamedItem(MOOD_CODE) != null) { + // create criteriaRef + Element criteriaReference = + hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaReference.setAttribute( + CLASS_CODE, criteriaNodeAttributeMap.getNamedItem(CLASS_CODE).getNodeValue()); + criteriaReference.setAttribute( + MOOD_CODE, criteriaNodeAttributeMap.getNamedItem(MOOD_CODE).getNodeValue()); + + Node idNodeForFunctionEntryNode_Clone = idNodeForFunctionEntryNode.cloneNode(true); + criteriaReference.appendChild(idNodeForFunctionEntryNode_Clone); + + outBoundForFunction.appendChild(criteriaReference); + grouperElem.appendChild(outBoundForFunction); + } + dataCriteriaSectionElem.appendChild(entryElem); + return entryElem; + } + + /** + * This is to be called when you want to check If the node passed is a FunctionOp with it's child + * being an elementRef/QDM. If the node passed is a SubTree/Clause node then this will + * "recursively" look into the child of that SubTree/Clause node to see if that child is a + * FunctionOp with child being an elementRef/QDM. + * + * @param node the node + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + private Node checkLHSFunctionalOpWithChildQDM(Node node) throws XPathExpressionException { + Node returnFunctionalNode = null; + + String nodeName = node.getNodeName(); + if (FUNCTIONAL_OP.equalsIgnoreCase(nodeName)) { + returnFunctionalNode = node; + /* + * Node childNode = node.getFirstChild(); if(childNode != null && + * ELEMENT_REF.equals(childNode.getNodeName())){ returnFunctionalNode = node; } + */ + } else if (SUB_TREE_REF.equals(nodeName)) { + String subTreeUUID = node.getAttributes().getNamedItem(ID).getNodeValue(); + + String xpath = "/measure/subTreeLookUp/subTree[@uuid='" + subTreeUUID + "']"; + Node subTreeNode = + measureExport + .getSimpleXmlProcessor() + .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); + + Node childNode = subTreeNode.getFirstChild(); + if (childNode != null) { + returnFunctionalNode = checkLHSFunctionalOpWithChildQDM(childNode); + } + } + return returnFunctionalNode; + } + + /** + * Gets the functional op lhs. + * + * @param relOpNode the rel op node + * @param dataCriteriaSectionElem the data criteria section elem + * @param lhsNode the lhs node + * @param rhsNode the rhs node + * @param clauseName the clause name + * @return the functional op lhs + * @throws XPathExpressionException the x path expression exception + */ + private Node getFunctionalOpLHS( + Node relOpNode, Node dataCriteriaSectionElem, Node lhsNode, Node rhsNode, String clauseName) + throws XPathExpressionException { + Node entryNode = + generateFunctionalOpHQMF(lhsNode, (Element) dataCriteriaSectionElem, clauseName); + + // Comment comment = + // measureExport.getHQMFXmlProcessor().getOriginalDoc().createComment("entry for + // "+relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + // dataCriteriaSectionElem.appendChild(comment); + if (entryNode != null) { + Node subTreeParentNode = checkIfSubTree(relOpNode.getParentNode()); + Node idNode = findNode(entryNode, "ID"); + if (idNode != null && subTreeParentNode != null) { + String idExtension = idNode.getAttributes().getNamedItem(EXTENSION).getNodeValue(); + String idRoot = idNode.getAttributes().getNamedItem(ROOT).getNodeValue(); + String root = subTreeParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); + String ext = + StringUtils.deleteWhitespace( + relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + "_" + + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); + if (subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { + String isQdmVariable = + subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (subTreeParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = + "occ" + + subTreeParentNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + + "of_"; + } + if (occText != null) { + ext = occText + "qdm_var_" + ext; + } else { + ext = "qdm_var_" + ext; + } + } + } + idNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); + idNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); + // Updated Excerpt tag idNode root and extension. + // String hqmfXmlString = measureExport.getHQMFXmlProcessor().getOriginalXml(); + Node idNodeExcerpt = + measureExport + .getHqmfXmlProcessor() + .findNode( + measureExport.getHqmfXmlProcessor().getOriginalDoc(), + "//entry/*/excerpt/*/id[@root='" + + idRoot + + "'][@extension=\"" + + idExtension + + "\"]"); + if (idNodeExcerpt != null) { + idNodeExcerpt.getAttributes().getNamedItem(ROOT).setNodeValue(root); + idNodeExcerpt.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); + } + } + + // Element temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, + // measureExport.getHQMFXmlProcessor()); + Element temporallyRelatedInfoNode = null; + if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { + temporallyRelatedInfoNode = + createBaseTemporalNode(relOpNode, measureExport.getHqmfXmlProcessor()); + } else { + temporallyRelatedInfoNode = + measureExport + .getHqmfXmlProcessor() + .getOriginalDoc() + .createElement(OUTBOUND_RELATIONSHIP); + temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); + } + handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); + Node firstChild = entryNode.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { + firstChild = firstChild.getNextSibling(); + } + NodeList outBoundList = ((Element) firstChild).getElementsByTagName(OUTBOUND_RELATIONSHIP); + if (outBoundList != null && outBoundList.getLength() > 0) { + Node outBound = outBoundList.item(0); + firstChild.insertBefore(temporallyRelatedInfoNode, outBound); + } else { + NodeList excerptList = ((Element) firstChild).getElementsByTagName(EXCERPT); + if (excerptList != null && excerptList.getLength() > 0) { + Node excerptNode = excerptList.item(0); + firstChild.insertBefore(temporallyRelatedInfoNode, excerptNode); + } else { + firstChild.appendChild(temporallyRelatedInfoNode); + } + } + dataCriteriaSectionElem.appendChild(entryNode); + } + /* + * else{ Comment commnt = measureExport.getHQMFXmlProcessor().getOriginalDoc(). + * createComment("CHECK:Could not find an entry for functionalOp:"+lhsNode. + * getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + * dataCriteriaSectionElem.appendChild(commnt); } + */ + return entryNode; + } + + /** + * Find node. + * + * @param criteriaNodeInEntry the criteria node in entry + * @param nodeName the node name + * @return idNode + */ + private Node findNode(Node criteriaNodeInEntry, String nodeName) { + Node idNode = null; + for (int i = 0; i < criteriaNodeInEntry.getChildNodes().getLength(); i++) { + Node childNode = criteriaNodeInEntry.getChildNodes().item(i); + String childNodeName = childNode.getNodeName(); + if (childNodeName.contains("Criteria")) { + NodeList criteriaChildNodes = childNode.getChildNodes(); + for (int j = 0; j < criteriaChildNodes.getLength(); j++) { + Node criteriaChildNode = criteriaChildNodes.item(j); + if (nodeName.equalsIgnoreCase(criteriaChildNode.getNodeName())) { + idNode = criteriaChildNode; + break; + } + } + break; + } + } + return idNode; + } + + /** + * Gets the rel op lhs subtree. + * + * @param relOpNode the rel op node + * @param dataCriteriaSectionElem the data criteria section elem + * @param lhsNode the lhs node + * @param rhsNode the rhs node + * @param clauseName the clause name + * @return the rel op lhs subtree + */ + private Node getrelOpLHSSubtree( + Node relOpNode, Node dataCriteriaSectionElem, Node lhsNode, Node rhsNode, String clauseName) { + + try { + String subTreeUUID = lhsNode.getAttributes().getNamedItem(ID).getNodeValue(); + String root = subTreeUUID; + + Node relOpParentNode = relOpNode.getParentNode(); + + String xpath = "/measure/subTreeLookUp/subTree[@uuid='" + subTreeUUID + "']"; + Node subTreeNode = + measureExport + .getSimpleXmlProcessor() + .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); + if (subTreeNode != null) { + /** + * Check if the Clause has already been generated. If it is not generated yet, then generate + * it by calling the 'generateSubTreeXML' method. + */ + if (!subTreeNodeMap.containsKey(subTreeUUID)) { + generateSubTreeXML(subTreeNode, false); + } + String isQdmVariable = + subTreeNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + Node firstChild = subTreeNode.getFirstChild(); + String firstChildName = firstChild.getNodeName(); + + String ext = + StringUtils.deleteWhitespace( + firstChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + if (FUNCTIONAL_OP.equals(firstChildName) + || RELATIONAL_OP.equals(firstChildName) + || SET_OP.equals(firstChildName)) { + ext += "_" + firstChild.getAttributes().getNamedItem(UUID).getNodeValue(); + } + + if (ELEMENT_REF.equals(firstChildName)) { + ext = getElementRefExt(firstChild, measureExport.getSimpleXmlProcessor()); + } else if (FUNCTIONAL_OP.equals(firstChildName)) { + if (firstChild.getFirstChild() != null) { + Node functionChild = firstChild.getFirstChild(); + if (functionChild != null) { + if (functionChild.getNodeName().equalsIgnoreCase(SUB_TREE_REF)) { + ext = functionChild.getAttributes().getNamedItem(ID).getNodeValue(); + } else if (functionChild.getNodeName().equalsIgnoreCase(ELEMENT_REF)) { + ext = getElementRefExt(functionChild, measureExport.getSimpleXmlProcessor()); + } else { + ext = + StringUtils.deleteWhitespace( + functionChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + "_" + + functionChild.getAttributes().getNamedItem(UUID).getNodeValue()) + .replaceAll(":", "_"); + } + } + } + } + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (subTreeNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = + "occ" + subTreeNode.getAttributes().getNamedItem("instance").getNodeValue() + "of_"; + } + if (occText != null) { + ext = occText + "qdm_var_" + ext; + } else { + ext = "qdm_var_" + ext; + } + } + + Node idNodeQDM = + measureExport + .getHqmfXmlProcessor() + .findNode( + measureExport.getHqmfXmlProcessor().getOriginalDoc(), + "//entry/*/id[@root='" + root + "'][@extension=\"" + ext + "\"]"); + if (idNodeQDM != null) { + String newExt = + StringUtils.deleteWhitespace( + relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + "_" + + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); + if (relOpParentNode != null && SUB_TREE.equals(relOpParentNode.getNodeName())) { + root = relOpParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); + Node qdmVarNode = relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE); + if (qdmVarNode != null) { + String isQdmVar = + relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVar)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (relOpParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = + "occ" + + relOpParentNode.getAttributes().getNamedItem("instance").getNodeValue() + + "of_"; + } + if (occText != null) { + newExt = occText + "qdm_var_" + newExt; + } else { + newExt = "qdm_var_" + newExt; + } + } + } + } else { + Node tempParentNode = checkIfParentSubTree(relOpParentNode); + if (tempParentNode != null) { + root = tempParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); + } + } + + Node parent = idNodeQDM.getParentNode(); + Node isOcc = subTreeNode.getAttributes().getNamedItem(INSTANCE_OF); + Node newEntryNode = null; + + if (TRUE.equals(isQdmVariable) && isOcc == null) { + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + // creating Entry Tag + Element entryElem = hqmfXmlProcessor.getOriginalDoc().createElement(ENTRY); + entryElem.setAttribute(TYPE_CODE, "DRIV"); + // create empty grouperCriteria + Node grouperElem = generateEmptyGrouper(hqmfXmlProcessor, root, newExt); + + // generate outboundRelationship + Element outboundRelElem = generateEmptyOutboundElem(hqmfXmlProcessor); + + NamedNodeMap attribMap = parent.getAttributes(); + String classCode = attribMap.getNamedItem(CLASS_CODE).getNodeValue(); + String moodCode = attribMap.getNamedItem(MOOD_CODE).getNodeValue(); + + // create criteriaRef + Element criteriaReference = + hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaReference.setAttribute(CLASS_CODE, classCode); + criteriaReference.setAttribute(MOOD_CODE, moodCode); + + Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + id.setAttribute(ROOT, subTreeUUID); + id.setAttribute(EXTENSION, ext); + + criteriaReference.appendChild(id); + outboundRelElem.appendChild(criteriaReference); + + Element localVarElem = + hqmfXmlProcessor.getOriginalDoc().createElement(LOCAL_VARIABLE_NAME); + localVarElem.setAttribute(VALUE, ext); + entryElem.appendChild(localVarElem); + + grouperElem.appendChild(outboundRelElem); + entryElem.appendChild(grouperElem); + + newEntryNode = entryElem; + } else { + Node entryNodeForSubTree = idNodeQDM.getParentNode().getParentNode(); + newEntryNode = entryNodeForSubTree.cloneNode(true); + + NodeList idChildNodeList = ((Element) newEntryNode).getElementsByTagName(ID); + if (idChildNodeList != null && idChildNodeList.getLength() > 0) { + Node idChildNode = idChildNodeList.item(0); + idChildNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(newExt); + idChildNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); + } + } + + // Element temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, + // measureExport.getHQMFXmlProcessor()); + Element temporallyRelatedInfoNode = null; + if (!FULFILLS.equalsIgnoreCase( + relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { + temporallyRelatedInfoNode = + createBaseTemporalNode(relOpNode, measureExport.getHqmfXmlProcessor()); + } else { + temporallyRelatedInfoNode = + measureExport + .getHqmfXmlProcessor() + .getOriginalDoc() + .createElement(OUTBOUND_RELATIONSHIP); + temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); + } + + handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); + + Node firstNode = newEntryNode.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstNode.getNodeName())) { + firstNode = firstNode.getNextSibling(); + } + NodeList outBoundList = ((Element) firstNode).getElementsByTagName(OUTBOUND_RELATIONSHIP); + if (outBoundList != null && outBoundList.getLength() > 0) { + Node outBound = outBoundList.item(0); + firstNode.insertBefore(temporallyRelatedInfoNode, outBound); + } else { + firstNode.appendChild(temporallyRelatedInfoNode); + } + // Entry for Functional Op. + if (FUNCTIONAL_OP.equals(relOpParentNode.getNodeName())) { + Element excerptElement = + generateExcerptEntryForFunctionalNode( + relOpParentNode, + lhsNode, + measureExport.getHqmfXmlProcessor(), + firstNode.getParentNode()); + if (excerptElement != null) { + // Comment comment = + // measureExport.getHQMFXmlProcessor().getOriginalDoc().createComment("entry for + // "+relOpParentNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + // firstNode.appendChild(comment); + firstNode.appendChild(excerptElement); + } + } + // create comment node + // Comment comment = + // measureExport.getHQMFXmlProcessor().getOriginalDoc().createComment("entry for + // "+relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + // dataCriteriaSectionElem.appendChild(comment); + dataCriteriaSectionElem.appendChild(newEntryNode); + return newEntryNode; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * Gets the rel op lhs set op. + * + * @param relOpNode the rel op node + * @param dataCriteriaSectionElem the data criteria section elem + * @param lhsNode the lhs node + * @param rhsNode the rhs node + * @param clauseName the clause name + * @return the rel op lhs set op + */ + private Node getrelOpLHSSetOp( + Node relOpNode, Node dataCriteriaSectionElem, Node lhsNode, Node rhsNode, String clauseName) { + + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + // Node relOpParentNode = relOpNode.getParentNode(); + + try { + Node setOpEntryNode = generateSetOpHQMF(lhsNode, dataCriteriaSectionElem, clauseName); + // Element temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, + // hqmfXmlProcessor); + Node relOpParentNode = checkIfSubTree(relOpNode.getParentNode()); + if (relOpParentNode != null) { + NodeList idChildNodeList = ((Element) setOpEntryNode).getElementsByTagName(ID); + if (idChildNodeList != null && idChildNodeList.getLength() > 0) { + Node idChildNode = idChildNodeList.item(0); + String root = relOpParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); + String ext = + StringUtils.deleteWhitespace( + relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + "_" + + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); + if (relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { + String isQdmVariable = + relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (relOpParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = + "occ" + + relOpParentNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + + "of_"; + } + if (occText != null) { + ext = occText + "qdm_var_" + ext; + } else { + ext = "qdm_var_" + ext; + } + } + } + idChildNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); + idChildNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); + } + } + Element temporallyRelatedInfoNode = null; + if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { + temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, hqmfXmlProcessor); + } else { + temporallyRelatedInfoNode = + hqmfXmlProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); + temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); + } + handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); + + Node firstChild = setOpEntryNode.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { + firstChild = firstChild.getNextSibling(); + } + NodeList outBoundList = ((Element) firstChild).getElementsByTagName(OUTBOUND_RELATIONSHIP); + if (outBoundList != null && outBoundList.getLength() > 0) { + Node outBound = outBoundList.item(0); + firstChild.insertBefore(temporallyRelatedInfoNode, outBound); + } else { + firstChild.appendChild(temporallyRelatedInfoNode); + } + + // create comment node + // Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("entry for + // "+relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + // dataCriteriaSectionElem.appendChild(comment); + dataCriteriaSectionElem.appendChild(setOpEntryNode); + return setOpEntryNode; + + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + /** + * Gets the rel op lhs rel op. + * + * @param relOpNode the rel op node + * @param dataCriteriaSectionElem the data criteria section elem + * @param lhsNode the lhs node + * @param rhsNode the rhs node + * @param clauseName the clause name + * @return the rel op lhs rel op + * @throws XPathExpressionException the x path expression exception + */ + private Node getrelOpLHSRelOp( + Node relOpNode, Node dataCriteriaSectionElem, Node lhsNode, Node rhsNode, String clauseName) + throws XPathExpressionException { + + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + // Node relOpParentNode = relOpNode.getParentNode(); + + try { + Node relOpEntryNode = generateRelOpHQMF(lhsNode, dataCriteriaSectionElem, clauseName); + /* + * Element temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, + * hqmfXmlProcessor); + */ + + Node relOpParentNode = checkIfSubTree(relOpNode.getParentNode()); + + if (relOpParentNode != null) { + NodeList idChildNodeList = ((Element) relOpEntryNode).getElementsByTagName(ID); + + if (idChildNodeList != null && idChildNodeList.getLength() > 0) { + Node idChildNode = idChildNodeList.item(0); + String root = relOpParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); + String ext = + StringUtils.deleteWhitespace( + relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + "_" + + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); + if (relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { + String isQdmVariable = + relOpParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (relOpParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = + "occ" + + relOpParentNode.getAttributes().getNamedItem("instance").getNodeValue() + + "of_"; + } + if (occText != null) { + ext = occText + "qdm_var_" + ext; + } else { + ext = "qdm_var_" + ext; + } + } + } + idChildNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); + idChildNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); + } + } + Element temporallyRelatedInfoNode = null; + if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { + temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, hqmfXmlProcessor); + } else { + temporallyRelatedInfoNode = + hqmfXmlProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); + temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); + } + + handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); + + Node firstChild = relOpEntryNode.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { + firstChild = firstChild.getNextSibling(); + } + NodeList outBoundList = ((Element) firstChild).getElementsByTagName(OUTBOUND_RELATIONSHIP); + if (outBoundList != null && outBoundList.getLength() > 0) { + Node outBound = outBoundList.item(0); + firstChild.insertBefore(temporallyRelatedInfoNode, outBound); + } else { + firstChild.appendChild(temporallyRelatedInfoNode); + } + // create comment node + // Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("entry for + // "+relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + // dataCriteriaSectionElem.appendChild(comment); + dataCriteriaSectionElem.appendChild(relOpEntryNode); + return relOpEntryNode; + + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + /** + * Gets the rel op lhsqdm. + * + * @param relOpNode the rel op node + * @param dataCriteriaSectionElem the data criteria section elem + * @param lhsNode the lhs node + * @param rhsNode the rhs node + * @param clauseName the clause name + * @return the rel op lhsqdm + * @throws XPathExpressionException the x path expression exception + */ + private Node getrelOpLHSQDM( + Node relOpNode, Node dataCriteriaSectionElem, Node lhsNode, Node rhsNode, String clauseName) + throws XPathExpressionException { + + String ext = getElementRefExt(lhsNode, measureExport.getSimpleXmlProcessor()); + String root = lhsNode.getAttributes().getNamedItem(ID).getNodeValue(); + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + Node relOpParentNode = relOpNode.getParentNode(); + Element excerptElement = null; + Node idNodeQDM = + hqmfXmlProcessor.findNode( + hqmfXmlProcessor.getOriginalDoc(), + "//entry/*/id[@root='" + root + "'][@extension=\"" + ext + "\"]"); + + if (relOpParentNode != null && idNodeQDM != null) { + ext = + StringUtils.deleteWhitespace( + relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() + + "_" + + relOpNode.getAttributes().getNamedItem(UUID).getNodeValue()); + Node subTreeParentNode = checkIfSubTree(relOpParentNode); + if (subTreeParentNode != null) { + root = subTreeParentNode.getAttributes().getNamedItem(UUID).getNodeValue(); + if (subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE) != null) { + String isQdmVariable = + subTreeParentNode.getAttributes().getNamedItem(QDM_VARIABLE).getNodeValue(); + if (TRUE.equalsIgnoreCase(isQdmVariable)) { + String occText = null; + // Handled Occurrence Of QDM Variable. + if (relOpParentNode.getAttributes().getNamedItem(INSTANCE_OF) != null) { + occText = + "occ" + + relOpParentNode.getAttributes().getNamedItem("instance").getNodeValue() + + "of_"; + } + if (occText != null) { + ext = occText + "qdm_var_" + ext; + } else { + ext = "qdm_var_" + ext; + } + } + } + } + + Node entryNodeForElementRef = idNodeQDM.getParentNode().getParentNode(); + Node clonedEntryNodeForElementRef = entryNodeForElementRef.cloneNode(true); + /* + * Element localVarName = (Element) + * ((Element)clonedEntryNodeForElementRef).getElementsByTagName( + * "localVariableName").item(0); + * localVarName.setAttribute(VALUE,findSubTreeDisplayName(lhsNode)); + */ + NodeList idChildNodeList = ((Element) clonedEntryNodeForElementRef).getElementsByTagName(ID); + updateLocalVar(clonedEntryNodeForElementRef, ext); + if (idChildNodeList != null && idChildNodeList.getLength() > 0) { + Node idChildNode = idChildNodeList.item(0); + idChildNode.getAttributes().getNamedItem(EXTENSION).setNodeValue(ext); + idChildNode.getAttributes().getNamedItem(ROOT).setNodeValue(root); + } + + // Added logic to show qdm_variable in extension if clause is of qdm variable + // type. + if (FUNCTIONAL_OP.equals(relOpParentNode.getNodeName())) { + excerptElement = + generateExcerptEntryForFunctionalNode( + relOpParentNode, lhsNode, hqmfXmlProcessor, clonedEntryNodeForElementRef); + } + Element temporallyRelatedInfoNode = null; + if (!FULFILLS.equalsIgnoreCase(relOpNode.getAttributes().getNamedItem(TYPE).getNodeValue())) { + temporallyRelatedInfoNode = createBaseTemporalNode(relOpNode, hqmfXmlProcessor); + generateTemporalAttribute( + hqmfXmlProcessor, + lhsNode, + temporallyRelatedInfoNode, + clonedEntryNodeForElementRef, + true); + } else { + temporallyRelatedInfoNode = + hqmfXmlProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); + temporallyRelatedInfoNode.setAttribute(TYPE_CODE, "FLFS"); + } + handleRelOpRHS(rhsNode, temporallyRelatedInfoNode, clauseName); + Node firstChild = clonedEntryNodeForElementRef.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { + firstChild = firstChild.getNextSibling(); + } + NodeList outBoundList = ((Element) firstChild).getElementsByTagName(OUTBOUND_RELATIONSHIP); + if (outBoundList != null && outBoundList.getLength() > 0) { + Node outBound = outBoundList.item(0); + firstChild.insertBefore(temporallyRelatedInfoNode, outBound); + } else { + firstChild.appendChild(temporallyRelatedInfoNode); + } + + if (excerptElement != null) { + // Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("excerpt + // for + // "+relOpParentNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + // firstChild.appendChild(comment); + firstChild.appendChild(excerptElement); + } + // create comment node + // Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("entry for + // "+relOpNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + // dataCriteriaSectionElem.appendChild(comment); + dataCriteriaSectionElem.appendChild(clonedEntryNodeForElementRef); + return clonedEntryNodeForElementRef; + } + return null; + } + + /** + * Handle rel op rhs. + * + * @param rhsNode the rhs node + * @param temporallyRelatedInfoNode the temporally related info node + * @param clauseName the clause name + * @throws XPathExpressionException the x path expression exception + */ + private void handleRelOpRHS(Node rhsNode, Element temporallyRelatedInfoNode, String clauseName) + throws XPathExpressionException { + + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + String rhsName = rhsNode.getNodeName(); + Node dataCritSectionNode = + hqmfXmlProcessor.findNode( + temporallyRelatedInfoNode.getOwnerDocument(), "//dataCriteriaSection"); + + if (ELEMENT_REF.equals(rhsName)) { + Node entryNode = + generateCritRefElementRef( + temporallyRelatedInfoNode, rhsNode, measureExport.getHqmfXmlProcessor()); + generateTemporalAttribute( + hqmfXmlProcessor, rhsNode, temporallyRelatedInfoNode, entryNode, false); + } else if (SUB_TREE_REF.equals(rhsName)) { + generateCritRefForNode(temporallyRelatedInfoNode, rhsNode); + } else { + switch (rhsName) { + case SET_OP: + generateCritRefSetOp( + dataCritSectionNode, + hqmfXmlProcessor, + rhsNode, + temporallyRelatedInfoNode, + clauseName); + break; + case RELATIONAL_OP: + generateRelOpHQMF(rhsNode, temporallyRelatedInfoNode, clauseName); + Node lastChild = temporallyRelatedInfoNode.getLastChild(); + if (lastChild.getNodeName().equals(ENTRY)) { + temporallyRelatedInfoNode.removeChild(lastChild); + + Node fChild = lastChild.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(fChild.getNodeName())) { + fChild = fChild.getNextSibling(); + } + + Node criteriaNode = fChild; + // temporallyRelatedInfoNode.appendChild(criteriaNode); + dataCritSectionNode.appendChild(lastChild); + // create criteriaRef + Element criteriaReference = + hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaReference.setAttribute( + CLASS_CODE, criteriaNode.getAttributes().getNamedItem(CLASS_CODE).getNodeValue()); + criteriaReference.setAttribute( + MOOD_CODE, criteriaNode.getAttributes().getNamedItem(MOOD_CODE).getNodeValue()); + + NodeList childNodeList = criteriaNode.getChildNodes(); + for (int i = 0; i < childNodeList.getLength(); i++) { + Node childNode = childNodeList.item(i); + if (childNode.getNodeName().equalsIgnoreCase(ID)) { + Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + id.setAttribute(ROOT, childNode.getAttributes().getNamedItem(ROOT).getNodeValue()); + id.setAttribute( + EXTENSION, childNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); + criteriaReference.appendChild(id); + temporallyRelatedInfoNode.appendChild(criteriaReference); + break; + } + } + + NodeList childTemporalNodeList = + ((Element) criteriaNode).getElementsByTagName("temporallyRelatedInformation"); + if (childTemporalNodeList != null && childTemporalNodeList.getLength() > 0) { + Node childTemporalNode = childTemporalNodeList.item(0); + Node temporalInfoNode = childTemporalNode.getFirstChild(); + // find sourceAttribute + NodeList childs = temporalInfoNode.getChildNodes(); + for (int c = 0; c < childs.getLength(); c++) { + Node child = childs.item(c); + String childName = child.getNodeName(); + if ("qdm:sourceAttribute".equals(childName)) { + Node cloneAttNode = child.cloneNode(true); + temporallyRelatedInfoNode.getFirstChild().appendChild(cloneAttNode); + hqmfXmlProcessor + .getOriginalDoc() + .renameNode(cloneAttNode, "", "qdm:targetAttribute"); + break; + } + } + } + } + break; + case FUNCTIONAL_OP: + Node entryNode = + generateFunctionalOpHQMF(rhsNode, (Element) dataCritSectionNode, clauseName); + if (entryNode != null && entryNode.getNodeName().equals(ENTRY)) { + Node fChild = entryNode.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(fChild.getNodeName())) { + fChild = fChild.getNextSibling(); + } + // create criteriaRef + Element criteriaReference = + hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaReference.setAttribute( + CLASS_CODE, fChild.getAttributes().getNamedItem(CLASS_CODE).getNodeValue()); + criteriaReference.setAttribute( + MOOD_CODE, fChild.getAttributes().getNamedItem(MOOD_CODE).getNodeValue()); + NodeList childNodeList = fChild.getChildNodes(); + for (int i = 0; i < childNodeList.getLength(); i++) { + Node childNode = childNodeList.item(i); + if (childNode.getNodeName().equalsIgnoreCase(ID)) { + Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + id.setAttribute(ROOT, childNode.getAttributes().getNamedItem(ROOT).getNodeValue()); + id.setAttribute( + EXTENSION, childNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); + criteriaReference.appendChild(id); + temporallyRelatedInfoNode.appendChild(criteriaReference); + break; + } + } + } + break; + default: + // Dont do anything + break; + } + } + } + + /** + * Generate temporal attribute. + * + * @param hqmfXmlProcessor the hqmf xml processor + * @param rhsNode the rhs node + * @param temporallyRelatedInfoNode the temporally related info node + * @param entryNode the entry node + * @param isSource the is source + * @return the node + */ + private Node generateTemporalAttribute( + XmlProcessor hqmfXmlProcessor, + Node rhsNode, + Element temporallyRelatedInfoNode, + Node entryNode, + boolean isSource) { + if (entryNode != null) { + Element entryElement = (Element) entryNode; + + if (!rhsNode.hasChildNodes()) { + return null; + } else { + Node child = rhsNode.getFirstChild(); + if (!"attribute".equals(child.getNodeName())) { + return null; + } + + String value = child.getAttributes().getNamedItem(NAME).getNodeValue(); + List validAttribNames = new ArrayList<>(); + validAttribNames.add("incision datetime"); + validAttribNames.add("facility location arrival datetime"); + validAttribNames.add("facility location departure datetime"); + validAttribNames.add("recorded datetime"); + validAttribNames.add("signed datetime"); + validAttribNames.add("start datetime"); + validAttribNames.add("stop datetime"); + if (!validAttribNames.contains(value)) { + return null; + } + if ("start datetime".equals(value) || "stop datetime".equals(value)) { + String dataType = rhsNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + if (!dataType.endsWith("Order")) { + return null; + } + } + + // create sourceAttribute/targetAttribute + String attribName = "qdm:sourceAttribute"; + if (!isSource) { + attribName = "qdm:targetAttribute"; + } + Element attribute = hqmfXmlProcessor.getOriginalDoc().createElement(attribName); + attribute.setAttribute(NAME, value); + String boundValue = "effectiveTime.low"; + + if ("incision datetime".equals(value)) { + NodeList nodeList = entryElement.getElementsByTagName(OUTBOUND_RELATIONSHIP); + if (nodeList != null && nodeList.getLength() > 0) { + // Always get the last outBoundRelationShip tag, because this is the one + // which will represent the + Node outBoundNode = nodeList.item(nodeList.getLength() - 1); + Node criteriaNode = outBoundNode.getFirstChild(); + + NodeList idNodeList = ((Element) criteriaNode).getElementsByTagName(ID); + if (idNodeList != null && idNodeList.getLength() > 0) { + Node idNode = idNodeList.item(0); + Element qdmId = hqmfXmlProcessor.getOriginalDoc().createElement("qdm:id"); + qdmId.setAttribute(ROOT, idNode.getAttributes().getNamedItem(ROOT).getNodeValue()); + qdmId.setAttribute( + EXTENSION, idNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); + attribute.appendChild(qdmId); + } + } + } else { + NodeList nodeList = entryElement.getElementsByTagName(PARTICIPATION); + if (nodeList != null && nodeList.getLength() > 0) { + // Always get the last outBoundRelationShip tag, because this is the one + // which will represent the + Node participationNode = nodeList.item(nodeList.getLength() - 1); + Node roleNode = ((Element) participationNode).getElementsByTagName(ROLE).item(0); + NodeList idNodeList = ((Element) roleNode).getElementsByTagName(ID); + if (idNodeList != null && idNodeList.getLength() > 0) { + Node idNode = idNodeList.item(0); + Node itemNode = idNode.getFirstChild(); + Element qdmId = hqmfXmlProcessor.getOriginalDoc().createElement("qdm:id"); + qdmId.setAttribute(ROOT, itemNode.getAttributes().getNamedItem(ROOT).getNodeValue()); + qdmId.setAttribute( + EXTENSION, itemNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); + attribute.appendChild(qdmId); + + if ("facility location departure datetime".equals(value) + || "stop datetime".equals(value) + || "signed datetime".equals(value) + || "recorded datetime".equals(value)) { + boundValue = "effectiveTime.high"; + } + } + } + } + attribute.setAttribute("bound", boundValue); + Node temporalInformation = temporallyRelatedInfoNode.getFirstChild(); + if (temporallyRelatedInfoNode.getElementsByTagName("qdm:delta").item(0) != null) { + Node qdmDeltaNode = temporallyRelatedInfoNode.getElementsByTagName("qdm:delta").item(0); + temporalInformation.insertBefore(attribute, qdmDeltaNode); + } else { + temporalInformation.appendChild(attribute); + } + + return attribute; + } + } + return null; + } + + /** + * Generate Excerpt for Functional Op used with timing/Relationship. + * + * @param functionalOpNode the functional op node + * @param lhsNode the lhs node + * @param hqmfXmlProcessor the hqmf xml processor + * @param clonedNodeToAppendExcerpt the cloned node to append excerpt + * @return the element + * @throws XPathExpressionException the x path expression exception + */ + private Element generateExcerptEntryForFunctionalNode( + Node functionalOpNode, + Node lhsNode, + XmlProcessor hqmfXmlProcessor, + Node clonedNodeToAppendExcerpt) + throws XPathExpressionException { + Element excerptElement = hqmfXmlProcessor.getOriginalDoc().createElement(EXCERPT); + String functionalOpName = functionalOpNode.getAttributes().getNamedItem(TYPE).getNodeValue(); + Element criteriaElement = null; + if (FUNCTIONAL_OPS_NON_SUBSET.containsKey(functionalOpName)) { + Element sequenceElement = hqmfXmlProcessor.getOriginalDoc().createElement(SEQUENCE_NUMBER); + sequenceElement.setAttribute( + VALUE, FUNCTIONAL_OPS_NON_SUBSET.get(functionalOpName.toUpperCase())); + excerptElement.appendChild(sequenceElement); + if (clonedNodeToAppendExcerpt != null) { + if (clonedNodeToAppendExcerpt.getNodeName().contains(GROUPER)) { + criteriaElement = + generateCriteriaElementForSetOpExcerpt(hqmfXmlProcessor, clonedNodeToAppendExcerpt); + excerptElement.appendChild(criteriaElement); + } else { + NodeList entryChildNodes = clonedNodeToAppendExcerpt.getChildNodes(); + criteriaElement = generateCriteriaElementForExcerpt(hqmfXmlProcessor, entryChildNodes); + excerptElement.appendChild(criteriaElement); + } + } + } else if (FUNCTIONAL_OPS_SUBSET.containsKey(functionalOpName)) { + NamedNodeMap attributeMap = functionalOpNode.getAttributes(); + if (clonedNodeToAppendExcerpt.getNodeName().contains(GROUPER)) { + criteriaElement = + generateCriteriaElementForSetOpExcerpt(hqmfXmlProcessor, clonedNodeToAppendExcerpt); + excerptElement.appendChild(criteriaElement); + } else { + NodeList entryChildNodes = clonedNodeToAppendExcerpt.getChildNodes(); + criteriaElement = generateCriteriaElementForExcerpt(hqmfXmlProcessor, entryChildNodes); + excerptElement.appendChild(criteriaElement); + } + if (clonedNodeToAppendExcerpt != null) { + + if ("count".equalsIgnoreCase(functionalOpName)) { + + createRepeatNumberTagForCountFuncttion(hqmfXmlProcessor, attributeMap, criteriaElement); + Element qdmSubSetElement = + hqmfXmlProcessor.getOriginalDoc().createElement("qdm:subsetCode"); + qdmSubSetElement.setAttribute( + CODE, FUNCTIONAL_OPS_SUBSET.get(functionalOpName.toUpperCase())); + Element subSetCodeElement = hqmfXmlProcessor.getOriginalDoc().createElement("subsetCode"); + subSetCodeElement.setAttribute(CODE, "SUM"); + + excerptElement.appendChild(subSetCodeElement); + excerptElement.appendChild(qdmSubSetElement); + excerptElement.appendChild(criteriaElement); + } else { + if (attributeMap.getNamedItem(OPERATOR_TYPE) != null && lhsNode != null) { + String lhsNodeType = lhsNode.getNodeName(); + if (ELEMENT_REF.equalsIgnoreCase(lhsNodeType)) { + String qdmUUID = lhsNode.getAttributes().getNamedItem(ID).getNodeValue(); + String xPath = "/measure/elementLookUp/qdm[@uuid ='" + qdmUUID + "']"; + Node node = + measureExport + .getSimpleXmlProcessor() + .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xPath); + if (node != null && lhsNode.hasChildNodes()) { + Node qdmNode = node.cloneNode(true); + Node attributeNode = lhsNode.getFirstChild().cloneNode(true); + attributeNode.setUserData( + ATTRIBUTE_NAME, + attributeNode.getAttributes().getNamedItem(NAME).getNodeValue(), + null); + attributeNode.setUserData( + ATTRIBUTE_MODE, attributeMap.getNamedItem(OPERATOR_TYPE).getNodeValue(), null); + attributeNode.setUserData( + ATTRIBUTE_UUID, + attributeNode.getAttributes().getNamedItem(ATTR_UUID).getNodeValue(), + null); + Element attributeElement = (Element) attributeNode; + + attributeElement.setAttribute( + MODE, attributeMap.getNamedItem(OPERATOR_TYPE).getNodeValue()); + if (attributeElement.getAttributes().getNamedItem(ATTR_DATE) != null) { + attributeNode.setUserData( + ATTRIBUTE_DATE, attributeMap.getNamedItem(QUANTITY).getNodeValue(), null); + } else { + attributeElement.setAttribute( + COMPARISON_VALUE, attributeMap.getNamedItem(QUANTITY).getNodeValue()); + } + if (attributeMap.getNamedItem(UNIT) != null) { + attributeElement.setAttribute( + UNIT, attributeMap.getNamedItem(UNIT).getNodeValue()); + } else { + if (attributeElement.getAttributes().getNamedItem(UNIT) != null) { + attributeElement.removeAttribute(UNIT); + } + } + attributeNode = attributeElement; + + // HQMFDataCriteriaElementGenerator hqmfDataCriteriaElementGenerator = new + // HQMFDataCriteriaElementGenerator(); + // hqmfDataCriteriaElementGenerator.generateAttributeTagForFunctionalOp(measureExport,qdmNode, + // criteriaElement, attributeNode); + HQMFAttributeGenerator attributeGenerator = new HQMFAttributeGenerator(); + attributeGenerator.generateAttributeTagForFunctionalOp( + measureExport, qdmNode, criteriaElement, attributeNode); + } + } + } + Element qdmSubSetElement = + hqmfXmlProcessor.getOriginalDoc().createElement("qdm:subsetCode"); + qdmSubSetElement.setAttribute( + CODE, FUNCTIONAL_OPS_SUBSET.get(functionalOpName.toUpperCase())); + + if ("sum".equalsIgnoreCase(functionalOpName)) { + Element subSetCodeElement = + hqmfXmlProcessor.getOriginalDoc().createElement("subsetCode"); + subSetCodeElement.setAttribute(CODE, "SUM"); + excerptElement.appendChild(subSetCodeElement); + } + excerptElement.appendChild(qdmSubSetElement); + excerptElement.appendChild(criteriaElement); + } + } + } + + return excerptElement; + } + + /** + * Check if parent sub tree. + * + * @param parentNode the parent node + * @return the node + */ + protected Node checkIfParentSubTree(Node parentNode) { + Node returnNode = null; + if (parentNode != null) { + String parentName = parentNode.getNodeName(); + if (SUB_TREE.equals(parentName)) { + returnNode = parentNode; + } else { + returnNode = checkIfParentSubTree(parentNode.getParentNode()); + } + } + + return returnNode; + } + + /** + * Generates RepeatNumber tags for Count Function. + * + * @param hqmfXmlProcessor - XmlProcessor. + * @param attributeMap - NamedNodeMap. + * @param criteriaElement - Element. + */ + private void createRepeatNumberTagForCountFuncttion( + XmlProcessor hqmfXmlProcessor, NamedNodeMap attributeMap, Element criteriaElement) { + Element repeatNumberElement = hqmfXmlProcessor.getOriginalDoc().createElement("repeatNumber"); + Element lowNode = hqmfXmlProcessor.getOriginalDoc().createElement("low"); + Element highNode = hqmfXmlProcessor.getOriginalDoc().createElement("high"); + if (attributeMap.getNamedItem(OPERATOR_TYPE) != null) { + String operatorType = attributeMap.getNamedItem(OPERATOR_TYPE).getNodeValue(); + String quantity = attributeMap.getNamedItem(QUANTITY).getNodeValue(); + if (operatorType.startsWith("Greater Than")) { + lowNode.setAttribute(VALUE, quantity); + highNode.setAttribute(NULL_FLAVOR, "PINF"); + if ("Greater Than or Equal To".equals(operatorType)) { + repeatNumberElement.setAttribute("lowClosed", TRUE); + } + } else if ("Equal To".equals(operatorType)) { + repeatNumberElement.setAttribute("lowClosed", TRUE); + repeatNumberElement.setAttribute("highClosed", TRUE); + lowNode.setAttribute(VALUE, quantity); + highNode.setAttribute(VALUE, quantity); + } else if (operatorType.startsWith("Less Than")) { + repeatNumberElement.setAttribute("lowClosed", TRUE); + lowNode.setAttribute(VALUE, "0"); + highNode.setAttribute(VALUE, quantity); + if ("Less Than or Equal To".equals(operatorType)) { + repeatNumberElement.setAttribute("highClosed", TRUE); + } + } + repeatNumberElement.appendChild(lowNode); + repeatNumberElement.appendChild(highNode); + criteriaElement.appendChild(repeatNumberElement); + } + } + + /** + * Generate criteria element for excerpt. + * + * @param hqmfXmlProcessor the hqmf xml processor + * @param entryChildNodes the entry child nodes + * @return the element + */ + private Element generateCriteriaElementForExcerpt( + XmlProcessor hqmfXmlProcessor, NodeList entryChildNodes) { + Element criteriaElement = null; + for (int i = 0; i < entryChildNodes.getLength(); i++) { + Node childNode = entryChildNodes.item(i); + String childNodeName = childNode.getNodeName(); + if (childNodeName.contains("Criteria")) { + criteriaElement = hqmfXmlProcessor.getOriginalDoc().createElement(childNodeName); + criteriaElement.setAttribute( + CLASS_CODE, childNode.getAttributes().getNamedItem(CLASS_CODE).getNodeValue()); + criteriaElement.setAttribute( + MOOD_CODE, childNode.getAttributes().getNamedItem(MOOD_CODE).getNodeValue()); + NodeList criteriaChildNodes = childNode.getChildNodes(); + for (int j = 0; j < criteriaChildNodes.getLength(); j++) { + Node criteriaChildNode = criteriaChildNodes.item(j); + if (ID.equalsIgnoreCase(criteriaChildNode.getNodeName())) { + Element idElement = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + idElement.setAttribute( + ROOT, criteriaChildNode.getAttributes().getNamedItem(ROOT).getNodeValue()); + idElement.setAttribute( + EXTENSION, + criteriaChildNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); + criteriaElement.appendChild(idElement); + break; + } + } + + break; + } + } + return criteriaElement; + } + + /** + * Generate criteria element for set op excerpt. + * + * @param hqmfXmlProcessor the hqmf xml processor + * @param clonedNodeToAppendExcerpt the cloned node to append excerpt + * @return the element + */ + private Element generateCriteriaElementForSetOpExcerpt( + XmlProcessor hqmfXmlProcessor, Node clonedNodeToAppendExcerpt) { + Element criteriaElement = null; + for (int i = 0; i < clonedNodeToAppendExcerpt.getChildNodes().getLength(); i++) { + Node childNode = clonedNodeToAppendExcerpt.getChildNodes().item(i); + if (ID.equalsIgnoreCase(childNode.getNodeName())) { + Node criteriaNode = + generateEmptyGrouper( + hqmfXmlProcessor, + childNode.getAttributes().getNamedItem(ROOT).getNodeValue(), + childNode.getAttributes().getNamedItem(EXTENSION).getNodeValue()); + criteriaElement = (Element) criteriaNode; + break; + } + } + return criteriaElement; + } + + /** + * Creates the base temporal node. + * + * @param relOpNode the rel op node + * @param hqmfXmlProcessor the hqmf xml processor + * @return the element + */ + private Element createBaseTemporalNode(Node relOpNode, XmlProcessor hqmfXmlProcessor) { + + NamedNodeMap attribMap = relOpNode.getAttributes(); + Element temporallyRelatedInfoNode = + hqmfXmlProcessor.getOriginalDoc().createElement("temporallyRelatedInformation"); + temporallyRelatedInfoNode.setAttribute( + TYPE_CODE, attribMap.getNamedItem(TYPE).getNodeValue().toUpperCase()); + + Element temporalInfoNode = + hqmfXmlProcessor.getOriginalDoc().createElement("qdm:temporalInformation"); + String precisionUnit = "min"; // use min by default + + if (attribMap.getNamedItem(OPERATOR_TYPE) != null) { + String operatorType = attribMap.getNamedItem(OPERATOR_TYPE).getNodeValue(); + String quantity = attribMap.getNamedItem(QUANTITY).getNodeValue(); + String unit = attribMap.getNamedItem(UNIT).getNodeValue(); + + if ("seconds".equals(unit)) { + precisionUnit = "s"; + unit = "s"; + } else if ("hours".equals(unit)) { + unit = "h"; + } else if ("minutes".equals(unit)) { + unit = "min"; + } else { + precisionUnit = "d"; + if ("days".equals(unit)) { + unit = "d"; + } else if ("weeks".equals(unit)) { + unit = "wk"; + } else if ("months".equals(unit)) { + unit = "mo"; + } else if ("years".equals(unit)) { + unit = "a"; + } + } + + Element deltaNode = hqmfXmlProcessor.getOriginalDoc().createElement("qdm:delta"); + Element lowNode = hqmfXmlProcessor.getOriginalDoc().createElement("low"); + lowNode.setAttribute(UNIT, unit); + + Element highNode = hqmfXmlProcessor.getOriginalDoc().createElement("high"); + highNode.setAttribute(UNIT, unit); + + if (operatorType.startsWith("Greater Than")) { + lowNode.setAttribute(VALUE, quantity); + highNode.removeAttribute(UNIT); + highNode.setAttribute(NULL_FLAVOR, "PINF"); + if ("Greater Than or Equal To".equals(operatorType)) { + deltaNode.setAttribute("lowClosed", TRUE); + } + } else if ("Equal To".equals(operatorType)) { + deltaNode.setAttribute("lowClosed", TRUE); + deltaNode.setAttribute("highClosed", TRUE); + lowNode.setAttribute(VALUE, quantity); + highNode.setAttribute(VALUE, quantity); + } else if (operatorType.startsWith("Less Than")) { + deltaNode.setAttribute("lowClosed", TRUE); + lowNode.setAttribute(VALUE, "0"); + highNode.setAttribute(VALUE, quantity); + if ("Less Than or Equal To".equals(operatorType)) { + deltaNode.setAttribute("highClosed", TRUE); + } + } + deltaNode.appendChild(lowNode); + deltaNode.appendChild(highNode); + temporalInfoNode.appendChild(deltaNode); + } + temporalInfoNode.setAttribute("precisionUnit", precisionUnit); + temporallyRelatedInfoNode.appendChild(temporalInfoNode); + return temporallyRelatedInfoNode; + } + + /** + * Generate crit ref rel op. + * + * @param parentNode the parent node + * @param hqmfXmlProcessor the hqmf xml processor + * @param childNode the child node + * @param outboundRelElem the outbound rel elem + * @param clauseName the clause name + * @throws XPathExpressionException the x path expression exception + */ + private void generateCritRefRelOp( + Node parentNode, + XmlProcessor hqmfXmlProcessor, + Node childNode, + Node outboundRelElem, + String clauseName) + throws XPathExpressionException { + Node relOpEntryNode = generateRelOpHQMF(childNode, parentNode, clauseName); + + if (relOpEntryNode != null) { + Node idNode = getTagFromEntry(relOpEntryNode, ID); + // Node critNode = relOpEntryNode.getFirstChild(); + // NodeList nodeList = ((Element)critNode).getElementsByTagName(ID); + // if(nodeList != null && nodeList.getLength() > 0){ + if (idNode != null) { + // Node idNode = nodeList.item(0); + NamedNodeMap idAttribMap = idNode.getAttributes(); + String idRoot = idAttribMap.getNamedItem(ROOT).getNodeValue(); + String idExt = idAttribMap.getNamedItem(EXTENSION).getNodeValue(); + + Node parent = idNode.getParentNode(); + + NamedNodeMap attribMap = parent.getAttributes(); + String classCode = attribMap.getNamedItem(CLASS_CODE).getNodeValue(); + String moodCode = attribMap.getNamedItem(MOOD_CODE).getNodeValue(); + + // create criteriaRef + Element criteriaReference = + hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaReference.setAttribute(CLASS_CODE, classCode); + criteriaReference.setAttribute(MOOD_CODE, moodCode); + + Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + id.setAttribute(ROOT, idRoot); + id.setAttribute(EXTENSION, idExt); + + criteriaReference.appendChild(id); + outboundRelElem.appendChild(criteriaReference); + } + } + } + + /** + * Generate crit ref set op. + * + * @param parentNode the parent node + * @param hqmfXmlProcessor the hqmf xml processor + * @param childNode the child node + * @param outboundRelElem the outbound rel elem + * @param clauseName the clause name + * @throws XPathExpressionException the x path expression exception + */ + private void generateCritRefSetOp( + Node parentNode, + XmlProcessor hqmfXmlProcessor, + Node childNode, + Node outboundRelElem, + String clauseName) + throws XPathExpressionException { + + Node setOpEntry = generateSetOpHQMF(childNode, parentNode, clauseName); + NodeList childList = setOpEntry.getChildNodes(); + for (int j = 0; j < childList.getLength(); j++) { + Node child = childList.item(j); + if (GROUPER_CRITERIA.equals(child.getNodeName())) { + NodeList idChildList = ((Element) child).getElementsByTagName(ID); + if (idChildList.getLength() > 0) { + Node idChild = idChildList.item(0); + NamedNodeMap attribMap = idChild.getAttributes(); + String idRoot = attribMap.getNamedItem(ROOT).getNodeValue(); + String idExt = attribMap.getNamedItem(EXTENSION).getNodeValue(); + + // create criteriaRef + Element criteriaReference = + hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaReference.setAttribute(CLASS_CODE, "GROUPER"); + criteriaReference.setAttribute(MOOD_CODE, "EVN"); + + Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + id.setAttribute(ROOT, idRoot); + id.setAttribute(EXTENSION, idExt); + + criteriaReference.appendChild(id); + outboundRelElem.appendChild(criteriaReference); + } + } + } + } + + /** + * Generate crit ref for node. + * + * @param outboundRelElem the outbound rel elem + * @param childNode the child node + * @throws XPathExpressionException the x path expression exception + */ + private void generateCritRefForNode(Node outboundRelElem, Node childNode) + throws XPathExpressionException { + XmlProcessor hqmfXmlProcessor = measureExport.getHqmfXmlProcessor(); + String childName = childNode.getNodeName(); + + switch (childName) { + case ELEMENT_REF: + generateCritRefElementRef(outboundRelElem, childNode, hqmfXmlProcessor); + break; + case SUB_TREE_REF: + generateCritRefCQLDefine(outboundRelElem, childNode, hqmfXmlProcessor, true); + break; + + default: + break; + } + } + + /** + * This method will basically create a with classCode='GROUPER' and + * moodCode='EVN' and have the tag pointing to the for the referenced + * subTree/clause. + * + * @param outboundRelElem the outbound rel elem + * @param subTreeRefNode the sub tree ref node + * @param hqmfXmlProcessor the hqmf xml processor + * @throws XPathExpressionException the x path expression exception + */ + protected void generateCritRefCQLDefine( + Node outboundRelElem, Node subTreeRefNode, XmlProcessor hqmfXmlProcessor) + throws XPathExpressionException { + generateCritRefCQLDefine(outboundRelElem, subTreeRefNode, hqmfXmlProcessor, false); + } + + /** + * This method will basically create a with classCode='GROUPER' and + * moodCode='EVN' and have the tag pointing to the for the referenced + * subTree/clause. + * + * @param outboundRelElem the outbound rel elem + * @param cqlDefineNode the sub tree ref node + * @param hqmfXmlProcessor the hqmf xml processor + * @param checkExisting check in the map if already existing + * @throws XPathExpressionException the x path expression exception + */ + protected void generateCritRefCQLDefine( + Node outboundRelElem, + Node cqlDefineNode, + XmlProcessor hqmfXmlProcessor, + boolean checkExisting) + throws XPathExpressionException { + + String cqlDefUUID = cqlDefineNode.getAttributes().getNamedItem(UUID).getNodeValue(); + + String xpath = "/measure/cqlLookUp//definition[@id='" + cqlDefUUID + "']"; + Node definitionNode = + measureExport + .getSimpleXmlProcessor() + .findNode(measureExport.getSimpleXmlProcessor().getOriginalDoc(), xpath); + if (definitionNode != null) { + String defineName = definitionNode.getAttributes().getNamedItem("name").getNodeValue(); + Node cqlUUIDNode = + measureExport + .getSimpleXmlProcessor() + .findNode( + measureExport.getSimpleXmlProcessor().getOriginalDoc(), + "/measure/measureDetails/cqlUUID"); + Node cqlLibraryNode = + measureExport + .getSimpleXmlProcessor() + .findNode( + measureExport.getSimpleXmlProcessor().getOriginalDoc(), + "/measure/cqlLookUp/library"); + if (cqlUUIDNode != null && cqlLibraryNode != null) { + String uuid = cqlUUIDNode.getTextContent(); + String libraryName = cqlLibraryNode.getTextContent(); + String ext = libraryName + ".\"" + defineName + "\""; + // create criteriaRef + Element criteriaReference = + hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaReference.setAttribute(CLASS_CODE, "OBS"); + criteriaReference.setAttribute(MOOD_CODE, "EVN"); + + Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + id.setAttribute(ROOT, uuid); + id.setAttribute(EXTENSION, ext); + + criteriaReference.appendChild(id); + outboundRelElem.appendChild(criteriaReference); + } + } + } + + /** + * Generate crit ref element ref. + * + * @param outboundRelElem the outbound rel elem + * @param elementRefNode the element ref node + * @param hqmfXmlProcessor the hqmf xml processor + * @return the node + * @throws XPathExpressionException the x path expression exception + */ + private Node generateCritRefElementRef( + Node outboundRelElem, Node elementRefNode, XmlProcessor hqmfXmlProcessor) + throws XPathExpressionException { + String ext = getElementRefExt(elementRefNode, measureExport.getSimpleXmlProcessor()); + String root = elementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + Node idNodeQDM = + hqmfXmlProcessor.findNode( + hqmfXmlProcessor.getOriginalDoc(), + "//entry/*/id[@root=\"" + root + "\"][@extension=\"" + ext + "\"]"); + if (idNodeQDM != null) { + Node parent = idNodeQDM.getParentNode(); + if (parent != null) { + NamedNodeMap attribMap = parent.getAttributes(); + String classCode = attribMap.getNamedItem(CLASS_CODE).getNodeValue(); + String moodCode = attribMap.getNamedItem(MOOD_CODE).getNodeValue(); + + // create criteriaRef + Element criteriaReference = + hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaReference.setAttribute(CLASS_CODE, classCode); + criteriaReference.setAttribute(MOOD_CODE, moodCode); + + Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + id.setAttribute(ROOT, root); + id.setAttribute(EXTENSION, ext); + + criteriaReference.appendChild(id); + outboundRelElem.appendChild(criteriaReference); + // return element + return parent.getParentNode(); + } + } else { + // check if this is a measurement period + String displayName = elementRefNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + if ("Measurement Period : Timing Element".equals(displayName)) { + // create criteriaRef + Element criteriaReference = + hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaReference.setAttribute(CLASS_CODE, "OBS"); + criteriaReference.setAttribute(MOOD_CODE, "EVN"); + + Element id = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + id.setAttribute(ROOT, elementRefNode.getAttributes().getNamedItem(ID).getNodeValue()); + id.setAttribute(EXTENSION, "measureperiod"); + + criteriaReference.appendChild(id); + outboundRelElem.appendChild(criteriaReference); + } + } + return null; + } + + /** + * Generate item count element ref. + * + * @param me the me + * @param populationTypeCriteriaElement the population type criteria element + * @param elementRefNode the element ref node + * @param hqmfXmlProcessor the hqmf xml processor + * @throws XPathExpressionException the x path expression exception + */ + public void generateItemCountElementRef( + MeasureExport me, + Element populationTypeCriteriaElement, + Node elementRefNode, + XmlProcessor hqmfXmlProcessor) + throws XPathExpressionException { + String ext = getElementRefExt(elementRefNode, me.getSimpleXmlProcessor()); + String root = elementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + Node idNodeQDM = + hqmfXmlProcessor.findNode( + hqmfXmlProcessor.getOriginalDoc(), + "//entry/*/id[@root='" + root + "'][@extension=\"" + ext + "\"]"); + if (idNodeQDM != null) { + Node parent = idNodeQDM.getParentNode(); + if (parent != null) { + String classCode = parent.getAttributes().getNamedItem("classCode").getNodeValue(); + String moodCode = parent.getAttributes().getNamedItem("moodCode").getNodeValue(); + // item count Criteria Ref for Measure Observations + if ("measureObservationDefinition".equals(populationTypeCriteriaElement.getNodeName())) { + Element componentOfElem = hqmfXmlProcessor.getOriginalDoc().createElement("componentOf"); + componentOfElem.setAttribute(TYPE_CODE, "COMP"); + Element criteriaRef = hqmfXmlProcessor.getOriginalDoc().createElement(CRITERIA_REFERENCE); + criteriaRef.setAttribute(CLASS_CODE, classCode); + criteriaRef.setAttribute(MOOD_CODE, moodCode); + Element idElement = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + idElement.setAttribute(ROOT, root); + idElement.setAttribute(EXTENSION, ext); + criteriaRef.appendChild(idElement); + componentOfElem.appendChild(criteriaRef); + Comment comment = hqmfXmlProcessor.getOriginalDoc().createComment("Item Count "); + populationTypeCriteriaElement.appendChild(comment); + populationTypeCriteriaElement.appendChild(componentOfElem); + } else { // item count Criteria Ref for Populations + // create component for ItemCount ElmentRef + Element componentElem = hqmfXmlProcessor.getOriginalDoc().createElement("component"); + componentElem.setAttribute(TYPE_CODE, "COMP"); + Element measureAttrElem = + hqmfXmlProcessor.getOriginalDoc().createElement("measureAttribute"); + componentElem.appendChild(measureAttrElem); + Element codeElem = hqmfXmlProcessor.getOriginalDoc().createElement("code"); + codeElem.setAttribute(CODE, "ITMCNT"); + codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.5.4"); + codeElem.setAttribute(CODE_SYSTEM_NAME, "HL7 Observation Value"); + Element displayNameElem = hqmfXmlProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + displayNameElem.setAttribute(VALUE, "Items to count"); + codeElem.appendChild(displayNameElem); + Element valueElem = hqmfXmlProcessor.getOriginalDoc().createElement(VALUE); + valueElem.setAttribute("xsi:type", "II"); + valueElem.setAttribute(ROOT, root); + valueElem.setAttribute(EXTENSION, ext); + measureAttrElem.appendChild(codeElem); + measureAttrElem.appendChild(valueElem); + populationTypeCriteriaElement.appendChild(componentElem); + } + } + } + } + + /** + * Gets the element ref ext. + * + * @param elementRefNode the element ref node + * @param simpleXmlProcessor the simple xml processor + * @return the element ref ext + * @throws XPathExpressionException the x path expression exception + */ + private String getElementRefExt(Node elementRefNode, XmlProcessor simpleXmlProcessor) + throws XPathExpressionException { + String extension = ""; + if (elementRefNode.hasChildNodes()) { + Node childNode = elementRefNode.getFirstChild(); + if ("attribute".equals(childNode.getNodeName())) { + extension = childNode.getAttributes().getNamedItem(ATTR_UUID).getNodeValue(); + } + } else { + String id = elementRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + Node qdmNode = + simpleXmlProcessor.findNode( + simpleXmlProcessor.getOriginalDoc(), + "/measure/elementLookUp/qdm[@uuid='" + id + "']"); + if (qdmNode != null) { + String dataType = qdmNode.getAttributes().getNamedItem(DATATYPE).getNodeValue(); + String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); + extension = qdmName + "_" + dataType; + if (qdmNode.getAttributes().getNamedItem(INSTANCE) != null) { + extension = + qdmNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + "_" + extension; + } + } + } + return StringUtils.deleteWhitespace(extension); + } + + /** + * Generate empty grouper. + * + * @param hqmfXmlProcessor the hqmf xml processor + * @param root the root + * @param ext the ext + * @return the node + */ + private Node generateEmptyGrouper(XmlProcessor hqmfXmlProcessor, String root, String ext) { + Element grouperElem = hqmfXmlProcessor.getOriginalDoc().createElement(GROUPER_CRITERIA); + grouperElem.setAttribute(CLASS_CODE, "GROUPER"); + grouperElem.setAttribute(MOOD_CODE, "EVN"); + + Element idElem = hqmfXmlProcessor.getOriginalDoc().createElement(ID); + idElem.setAttribute(ROOT, root); + idElem.setAttribute(EXTENSION, StringUtils.deleteWhitespace(ext)); + + grouperElem.appendChild(idElem); + + return grouperElem; + } + + /** + * Generate empty outbound elem. + * + * @param hqmfXmlProcessor the hqmf xml processor + * @return the element + */ + private Element generateEmptyOutboundElem(XmlProcessor hqmfXmlProcessor) { + Element outboundRelElem = + hqmfXmlProcessor.getOriginalDoc().createElement(OUTBOUND_RELATIONSHIP); + outboundRelElem.setAttribute(TYPE_CODE, "COMP"); + return outboundRelElem; + } + + /** + * Gets the tag from entry. + * + * @param entryElem the entry elem + * @param tagName the tag name + * @return the tag from entry + */ + private Node getTagFromEntry(Node entryElem, String tagName) { + + String entryElemName = entryElem.getNodeName(); + if (ENTRY.equals(entryElemName)) { + Node firstChild = entryElem.getFirstChild(); + if (LOCAL_VARIABLE_NAME.equals(firstChild.getNodeName())) { + NodeList nodeList = ((Element) firstChild.getNextSibling()).getElementsByTagName(tagName); + if (nodeList != null && nodeList.getLength() > 0) { + return nodeList.item(0); + } + } else { + NodeList nodeList = ((Element) firstChild).getElementsByTagName(tagName); + if (nodeList != null && nodeList.getLength() > 0) { + return nodeList.item(0); + } + } + } + return null; + } + + /** + * Check If the parentNode is a SUB_TREE node. Or else, if parent is a 'functionalOp' then + * recursively check if the parentNode's parent is a 'subTree'. If yes, then return true. + * + * @param parentNode the parent node + * @return boolean + */ + private Node checkIfSubTree(Node parentNode) { + Node returnNode = null; + if (parentNode != null) { + String parentName = parentNode.getNodeName(); + if (SUB_TREE.equals(parentName)) { + returnNode = parentNode; + } else if (FUNCTIONAL_OP.equals(parentName)) { + returnNode = checkIfSubTree(parentNode.getParentNode()); + } + } + return returnNode; + } + + /** + * Gets the firt child list. + * + * @param function the function + * @return the firt child list + */ + public static List getFunctionalOpFirstChild(String function) { + List childList = new ArrayList<>(); + if (AGE_AT.equalsIgnoreCase(function)) { + childList.add(SUB_TREE_REF); + childList.add(RELATIONAL_OP); + childList.add(FUNCTIONAL_OP); + childList.add(ELEMENT_REF); + } else { + childList.add(ELEMENT_REF); + childList.add(SET_OP); + childList.add(SUB_TREE_REF); + childList.add(RELATIONAL_OP); + } + return childList; + } + + /** + * Gets the aggregate and instance function childs. + * + * @param typeChild the type child + * @return the aggregate and instance function childs + */ + public static List getAggregateAndInstanceFunctionChilds(String typeChild) { + List aggregateList = new ArrayList<>(); + aggregateList.add("FIRST"); + aggregateList.add("SECOND"); + aggregateList.add("THIRD"); + aggregateList.add("FOURTH"); + aggregateList.add("FIFTH"); + aggregateList.add("MOST RECENT"); + if ("AGGREGATE".equals(typeChild)) { + aggregateList.add("DATETIMEDIFF"); + } + return aggregateList; + } + + /** + * Gets the functional op first child in mo. + * + * @param function the function + * @return the functional op first child in mo + */ + public static List getFunctionalOpFirstChildInMO(String function) { + List childList = new ArrayList<>(); + if ("DATETIMEDIFF".equalsIgnoreCase(function)) { + childList.add(ELEMENT_REF); + childList.add(SUB_TREE_REF); + childList.add(RELATIONAL_OP); + childList.addAll(getAggregateAndInstanceFunctionChilds("INSTANCE")); + } else { + childList.addAll(getFunctionalOpFirstChild(function)); + childList.addAll(getAggregateAndInstanceFunctionChilds("AGGREGATE")); + } + return childList; + } + + /** Check for used Used sub tree ref Node map in Populations and Meausre Observations. */ + private void createUsedSubTreeRefMap() { + + XmlProcessor simpleXmlProcessor = measureExport.getSimpleXmlProcessor(); + String typeXpathString = ""; + List usedSubTreeRefIdsPop = new ArrayList<>(); + List usedSubTreeRefIdsMO = new ArrayList<>(); + List usedSubTreeRefIDsRA = new ArrayList<>(); + for (String typeString : POPULATION_NAME_LIST) { + typeXpathString += "@type = '" + typeString + "' or"; + } + typeXpathString = typeXpathString.substring(0, typeXpathString.lastIndexOf(" or")); + String xpathForSubTreeInPOPClause = + "/measure/measureGrouping//clause[" + typeXpathString + "]//subTreeRef/@id"; + String xpathForSubTreeInMOClause = + "/measure/measureGrouping//clause[@type='measureObservation']//subTreeRef/@id"; + String xpathForSubTreeInRAClause = "/measure//riskAdjustmentVariables/subTreeRef/@id"; + try { + + // creating used Subtree Red Map in Populations + NodeList populationsSubTreeNode = + simpleXmlProcessor.findNodeList( + simpleXmlProcessor.getOriginalDoc(), xpathForSubTreeInPOPClause); + for (int i = 0; i < populationsSubTreeNode.getLength(); i++) { + String uuid = populationsSubTreeNode.item(i).getNodeValue(); + uuid = checkIfQDMVarInstanceIsPresent(uuid, simpleXmlProcessor); + if (!usedSubTreeRefIdsPop.contains(uuid)) { + usedSubTreeRefIdsPop.add(uuid); + } + } + usedSubTreeRefIdsPop = checkUnUsedSubTreeRef(simpleXmlProcessor, usedSubTreeRefIdsPop); + for (String uuid : usedSubTreeRefIdsPop) { + Node subTreeNode = createUsedSubTreeRefMap(simpleXmlProcessor, uuid); + subTreeNodeInPOPMap.put(uuid, subTreeNode); + } + + // creating used Subtree Red Map in Measure Observations + NodeList measureObsSubTreeNode = + simpleXmlProcessor.findNodeList( + simpleXmlProcessor.getOriginalDoc(), xpathForSubTreeInMOClause); + for (int i = 0; i < measureObsSubTreeNode.getLength(); i++) { + String uuid = measureObsSubTreeNode.item(i).getNodeValue(); + uuid = checkIfQDMVarInstanceIsPresent(uuid, simpleXmlProcessor); + if (!usedSubTreeRefIdsMO.contains(uuid)) { + usedSubTreeRefIdsMO.add(uuid); + } + } + usedSubTreeRefIdsMO = checkUnUsedSubTreeRef(simpleXmlProcessor, usedSubTreeRefIdsMO); + for (String uuid : usedSubTreeRefIdsMO) { + Node subTreeNode = createUsedSubTreeRefMap(simpleXmlProcessor, uuid); + subTreeNodeInMOMap.put(uuid, subTreeNode); + } + // creating used Subtree Red in Risk Adjustment + NodeList riskAdjSubTreeNode = + simpleXmlProcessor.findNodeList( + simpleXmlProcessor.getOriginalDoc(), xpathForSubTreeInRAClause); + for (int i = 0; i < riskAdjSubTreeNode.getLength(); i++) { + String uuid = riskAdjSubTreeNode.item(i).getNodeValue(); + uuid = checkIfQDMVarInstanceIsPresent(uuid, simpleXmlProcessor); + if (!usedSubTreeRefIDsRA.contains(uuid)) { + usedSubTreeRefIDsRA.add(uuid); + } + } + usedSubTreeRefIDsRA = checkUnUsedSubTreeRef(simpleXmlProcessor, usedSubTreeRefIDsRA); + for (String uuid : usedSubTreeRefIDsRA) { + Node subTreeNode = createUsedSubTreeRefMap(simpleXmlProcessor, uuid); + subTreeNodeInRAMap.put(uuid, subTreeNode); + } + + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + + /** + * Creates the used sub tree ref map. + * + * @param simpleXmlProcessor the simple xml processor + * @param uuid the uuid + * @return the node + */ + private Node createUsedSubTreeRefMap(XmlProcessor simpleXmlProcessor, String uuid) { + String xpathforUsedSubTreeMap = "/measure/subTreeLookUp/subTree[@uuid='" + uuid + "']"; + Node subTreeNode = null; + try { + subTreeNode = + simpleXmlProcessor.findNode(simpleXmlProcessor.getOriginalDoc(), xpathforUsedSubTreeMap); + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + return subTreeNode; + } + + /** + * Check un used sub tree ref. + * + * @param xmlProcessor the xml processor + * @param usedSubTreeRefIds the used sub tree ref ids + * @return the list + */ + private List checkUnUsedSubTreeRef( + XmlProcessor xmlProcessor, List usedSubTreeRefIds) { + + List allSubTreeRefIds = new ArrayList<>(); + NodeList subTreeRefIdsNodeList; + javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); + try { + subTreeRefIdsNodeList = + xmlProcessor.findNodeList(xmlProcessor.getOriginalDoc(), "/measure//subTreeRef/@id"); + + for (int i = 0; i < subTreeRefIdsNodeList.getLength(); i++) { + Node SubTreeRefIdAttributeNode = subTreeRefIdsNodeList.item(i); + if (!allSubTreeRefIds.contains(SubTreeRefIdAttributeNode.getNodeValue())) { + allSubTreeRefIds.add(SubTreeRefIdAttributeNode.getNodeValue()); + } + } + allSubTreeRefIds.removeAll(usedSubTreeRefIds); + + for (int i = 0; i < usedSubTreeRefIds.size(); i++) { + for (int j = 0; j < allSubTreeRefIds.size(); j++) { + Node usedSubTreeRefNode = + xmlProcessor.findNode( + xmlProcessor.getOriginalDoc(), + "/measure/subTreeLookUp/subTree[@uuid='" + + usedSubTreeRefIds.get(i) + + "']//subTreeRef[@id='" + + allSubTreeRefIds.get(j) + + "']"); + if (usedSubTreeRefNode != null) { + + String subTreeUUID = usedSubTreeRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + String XPATH_IS_INSTANCE_OF = + "//subTree [boolean(@instanceOf)]/@uuid ='" + subTreeUUID + "'"; + boolean isOccurrenceNode = + (Boolean) + xPath.evaluate( + XPATH_IS_INSTANCE_OF, + xmlProcessor.getOriginalDoc(), + XPathConstants.BOOLEAN); + if (isOccurrenceNode) { + String XPATH_PARENT_UUID = "//subTree [@uuid ='" + subTreeUUID + "']/@instanceOf"; + String parentUUID = + (String) + xPath.evaluate( + XPATH_PARENT_UUID, xmlProcessor.getOriginalDoc(), XPathConstants.STRING); + if (!usedSubTreeRefIds.contains(parentUUID)) { + usedSubTreeRefIds.add(parentUUID); + } + } + if (!usedSubTreeRefIds.contains(allSubTreeRefIds.get(j))) { + + usedSubTreeRefIds.add(allSubTreeRefIds.get(j)); + } + } + } + } + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + return usedSubTreeRefIds; + } + + /** + * Validate sub tree ref in pop. + * + * @param subTreeNode the sub tree node + * @param functionalOpNode the functional op node + * @return true, if successful + */ + public boolean validateSubTreeRefInPOP(Node subTreeNode, Node functionalOpNode) { + if (subTreeNodeInPOPMap.get(subTreeNode.getAttributes().getNamedItem(UUID).getNodeValue()) + != null) { + String firstChildName = functionalOpNode.getFirstChild().getNodeName(); + String functionalOpType = functionalOpNode.getAttributes().getNamedItem(TYPE).getNodeValue(); + List childsList = FUNCTIONAL_OP_RULES_IN_POP.get(functionalOpType); + if (childsList.contains(firstChildName)) { + return true; + } + } + return false; + } + + /** + * Utility method which will try to find the tag "localVariableName" and set the given string + * value to its VALUE attribute. + * + * @param node the node + * @param localVarName the local var name + */ + private void updateLocalVar(Node node, String localVarName) { + if (node == null) { + return; + } + NodeList localVarNodeList = ((Element) node).getElementsByTagName(LOCAL_VARIABLE_NAME); + if (localVarNodeList != null && localVarNodeList.getLength() > 0) { + Element localVar = (Element) localVarNodeList.item(0); + localVar.setAttribute(VALUE, localVarName); + } + } + + /** + * Check if qdm var instance is present. + * + * @param usedSubtreeRefId the used subtree ref id + * @param xmlProcessor the xml processor + * @return the string + */ + private String checkIfQDMVarInstanceIsPresent( + String usedSubtreeRefId, XmlProcessor xmlProcessor) { + + String XPATH_INSTANCE_QDM_VAR = + "/measure/subTreeLookUp/subTree[@uuid='" + usedSubtreeRefId + "']/@instance"; + String XPATH_INSTANCE_OF_QDM_VAR = + "/measure/subTreeLookUp/subTree[@uuid='" + usedSubtreeRefId + "']/@instanceOf"; + try { + Node nodesSDE_SubTree = + xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), XPATH_INSTANCE_QDM_VAR); + if (nodesSDE_SubTree != null) { + Node nodesSDE_SubTreeInstance = + xmlProcessor.findNode(xmlProcessor.getOriginalDoc(), XPATH_INSTANCE_OF_QDM_VAR); + usedSubtreeRefId = nodesSDE_SubTreeInstance.getNodeValue(); + } + + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + + return usedSubtreeRefId; + } + + /** + * Gets the sub tree node map. + * + * @return the subTreeNodeMap + */ + public Map getSubTreeNodeMap() { + return subTreeNodeMap; + } + + /** + * Sets the sub tree node map. + * + * @param subTreeNodeMap the subTreeNodeMap to set + */ + public void setSubTreeNodeMap(Map subTreeNodeMap) { + this.subTreeNodeMap = subTreeNodeMap; + } + + /** + * Gets the measure export. + * + * @return the measureExport + */ + public MeasureExport getMeasureExport() { + return measureExport; + } + + /** + * Sets the measure export. + * + * @param measureExport the measureExport to set + */ + public void setMeasureExport(MeasureExport measureExport) { + this.measureExport = measureExport; + } + + /** + * Gets the sub tree node in mo map. + * + * @return the subTreeNodeInMOMap + */ + public Map getSubTreeNodeInMOMap() { + return subTreeNodeInMOMap; + } + + /** + * Sets the sub tree node in mo map. + * + * @param subTreeNodeInMOMap the subTreeNodeInMOMap to set + */ + public void setSubTreeNodeInMOMap(Map subTreeNodeInMOMap) { + this.subTreeNodeInMOMap = subTreeNodeInMOMap; + } + + /** + * Gets the sub tree node in ra map. + * + * @return the subTreeNodeInMOMap + */ + public Map getSubTreeNodeInRAMap() { + return subTreeNodeInRAMap; + } + + /** + * Sets the sub tree node in ra map. + * + * @param subTreeNodeInRAMap the sub tree node in ra map + */ + public void setSubTreeNodeInRAMap(Map subTreeNodeInRAMap) { + this.subTreeNodeInRAMap = subTreeNodeInRAMap; + } + + /** + * Gets the sub tree node in pop map. + * + * @return the subTreeNodeInPOPMap + */ + public Map getSubTreeNodeInPOPMap() { + return subTreeNodeInPOPMap; + } + + /** + * Sets the sub tree node in pop map. + * + * @param subTreeNodeInPOPMap the subTreeNodeInPOPMap to set + */ + public void setSubTreeNodeInPOPMap(Map subTreeNodeInPOPMap) { + this.subTreeNodeInPOPMap = subTreeNodeInPOPMap; + } } diff --git a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaElementGenerator.java b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaElementGenerator.java index 5a1854f..055309b 100644 --- a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaElementGenerator.java +++ b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaElementGenerator.java @@ -21,744 +21,873 @@ import java.util.Map; public class HQMFDataCriteriaElementGenerator implements Generator { - - private static final String DATA_CRITERIA_EXTENSION = "2021-02-01"; - - /** The occurrence map. */ - private Map occurrenceMap = new HashMap<>(); - - protected String extensionValue = null; - - /** The Constant logger. */ - private static final Logger logger = LoggerFactory.getLogger(HQMFDataCriteriaElementGenerator.class); - - /** - * Generate hqm for measure. - * - * @param me the me - * @return the string - */ - @Override - public String generate(MeasureExport me) { - getExtensionValueBasedOnVersion(me); - XmlProcessor dataCriteriaXMLProcessor = createDateCriteriaTemplate(); - me.setHqmfXmlProcessor(dataCriteriaXMLProcessor); - - String simpleXMLStr = me.getSimpleXml(); - XmlProcessor simpleXmlprocessor = new XmlProcessor(simpleXMLStr); - me.setSimpleXmlProcessor(simpleXmlprocessor); - - createDataCriteriaForQDMELements(me, dataCriteriaXMLProcessor, simpleXmlprocessor); - addDataCriteriaComment(dataCriteriaXMLProcessor); - return dataCriteriaXMLProcessor.transform(dataCriteriaXMLProcessor.getOriginalDoc(), true); - } - - /** - * Creates the date criteria template. - * - * @return the string - */ - private XmlProcessor createDateCriteriaTemplate() { - XmlProcessor outputProcessor = new XmlProcessor( - ""); - - Node dataCriteriaElem = outputProcessor.getOriginalDoc() - .getElementsByTagName("dataCriteriaSection").item(0); - Element templateId = outputProcessor.getOriginalDoc() - .createElement(TEMPLATE_ID); - dataCriteriaElem.appendChild(templateId); - Element itemChild = outputProcessor.getOriginalDoc() - .createElement(ITEM); - itemChild.setAttribute(ROOT, "2.16.840.1.113883.10.20.28.2.6"); - //itemChild.setAttribute("extension", getDataCriteriaExtValueBasedOnVersion(me)); - itemChild.setAttribute("extension", DATA_CRITERIA_EXTENSION); - templateId.appendChild(itemChild); - // creating Code Element for DataCriteria - Element codeElem = outputProcessor.getOriginalDoc() - .createElement(CODE); - codeElem.setAttribute(CODE, "57025-9"); - codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.6.1"); - dataCriteriaElem.appendChild(codeElem); - // creating title for DataCriteria - Element titleElem = outputProcessor.getOriginalDoc() - .createElement(TITLE); - titleElem.setAttribute(VALUE, "Data Criteria Section"); - dataCriteriaElem.appendChild(titleElem); - // creating text for DataCriteria - Element textElem = outputProcessor.getOriginalDoc() - .createElement("text"); - dataCriteriaElem.appendChild(textElem); - - return outputProcessor; - } - - private String getDataCriteriaExtValueBasedOnVersion() { - return VERSION_5_0_ID; - } - /** - * Creates the data criteria for qdm elements. - * - * @param me the me - * @param dataCriteriaXMLProcessor the data criteria xml processor - * @param simpleXmlprocessor the simple xmlprocessor - */ - private void createDataCriteriaForQDMELements(MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor) { - String xPathForQDMNoAttribs = "/measure/elementLookUp/qdm[@datatype and @code ='false']"; - String xpathForOtherSupplementalQDMs = "/measure/supplementalDataElements/elementRef/@id"; - String xpathForMeasureGroupingItemCount = "/measure//itemCount/elementRef/@id"; - - - try { - NodeList qdmNoAttributeNodeList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), xPathForQDMNoAttribs); - generateCQLQDMNodeEntries(dataCriteriaXMLProcessor, simpleXmlprocessor, - qdmNoAttributeNodeList); - - HQMFDataCriteriaElementGeneratorForCodes cqlBasedHQMFDataCriteriaElementGeneratorForCodes = new HQMFDataCriteriaElementGeneratorForCodes(); - cqlBasedHQMFDataCriteriaElementGeneratorForCodes.generate(me); - - //generating QDM Entries for other Supplemental Data Elements - NodeList supplementalDataElements = me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), - xpathForOtherSupplementalQDMs); - generateOtherSupplementalDataQDMEntries(me, dataCriteriaXMLProcessor, supplementalDataElements); - - //generating QDM entries for measureGrouping ItemCountlist - NodeList measureGroupingItemCountList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), xpathForMeasureGroupingItemCount); - generateMeasureGrpnItemCountQDMEntries(me, dataCriteriaXMLProcessor, measureGroupingItemCountList); - - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - - - protected void getExtensionValueBasedOnVersion(MeasureExport me) { - if(me!=null){ - extensionValue = getDataCriteriaExtValueBasedOnVersion(); - } - } - - /** - * Generate measure grp item count qdm entries. - * - * @param me the me - * @param dataCriteriaXMLProcessor the data criteria xml processor - * @param measureGroupingItemCountList the measure grouping item count list - * @throws XPathExpressionException the x path expression exception - */ - private void generateMeasureGrpnItemCountQDMEntries(MeasureExport me, - XmlProcessor dataCriteriaXMLProcessor, - NodeList measureGroupingItemCountList) throws XPathExpressionException { - - if(measureGroupingItemCountList==null || - measureGroupingItemCountList.getLength()<1){ - return; - } - List itemCountIDList = new ArrayList(); - for(int i=0; i supplementalElemenRefIds = new ArrayList(); - for(int i=0; i uuidList){ - String uuidXPathString = ""; - for (String uuidString: uuidList) { - uuidXPathString += "@uuid = '" + uuidString + "' or"; - } - - uuidXPathString = uuidXPathString.substring(0, uuidXPathString.lastIndexOf(" or")); - return uuidXPathString; - } - - private void generateCQLQDMNodeEntries(XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor simpleXmlprocessor, NodeList qdmNoAttributeNodeList) - throws XPathExpressionException { - - if (qdmNoAttributeNodeList == null) { - return; - } - - for (int i = 0; i < qdmNoAttributeNodeList.getLength(); i++) { - Node qdmNode = qdmNoAttributeNodeList.item(i); - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor); - } - } - - /** - * Generate qdm entry. - * - * @param dataCriteriaXMLProcessor the data criteria xml processor - * @param simpleXmlprocessor the simple xmlprocessor - * @param qdmNode the qdm node - * @param forceGenerate the force generate - * @throws XPathExpressionException the x path expression exception - */ - private void generateQDMEntry(XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor simpleXmlprocessor, Node qdmNode, boolean forceGenerate) - throws XPathExpressionException { - String qdmUUID = qdmNode.getAttributes().getNamedItem(UUID).getNodeValue(); - - String xPathForIndividualElementRefs = "/measure/subTreeLookUp//elementRef[@id='"+qdmUUID+"'][not(attribute)]"; - NodeList elementRefList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), xPathForIndividualElementRefs); - if(forceGenerate || elementRefList.getLength() > 0){ - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor); - } - } - - /** - * Create xml for data criteria. - * - * @param qdmNode the qdm node - * @param dataCriteriaXMLProcessor the data criteria xml processor - * @param simpleXmlprocessor the simple xmlprocessor - * @return void - */ - private void createXmlForDataCriteria(Node qdmNode, XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor) { - String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(5.6); - String xPathForTemplate = "/templates/template[text()='" + dataType.toLowerCase() + "']"; - String actNodeStr = ""; - try { - - Node templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xPathForTemplate); - if (templateNode != null) { - String attrClass = templateNode.getAttributes() - .getNamedItem(CLASS).getNodeValue(); - String xpathForAct = "/templates/acts/act[@a_id='" + attrClass - + "']"; - Node actNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xpathForAct); - if (actNode != null) { - actNodeStr = actNode.getTextContent(); - } - - createDataCriteriaElementTag(actNodeStr, templateNode, qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor,templateXMLProcessor); - } - - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - - /** - * Gets the creates the data create element tag. - * - * @param actNodeStr the act node str - * @param templateNode the template node - * @param qdmNode the qdm node - * @param dataCriteriaXMLProcessor the data criteria xml processor - * @param simpleXmlprocessor the simple xmlprocessor - * @param templateXMLProcessor - templateXmlProcessor - * @throws XPathExpressionException the x path expression exception - */ - private void createDataCriteriaElementTag(String actNodeStr, Node templateNode, - Node qdmNode, XmlProcessor dataCriteriaXMLProcessor, XmlProcessor - simpleXmlprocessor, XmlProcessor templateXMLProcessor) throws XPathExpressionException { - String oidValue = templateNode.getAttributes().getNamedItem(OID).getNodeValue(); - String classCodeValue = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); - String moodValue = templateNode.getAttributes().getNamedItem(MOOD).getNodeValue(); - - Node statusNode= templateNode.getAttributes().getNamedItem("status"); - String statusValue = statusNode != null ? statusNode.getNodeValue() : ""; - String rootValue = qdmNode.getAttributes().getNamedItem(ID).getNodeValue(); - String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); - - String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); - Node actionNegInd = templateNode.getAttributes().getNamedItem("actionNegationInd"); - String entryCommentText = dataType; - // Local variable changes. - String qdmLocalVariableName = qdmName + "_" + dataType; - String localVariableName = qdmLocalVariableName; - - qdmLocalVariableName = StringUtils.deleteWhitespace(qdmLocalVariableName); - localVariableName = StringUtils.deleteWhitespace(localVariableName); - - Element dataCriteriaSectionElem = (Element) dataCriteriaXMLProcessor.getOriginalDoc().getElementsByTagName("dataCriteriaSection").item(0); - Element componentElem = (Element) dataCriteriaXMLProcessor.getOriginalDoc().getElementsByTagName("component").item(0); - Attr nameSpaceAttr = dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:xsi"); - nameSpaceAttr.setNodeValue(nameSpace); - componentElem.setAttributeNodeNS(nameSpaceAttr); - Attr qdmNameSpaceAttr = dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:cql-ext"); - qdmNameSpaceAttr.setNodeValue("urn:hhs-cql:hqmf-n1-extensions:v1"); - componentElem.setAttributeNodeNS(qdmNameSpaceAttr); - // creating Entry Tag - Element entryElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("entry"); - entryElem.setAttribute(TYPE_CODE, "DRIV"); - // Local Variable Name Tag - Inside Entry tag. - Element localVarElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("localVariableName"); - localVarElem.setAttribute(VALUE, localVariableName + "_" + UUIDUtilClient.uuid(5)); - entryElem.appendChild(localVarElem); - Element dataCriteriaElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(actNodeStr); - entryElem.appendChild(dataCriteriaElem); - dataCriteriaElem.setAttribute(CLASS_CODE, classCodeValue); - dataCriteriaElem.setAttribute(MOOD_CODE, moodValue); - // adding actionNegationInd for Negative Datatypes - if (actionNegInd != null) { - dataCriteriaElem.setAttribute(ACTION_NEGATION_IND, actionNegInd.getNodeValue()); - } - Element templateId = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TEMPLATE_ID); - dataCriteriaElem.appendChild(templateId); - Element itemChild = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); - itemChild.setAttribute(ROOT, oidValue); - if (templateNode.getAttributes().getNamedItem("specificExtensionValue") != null) { - String specificExtensionValue = templateNode.getAttributes().getNamedItem("specificExtensionValue") - .getNodeValue(); - itemChild.setAttribute("extension", specificExtensionValue); - } else if (templateNode.getAttributes().getNamedItem("addExtensionInTemplate") == null) { - itemChild.setAttribute("extension", extensionValue); - } - templateId.appendChild(itemChild); - Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); - idElem.setAttribute(ROOT, rootValue); - idElem.setAttribute("extension", qdmLocalVariableName); - dataCriteriaElem.appendChild(idElem); - - boolean appendEntryElem = false; - String occurString = dataType + "-" + qdmOidValue; - - if (qdmNode.getAttributes().getNamedItem("instance") != null) { - generateOutboundForOccur(templateNode, qdmNode, dataCriteriaElem, occurString, dataCriteriaXMLProcessor, - simpleXmlprocessor); - entryCommentText = qdmNode.getAttributes().getNamedItem("instance").getNodeValue() + " " + entryCommentText; - appendEntryElem = true; - } else if (!occurrenceMap.containsKey(occurString) /* || (attributeQDMNode != null) */) { - - String isAddCodeTag = templateNode.getAttributes().getNamedItem("addCodeTag").getNodeValue(); - if ("true".equalsIgnoreCase(isAddCodeTag)) { // Add Code Element to DataCriteria Element. - addCodeElementToDataCriteriaElement(templateNode, dataCriteriaXMLProcessor, qdmNode, dataCriteriaElem); - } - Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); - titleElem.setAttribute(VALUE, dataType); - dataCriteriaElem.appendChild(titleElem); - - if(StringUtils.isNotEmpty(statusValue)) { - Element statusCodeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("statusCode"); - statusCodeElem.setAttribute(CODE, statusValue); - dataCriteriaElem.appendChild(statusCodeElem); - } - - // Add value tag in entry element. - String addValueSetElement = templateNode.getAttributes().getNamedItem("addValueTag").getNodeValue(); - if ("true".equalsIgnoreCase(addValueSetElement)) { - Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(VALUE); - Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); - if (valueTypeAttr != null) { - valueElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); - } - - Node valueCodeSystem = templateNode.getAttributes().getNamedItem("valueCodeSystem"); - Node valueCode = templateNode.getAttributes().getNamedItem("valueCode"); - Node valueDisplayName = templateNode.getAttributes().getNamedItem("valueDisplayName"); - Node valueCodeSystemName = templateNode.getAttributes().getNamedItem("valueCodeSystemName"); - if (valueCode != null && valueCodeSystem != null) { - valueElem.setAttribute("code", valueCode.getNodeValue()); - valueElem.setAttribute("codeSystem", valueCodeSystem.getNodeValue()); - if (valueCodeSystemName != null) { - valueElem.setAttribute("codeSystemName", valueCodeSystemName.getNodeValue()); - } - } else { - valueElem.setAttribute("valueSet", qdmOidValue); - addValueSetVersion(qdmNode, valueElem); - } - - dataCriteriaElem.appendChild(valueElem); - } - if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { - appendSubTemplateNode(templateNode, dataCriteriaXMLProcessor, templateXMLProcessor, dataCriteriaElem, - qdmNode); - } - // checkForAttributes - - appendEntryElem = true; - } - if (appendEntryElem) { - dataCriteriaSectionElem.appendChild(entryElem); - } - - } - - /** - * Method to add valueSetVersion attribute in value element tag. - * - * @param qdmNode the qdm node - * @param valueElem the value elem - */ - protected void addValueSetVersion(Node qdmNode, Element valueElem) { - // This is to be commented until we start getting value set versions from VSAC. - boolean addVersionToValueTag = false; - String valueSetVersion = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); - - if ("1.0".equals(valueSetVersion) || "1".equals(valueSetVersion) || StringUtils.isBlank(valueSetVersion)) { - addVersionToValueTag = false; - } else { - valueSetVersion = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); - addVersionToValueTag = true; - } - if (addVersionToValueTag) { - valueElem.setAttribute("valueSetVersion", valueSetVersion); - } - } - - /** - * Generate outbound for occur. - * - * @param templateNode the template node - * @param qdmNode the qdm node - * @param dataCriteriaElem the data criteria elem - * @param occurString the occur string - */ - private void generateOutboundForOccur(Node templateNode, Node qdmNode, - Element dataCriteriaElem, String occurString,XmlProcessor dataCriteriaXMLProcessor, XmlProcessor - simpleXmlprocessor) { - Node refNode = occurrenceMap.get(occurString); - - logger.debug("In generateOutboundForOccur()..refNode:"+refNode); - logger.debug("----------Occurance map:"+occurrenceMap); - - if(refNode != null){ - - try { - Node cloneRefNode = refNode.cloneNode(true); - String name = cloneRefNode.getAttributes().getNamedItem("name").getNodeValue(); - String occName = qdmNode.getAttributes().getNamedItem("instance").getNodeValue(); - cloneRefNode.getAttributes().getNamedItem("name").setNodeValue(occName + "_" + name); - - if (!occurrenceMap.containsKey(occName + occurString)) { - occurrenceMap.remove(occurString); - generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, cloneRefNode, true); - occurrenceMap.put(occurString, refNode); - occurrenceMap.put(occName + occurString, cloneRefNode); - } - - String refRootValue = cloneRefNode.getAttributes().getNamedItem(ID).getNodeValue(); - - String refDatatype = cloneRefNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String refQdmName = cloneRefNode.getAttributes().getNamedItem("name").getNodeValue(); - String reExt = StringUtils.deleteWhitespace(refQdmName + "_" + refDatatype); - - Element outboundRelElem = dataCriteriaElem.getOwnerDocument().createElement("outboundRelationship"); - outboundRelElem.setAttribute("typeCode", "OCCR"); - - Element criteriaRefElem = dataCriteriaElem.getOwnerDocument().createElement("criteriaReference"); - String refClassCodeValue = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); - String refMoodValue = templateNode.getAttributes().getNamedItem(MOOD).getNodeValue(); - criteriaRefElem.setAttribute(CLASS_CODE, refClassCodeValue); - criteriaRefElem.setAttribute(MOOD_CODE, refMoodValue); - - Element idRelElem = dataCriteriaElem.getOwnerDocument().createElement(ID); - idRelElem.setAttribute(ROOT, refRootValue); - idRelElem.setAttribute("extension", reExt); - - criteriaRefElem.appendChild(idRelElem); - outboundRelElem.appendChild(criteriaRefElem); - dataCriteriaElem.appendChild(outboundRelElem); - Node templateIdNode = dataCriteriaElem.getElementsByTagName("templateId").item(0); - dataCriteriaElem.removeChild(templateIdNode); - } - catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - } - - /** - * Add Code Element To data Criteria Element based on condition. - * - * @param templateNode - Node - * @param dataCriteriaXMLProcessor - XmlProcessor - * @param qdmNode the qdm node - * @param dataCriteriaElem - Element - */ - private void addCodeElementToDataCriteriaElement(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, Node qdmNode, Element dataCriteriaElem) { - String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); - - // Patient Characteristic data type - contains code tag with valueSetId - // attribute and no title and value set tag. - boolean isPatientChar = templateNode.getAttributes().getNamedItem("valueSetId") != null; - boolean isAddValueSetInCodeTrue = templateNode.getAttributes().getNamedItem("addValueSetInCode") != null; - boolean isIntervention = "Intervention, Order".equalsIgnoreCase(dataType) - || "Intervention, Performed".equalsIgnoreCase(dataType) - || "Intervention, Recommended".equalsIgnoreCase(dataType) - || "Intervention, Not Ordered".equalsIgnoreCase(dataType) - || "Intervention, Not Performed".equalsIgnoreCase(dataType) - || "Intervention, Not Recommended".equalsIgnoreCase(dataType); - if (isAddValueSetInCodeTrue) { - Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); - if (valueTypeAttr != null) { - codeElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); - } - codeElem.setAttribute("valueSet", qdmOidValue); - addValueSetVersion(qdmNode, codeElem); - dataCriteriaElem.appendChild(codeElem); - - } else if (isPatientChar) { - Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - codeElem.setAttribute(templateNode.getAttributes().getNamedItem("valueSetId").getNodeValue(), qdmOidValue); - addValueSetVersion(qdmNode, codeElem); - dataCriteriaElem.appendChild(codeElem); - } else if (isIntervention) { - Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - codeElem.setAttribute("valueSet", qdmOidValue); - addValueSetVersion(qdmNode, codeElem); - dataCriteriaElem.appendChild(codeElem); - } else { - Element codeElement = createCodeForDatatype(templateNode, dataCriteriaXMLProcessor); - if (codeElement != null) { - dataCriteriaElem.appendChild(codeElement); - } - } - } - - /** - * This method is called for populating version/expansion Identifier of value set when value set attribute - * mode is applied. If version is most recent, 1.0 or 1 is returned. - * @param qdmNode - * @return version - */ - private String valueSetVersionStringValue(Node qdmNode){ - String version = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); - if (!"1.0".equals(version) && !"1".equals(version) && StringUtils.isNotBlank(version)) { - version = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); - } else { - version = null; - } - return version; - } - /** - * Add SubTemplate defined in Template.xml to data criteria Element. - * - * @param templateNode - Node - * @param dataCriteriaXMLProcessor - XmlProcessor for Data Criteria - * @param templateXMLProcessor -XmlProcessor for Template Xml. - * @param dataCriteriaElem - Element - * @param qdmNode the qdm node - * @throws XPathExpressionException the x path expression exception - */ - private void appendSubTemplateNode(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, XmlProcessor templateXMLProcessor, - Element dataCriteriaElem, Node qdmNode) throws XPathExpressionException { - String subTemplateName = templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); - Node subTemplateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), "/templates/subtemplates/" + subTemplateName); - NodeList subTemplateNodeChilds = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), "/templates/subtemplates/" + subTemplateName + "/child::node()"); - String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); - String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); - String qdmNameDataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String qdmTaxonomy = qdmNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); - - if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { - String[] attributeToBeModified = subTemplateNode.getAttributes().getNamedItem("changeAttribute").getNodeValue().split(","); - for (String changeAttribute : attributeToBeModified) { - NodeList attributedToBeChangedInNode = null; - attributedToBeChangedInNode = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); - if (changeAttribute.equalsIgnoreCase(ID)) { - String rootId = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("root").setNodeValue(rootId); - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("extension").setNodeValue(java.util.UUID.randomUUID().toString()); - } else if (changeAttribute.equalsIgnoreCase(CODE)) { - if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("code") != null) { - attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("code"); - } - - if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("codeSystem") != null) { - attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("codeSystem"); - } - - if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("codeSystemName") != null) { - attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("codeSystemName"); - } - - if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("codeSystemVersion") != null) { - attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("codeSystemVersion"); - } - - if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("valueSetVersion") != null) { - attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("valueSetVersion"); - } - - Attr attrNodeValueSet = attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("valueSet"); - attrNodeValueSet.setNodeValue(qdmOidValue); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attrNodeValueSet); - String valueSetVersion = valueSetVersionStringValue(qdmNode); - - if (valueSetVersion != null) { - Attr attrNode = attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("valueSetVersion"); - attrNode.setNodeValue(valueSetVersion); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attrNode); - } - - } else if (changeAttribute.equalsIgnoreCase(DISPLAY_NAME)) { - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("value").setNodeValue(HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + " " + qdmTaxonomy + " value set"); - } else if (changeAttribute.equalsIgnoreCase(TITLE)) { - attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("value").setNodeValue(qdmNameDataType); - } else if (changeAttribute.equalsIgnoreCase(ITEM)) { - for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { - Node itemNode = attributedToBeChangedInNode.item(count); - itemNode.getAttributes().getNamedItem("extension").setNodeValue(extensionValue); - } - - } else if (changeAttribute.equalsIgnoreCase("value")) { - Attr attrNode = attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("valueSet"); - attrNode.setNodeValue(qdmOidValue); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attrNode); - - } - - } - } - - for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { - Node childNode = subTemplateNodeChilds.item(i); - Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); - XmlProcessor.clean(nodeToAttach); - dataCriteriaElem.appendChild(nodeToAttach); - } - } - - - /** - * Adds the data criteria comment. - * - * @param dataCriteriaXMLProcessor the data criteria xml processor - */ - private void addDataCriteriaComment(XmlProcessor dataCriteriaXMLProcessor) { - Element element = dataCriteriaXMLProcessor.getOriginalDoc().getDocumentElement(); - Comment comment = dataCriteriaXMLProcessor.getOriginalDoc().createComment( - "Data Criteria Section"); - element.getParentNode().insertBefore(comment, element); - } - - /** - * Creates the code for datatype. - * - * @param templateNode the template node - * @param dataCriteriaXMLProcessor the data criteria xml processor - * @return the element - */ - protected Element createCodeForDatatype(Node templateNode, XmlProcessor dataCriteriaXMLProcessor) { - Node codeAttr = templateNode.getAttributes().getNamedItem(CODE); - Node codeSystemAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM); - Node codeSystemNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_NAME); - Node codeDisplayNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_DISPLAY_NAME); - Element codeElement = null; - if (codeAttr != null || codeSystemAttr != null || codeSystemNameAttr != null - || codeDisplayNameAttr != null) { - codeElement = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - if (codeAttr != null) { - codeElement.setAttribute(CODE, codeAttr.getNodeValue()); - } - if (codeSystemAttr != null) { - codeElement.setAttribute(CODE_SYSTEM, codeSystemAttr.getNodeValue()); - } - if (codeSystemNameAttr != null) { - codeElement.setAttribute(CODE_SYSTEM_NAME, codeSystemNameAttr.getNodeValue()); - } - if (codeDisplayNameAttr != null) { - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - displayNameElem.setAttribute(VALUE, codeDisplayNameAttr.getNodeValue()); - codeElement.appendChild(displayNameElem); - } - } - return codeElement; - } -} + private static final String DATA_CRITERIA_EXTENSION = "2021-02-01"; + + /** The occurrence map. */ + private Map occurrenceMap = new HashMap<>(); + + protected String extensionValue = null; + + /** The Constant logger. */ + private static final Logger logger = + LoggerFactory.getLogger(HQMFDataCriteriaElementGenerator.class); + + /** + * Generate hqm for measure. + * + * @param me the me + * @return the string + */ + @Override + public String generate(MeasureExport me) { + getExtensionValueBasedOnVersion(me); + XmlProcessor dataCriteriaXMLProcessor = createDateCriteriaTemplate(); + me.setHqmfXmlProcessor(dataCriteriaXMLProcessor); + + String simpleXMLStr = me.getSimpleXml(); + XmlProcessor simpleXmlprocessor = new XmlProcessor(simpleXMLStr); + me.setSimpleXmlProcessor(simpleXmlprocessor); + + createDataCriteriaForQDMELements(me, dataCriteriaXMLProcessor, simpleXmlprocessor); + addDataCriteriaComment(dataCriteriaXMLProcessor); + return dataCriteriaXMLProcessor.transform(dataCriteriaXMLProcessor.getOriginalDoc(), true); + } + + /** + * Creates the date criteria template. + * + * @return the string + */ + private XmlProcessor createDateCriteriaTemplate() { + XmlProcessor outputProcessor = + new XmlProcessor( + ""); + + Node dataCriteriaElem = + outputProcessor.getOriginalDoc().getElementsByTagName("dataCriteriaSection").item(0); + Element templateId = outputProcessor.getOriginalDoc().createElement(TEMPLATE_ID); + dataCriteriaElem.appendChild(templateId); + Element itemChild = outputProcessor.getOriginalDoc().createElement(ITEM); + itemChild.setAttribute(ROOT, "2.16.840.1.113883.10.20.28.2.6"); + // itemChild.setAttribute("extension", getDataCriteriaExtValueBasedOnVersion(me)); + itemChild.setAttribute("extension", DATA_CRITERIA_EXTENSION); + templateId.appendChild(itemChild); + // creating Code Element for DataCriteria + Element codeElem = outputProcessor.getOriginalDoc().createElement(CODE); + codeElem.setAttribute(CODE, "57025-9"); + codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.6.1"); + dataCriteriaElem.appendChild(codeElem); + // creating title for DataCriteria + Element titleElem = outputProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, "Data Criteria Section"); + dataCriteriaElem.appendChild(titleElem); + // creating text for DataCriteria + Element textElem = outputProcessor.getOriginalDoc().createElement("text"); + dataCriteriaElem.appendChild(textElem); + + return outputProcessor; + } + + private String getDataCriteriaExtValueBasedOnVersion() { + return VERSION_5_0_ID; + } + + /** + * Creates the data criteria for qdm elements. + * + * @param me the me + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + */ + private void createDataCriteriaForQDMELements( + MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor) { + String xPathForQDMNoAttribs = "/measure/elementLookUp/qdm[@datatype and @code ='false']"; + String xpathForOtherSupplementalQDMs = "/measure/supplementalDataElements/elementRef/@id"; + String xpathForMeasureGroupingItemCount = "/measure//itemCount/elementRef/@id"; + + try { + NodeList qdmNoAttributeNodeList = + simpleXmlprocessor.findNodeList( + simpleXmlprocessor.getOriginalDoc(), xPathForQDMNoAttribs); + generateCQLQDMNodeEntries( + dataCriteriaXMLProcessor, simpleXmlprocessor, qdmNoAttributeNodeList); + + HQMFDataCriteriaElementGeneratorForCodes cqlBasedHQMFDataCriteriaElementGeneratorForCodes = + new HQMFDataCriteriaElementGeneratorForCodes(); + cqlBasedHQMFDataCriteriaElementGeneratorForCodes.generate(me); + + // generating QDM Entries for other Supplemental Data Elements + NodeList supplementalDataElements = + me.getSimpleXmlProcessor() + .findNodeList( + me.getSimpleXmlProcessor().getOriginalDoc(), xpathForOtherSupplementalQDMs); + generateOtherSupplementalDataQDMEntries( + me, dataCriteriaXMLProcessor, supplementalDataElements); + + // generating QDM entries for measureGrouping ItemCountlist + NodeList measureGroupingItemCountList = + simpleXmlprocessor.findNodeList( + simpleXmlprocessor.getOriginalDoc(), xpathForMeasureGroupingItemCount); + generateMeasureGrpnItemCountQDMEntries( + me, dataCriteriaXMLProcessor, measureGroupingItemCountList); + + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + + protected void getExtensionValueBasedOnVersion(MeasureExport me) { + if (me != null) { + extensionValue = getDataCriteriaExtValueBasedOnVersion(); + } + } + + /** + * Generate measure grp item count qdm entries. + * + * @param me the me + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param measureGroupingItemCountList the measure grouping item count list + * @throws XPathExpressionException the x path expression exception + */ + private void generateMeasureGrpnItemCountQDMEntries( + MeasureExport me, + XmlProcessor dataCriteriaXMLProcessor, + NodeList measureGroupingItemCountList) + throws XPathExpressionException { + + if (measureGroupingItemCountList == null || measureGroupingItemCountList.getLength() < 1) { + return; + } + List itemCountIDList = new ArrayList(); + for (int i = 0; i < measureGroupingItemCountList.getLength(); i++) { + if (!itemCountIDList.contains(measureGroupingItemCountList.item(i).getNodeValue())) { + itemCountIDList.add(measureGroupingItemCountList.item(i).getNodeValue()); + } + } + String xpathforElementLookUpElements = + "/measure/elementLookUp/qdm[" + getUUIDString(itemCountIDList) + "]"; + + NodeList measureGroupingElementRefNodeList = + me.getSimpleXmlProcessor() + .findNodeList( + me.getSimpleXmlProcessor().getOriginalDoc(), xpathforElementLookUpElements); + generateItemCountQDMEntries(me, dataCriteriaXMLProcessor, measureGroupingElementRefNodeList); + } + + /** + * Generate supplemental data qdm entries. + * + * @param me the me + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param supplementalDataElements the supplemental data elements + * @throws XPathExpressionException the x path expression exception + */ + private void generateOtherSupplementalDataQDMEntries( + MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, NodeList supplementalDataElements) + throws XPathExpressionException { + if (supplementalDataElements == null || supplementalDataElements.getLength() < 1) { + return; + } + List supplementalElemenRefIds = new ArrayList(); + for (int i = 0; i < supplementalDataElements.getLength(); i++) { + supplementalElemenRefIds.add(supplementalDataElements.item(i).getNodeValue()); + } + + String xpathforOtherSupplementalDataElements = + "/measure/elementLookUp/qdm[" + + getUUIDString(supplementalElemenRefIds) + + "][@suppDataElement != 'true']"; + NodeList otherSupplementalQDMNodeList = + me.getSimpleXmlProcessor() + .findNodeList( + me.getSimpleXmlProcessor().getOriginalDoc(), xpathforOtherSupplementalDataElements); + + generateSupplementalDataQDMEntries(me, dataCriteriaXMLProcessor, otherSupplementalQDMNodeList); + } + + /** + * Generate supplemental data qdm entries. + * + * @param me the me + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param qdmNodeList the qdm node list + * @throws XPathExpressionException the x path expression exception + */ + private void generateSupplementalDataQDMEntries( + MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, NodeList qdmNodeList) + throws XPathExpressionException { + for (int j = 0; j < qdmNodeList.getLength(); j++) { + Node qdmNode = qdmNodeList.item(j); + String qdmName = qdmNode.getAttributes().getNamedItem("name").getNodeValue(); + String qdmDatatype = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmUUID = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); + String qdmExtension = qdmName.replaceAll("\\s", "") + "_" + qdmDatatype.replaceAll("\\s", ""); + String xpathForQDMEntry = + "/root/component/dataCriteriaSection/entry/*/id[@root='" + + qdmUUID + + "'][@extension=\"" + + qdmExtension + + "\"]"; + Node qmdEntryIDNode = + dataCriteriaXMLProcessor.findNode( + dataCriteriaXMLProcessor.getOriginalDoc(), xpathForQDMEntry); + if (qmdEntryIDNode == null) { + createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, me.getSimpleXmlProcessor()); + } + } + } + + /** + * Generate Item Count qdm entries. + * + * @param me the me + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param qdmNodeList the qdm node list + * @throws XPathExpressionException the x path expression exception + */ + private void generateItemCountQDMEntries( + MeasureExport me, XmlProcessor dataCriteriaXMLProcessor, NodeList qdmNodeList) + throws XPathExpressionException { + for (int j = 0; j < qdmNodeList.getLength(); j++) { + Node qdmNode = qdmNodeList.item(j); + String qdmName = qdmNode.getAttributes().getNamedItem("name").getNodeValue(); + String qdmDatatype = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmUUID = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); + String qdmExtension = qdmName.replaceAll("\\s", "") + "_" + qdmDatatype.replaceAll("\\s", ""); + if (qdmNode.getAttributes().getNamedItem("instance") != null) { + String instanceOfValue = qdmNode.getAttributes().getNamedItem("instance").getNodeValue(); + String newExtension = instanceOfValue.replaceAll("\\s", "") + "_" + qdmExtension; + qdmExtension = newExtension; + } + String xpathForQDMEntry = + "/root/component/dataCriteriaSection/entry/*/id[@root='" + + qdmUUID + + "'][@extension=\"" + + qdmExtension + + "\"]"; + Node qmdEntryIDNode = + dataCriteriaXMLProcessor.findNode( + dataCriteriaXMLProcessor.getOriginalDoc(), xpathForQDMEntry); + if (qmdEntryIDNode == null) { + createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, me.getSimpleXmlProcessor()); + } + } + } + + /** + * Gets the UUID string. + * + * @param uuidList the uuid list + * @return the UUID string + */ + private String getUUIDString(List uuidList) { + String uuidXPathString = ""; + for (String uuidString : uuidList) { + uuidXPathString += "@uuid = '" + uuidString + "' or"; + } + + uuidXPathString = uuidXPathString.substring(0, uuidXPathString.lastIndexOf(" or")); + return uuidXPathString; + } + + private void generateCQLQDMNodeEntries( + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + NodeList qdmNoAttributeNodeList) + throws XPathExpressionException { + + if (qdmNoAttributeNodeList == null) { + return; + } + + for (int i = 0; i < qdmNoAttributeNodeList.getLength(); i++) { + Node qdmNode = qdmNoAttributeNodeList.item(i); + createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor); + } + } + + /** + * Generate qdm entry. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param qdmNode the qdm node + * @param forceGenerate the force generate + * @throws XPathExpressionException the x path expression exception + */ + private void generateQDMEntry( + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + Node qdmNode, + boolean forceGenerate) + throws XPathExpressionException { + String qdmUUID = qdmNode.getAttributes().getNamedItem(UUID).getNodeValue(); + + String xPathForIndividualElementRefs = + "/measure/subTreeLookUp//elementRef[@id='" + qdmUUID + "'][not(attribute)]"; + NodeList elementRefList = + simpleXmlprocessor.findNodeList( + simpleXmlprocessor.getOriginalDoc(), xPathForIndividualElementRefs); + if (forceGenerate || elementRefList.getLength() > 0) { + createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor); + } + } + + /** + * Create xml for data criteria. + * + * @param qdmNode the qdm node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @return void + */ + private void createXmlForDataCriteria( + Node qdmNode, XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor) { + String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(5.6); + String xPathForTemplate = "/templates/template[text()='" + dataType.toLowerCase() + "']"; + String actNodeStr = ""; + try { + + Node templateNode = + templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xPathForTemplate); + if (templateNode != null) { + String attrClass = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); + String xpathForAct = "/templates/acts/act[@a_id='" + attrClass + "']"; + Node actNode = + templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xpathForAct); + if (actNode != null) { + actNodeStr = actNode.getTextContent(); + } + + createDataCriteriaElementTag( + actNodeStr, + templateNode, + qdmNode, + dataCriteriaXMLProcessor, + simpleXmlprocessor, + templateXMLProcessor); + } + + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + + /** + * Gets the creates the data create element tag. + * + * @param actNodeStr the act node str + * @param templateNode the template node + * @param qdmNode the qdm node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + * @param templateXMLProcessor - templateXmlProcessor + * @throws XPathExpressionException the x path expression exception + */ + private void createDataCriteriaElementTag( + String actNodeStr, + Node templateNode, + Node qdmNode, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + XmlProcessor templateXMLProcessor) + throws XPathExpressionException { + String oidValue = templateNode.getAttributes().getNamedItem(OID).getNodeValue(); + String classCodeValue = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); + String moodValue = templateNode.getAttributes().getNamedItem(MOOD).getNodeValue(); + + Node statusNode = templateNode.getAttributes().getNamedItem("status"); + String statusValue = statusNode != null ? statusNode.getNodeValue() : ""; + String rootValue = qdmNode.getAttributes().getNamedItem(ID).getNodeValue(); + String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); + + String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); + Node actionNegInd = templateNode.getAttributes().getNamedItem("actionNegationInd"); + String entryCommentText = dataType; + // Local variable changes. + String qdmLocalVariableName = qdmName + "_" + dataType; + String localVariableName = qdmLocalVariableName; + + qdmLocalVariableName = StringUtils.deleteWhitespace(qdmLocalVariableName); + localVariableName = StringUtils.deleteWhitespace(localVariableName); + + Element dataCriteriaSectionElem = + (Element) + dataCriteriaXMLProcessor + .getOriginalDoc() + .getElementsByTagName("dataCriteriaSection") + .item(0); + Element componentElem = + (Element) + dataCriteriaXMLProcessor.getOriginalDoc().getElementsByTagName("component").item(0); + Attr nameSpaceAttr = dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:xsi"); + nameSpaceAttr.setNodeValue(nameSpace); + componentElem.setAttributeNodeNS(nameSpaceAttr); + Attr qdmNameSpaceAttr = + dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:cql-ext"); + qdmNameSpaceAttr.setNodeValue("urn:hhs-cql:hqmf-n1-extensions:v1"); + componentElem.setAttributeNodeNS(qdmNameSpaceAttr); + // creating Entry Tag + Element entryElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("entry"); + entryElem.setAttribute(TYPE_CODE, "DRIV"); + // Local Variable Name Tag - Inside Entry tag. + Element localVarElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement("localVariableName"); + localVarElem.setAttribute(VALUE, localVariableName + "_" + UUIDUtilClient.uuid(5)); + entryElem.appendChild(localVarElem); + Element dataCriteriaElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(actNodeStr); + entryElem.appendChild(dataCriteriaElem); + dataCriteriaElem.setAttribute(CLASS_CODE, classCodeValue); + dataCriteriaElem.setAttribute(MOOD_CODE, moodValue); + // adding actionNegationInd for Negative Datatypes + if (actionNegInd != null) { + dataCriteriaElem.setAttribute(ACTION_NEGATION_IND, actionNegInd.getNodeValue()); + } + Element templateId = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TEMPLATE_ID); + dataCriteriaElem.appendChild(templateId); + Element itemChild = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); + itemChild.setAttribute(ROOT, oidValue); + if (templateNode.getAttributes().getNamedItem("specificExtensionValue") != null) { + String specificExtensionValue = + templateNode.getAttributes().getNamedItem("specificExtensionValue").getNodeValue(); + itemChild.setAttribute("extension", specificExtensionValue); + } else if (templateNode.getAttributes().getNamedItem("addExtensionInTemplate") == null) { + itemChild.setAttribute("extension", extensionValue); + } + templateId.appendChild(itemChild); + Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); + idElem.setAttribute(ROOT, rootValue); + idElem.setAttribute("extension", qdmLocalVariableName); + dataCriteriaElem.appendChild(idElem); + + boolean appendEntryElem = false; + String occurString = dataType + "-" + qdmOidValue; + + if (qdmNode.getAttributes().getNamedItem("instance") != null) { + generateOutboundForOccur( + templateNode, + qdmNode, + dataCriteriaElem, + occurString, + dataCriteriaXMLProcessor, + simpleXmlprocessor); + entryCommentText = + qdmNode.getAttributes().getNamedItem("instance").getNodeValue() + " " + entryCommentText; + appendEntryElem = true; + } else if (!occurrenceMap.containsKey(occurString) /* || (attributeQDMNode != null) */) { + + String isAddCodeTag = templateNode.getAttributes().getNamedItem("addCodeTag").getNodeValue(); + if ("true".equalsIgnoreCase(isAddCodeTag)) { // Add Code Element to DataCriteria Element. + addCodeElementToDataCriteriaElement( + templateNode, dataCriteriaXMLProcessor, qdmNode, dataCriteriaElem); + } + Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, dataType); + dataCriteriaElem.appendChild(titleElem); + + if (StringUtils.isNotEmpty(statusValue)) { + Element statusCodeElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement("statusCode"); + statusCodeElem.setAttribute(CODE, statusValue); + dataCriteriaElem.appendChild(statusCodeElem); + } + + // Add value tag in entry element. + String addValueSetElement = + templateNode.getAttributes().getNamedItem("addValueTag").getNodeValue(); + if ("true".equalsIgnoreCase(addValueSetElement)) { + Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(VALUE); + Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); + if (valueTypeAttr != null) { + valueElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); + } + + Node valueCodeSystem = templateNode.getAttributes().getNamedItem("valueCodeSystem"); + Node valueCode = templateNode.getAttributes().getNamedItem("valueCode"); + Node valueDisplayName = templateNode.getAttributes().getNamedItem("valueDisplayName"); + Node valueCodeSystemName = templateNode.getAttributes().getNamedItem("valueCodeSystemName"); + if (valueCode != null && valueCodeSystem != null) { + valueElem.setAttribute("code", valueCode.getNodeValue()); + valueElem.setAttribute("codeSystem", valueCodeSystem.getNodeValue()); + if (valueCodeSystemName != null) { + valueElem.setAttribute("codeSystemName", valueCodeSystemName.getNodeValue()); + } + } else { + valueElem.setAttribute("valueSet", qdmOidValue); + addValueSetVersion(qdmNode, valueElem); + } + + dataCriteriaElem.appendChild(valueElem); + } + if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { + appendSubTemplateNode( + templateNode, + dataCriteriaXMLProcessor, + templateXMLProcessor, + dataCriteriaElem, + qdmNode); + } + // checkForAttributes + + appendEntryElem = true; + } + if (appendEntryElem) { + dataCriteriaSectionElem.appendChild(entryElem); + } + } + + /** + * Method to add valueSetVersion attribute in value element tag. + * + * @param qdmNode the qdm node + * @param valueElem the value elem + */ + protected void addValueSetVersion(Node qdmNode, Element valueElem) { + // This is to be commented until we start getting value set versions from VSAC. + boolean addVersionToValueTag = false; + String valueSetVersion = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); + + if ("1.0".equals(valueSetVersion) + || "1".equals(valueSetVersion) + || StringUtils.isBlank(valueSetVersion)) { + addVersionToValueTag = false; + } else { + valueSetVersion = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); + addVersionToValueTag = true; + } + if (addVersionToValueTag) { + valueElem.setAttribute("valueSetVersion", valueSetVersion); + } + } + + /** + * Generate outbound for occur. + * + * @param templateNode the template node + * @param qdmNode the qdm node + * @param dataCriteriaElem the data criteria elem + * @param occurString the occur string + */ + private void generateOutboundForOccur( + Node templateNode, + Node qdmNode, + Element dataCriteriaElem, + String occurString, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor) { + Node refNode = occurrenceMap.get(occurString); + + logger.debug("In generateOutboundForOccur()..refNode:" + refNode); + logger.debug("----------Occurance map:" + occurrenceMap); + + if (refNode != null) { + + try { + Node cloneRefNode = refNode.cloneNode(true); + String name = cloneRefNode.getAttributes().getNamedItem("name").getNodeValue(); + String occName = qdmNode.getAttributes().getNamedItem("instance").getNodeValue(); + cloneRefNode.getAttributes().getNamedItem("name").setNodeValue(occName + "_" + name); + + if (!occurrenceMap.containsKey(occName + occurString)) { + occurrenceMap.remove(occurString); + generateQDMEntry(dataCriteriaXMLProcessor, simpleXmlprocessor, cloneRefNode, true); + occurrenceMap.put(occurString, refNode); + occurrenceMap.put(occName + occurString, cloneRefNode); + } + + String refRootValue = cloneRefNode.getAttributes().getNamedItem(ID).getNodeValue(); + + String refDatatype = cloneRefNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String refQdmName = cloneRefNode.getAttributes().getNamedItem("name").getNodeValue(); + String reExt = StringUtils.deleteWhitespace(refQdmName + "_" + refDatatype); + + Element outboundRelElem = + dataCriteriaElem.getOwnerDocument().createElement("outboundRelationship"); + outboundRelElem.setAttribute("typeCode", "OCCR"); + + Element criteriaRefElem = + dataCriteriaElem.getOwnerDocument().createElement("criteriaReference"); + String refClassCodeValue = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); + String refMoodValue = templateNode.getAttributes().getNamedItem(MOOD).getNodeValue(); + criteriaRefElem.setAttribute(CLASS_CODE, refClassCodeValue); + criteriaRefElem.setAttribute(MOOD_CODE, refMoodValue); + + Element idRelElem = dataCriteriaElem.getOwnerDocument().createElement(ID); + idRelElem.setAttribute(ROOT, refRootValue); + idRelElem.setAttribute("extension", reExt); + + criteriaRefElem.appendChild(idRelElem); + outboundRelElem.appendChild(criteriaRefElem); + dataCriteriaElem.appendChild(outboundRelElem); + Node templateIdNode = dataCriteriaElem.getElementsByTagName("templateId").item(0); + dataCriteriaElem.removeChild(templateIdNode); + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + } + + /** + * Add Code Element To data Criteria Element based on condition. + * + * @param templateNode - Node + * @param dataCriteriaXMLProcessor - XmlProcessor + * @param qdmNode the qdm node + * @param dataCriteriaElem - Element + */ + private void addCodeElementToDataCriteriaElement( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + Node qdmNode, + Element dataCriteriaElem) { + String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); + + // Patient Characteristic data type - contains code tag with valueSetId + // attribute and no title and value set tag. + boolean isPatientChar = templateNode.getAttributes().getNamedItem("valueSetId") != null; + boolean isAddValueSetInCodeTrue = + templateNode.getAttributes().getNamedItem("addValueSetInCode") != null; + boolean isIntervention = + "Intervention, Order".equalsIgnoreCase(dataType) + || "Intervention, Performed".equalsIgnoreCase(dataType) + || "Intervention, Recommended".equalsIgnoreCase(dataType) + || "Intervention, Not Ordered".equalsIgnoreCase(dataType) + || "Intervention, Not Performed".equalsIgnoreCase(dataType) + || "Intervention, Not Recommended".equalsIgnoreCase(dataType); + if (isAddValueSetInCodeTrue) { + Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); + if (valueTypeAttr != null) { + codeElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); + } + codeElem.setAttribute("valueSet", qdmOidValue); + addValueSetVersion(qdmNode, codeElem); + dataCriteriaElem.appendChild(codeElem); + + } else if (isPatientChar) { + Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + codeElem.setAttribute( + templateNode.getAttributes().getNamedItem("valueSetId").getNodeValue(), qdmOidValue); + addValueSetVersion(qdmNode, codeElem); + dataCriteriaElem.appendChild(codeElem); + } else if (isIntervention) { + Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + codeElem.setAttribute("valueSet", qdmOidValue); + addValueSetVersion(qdmNode, codeElem); + dataCriteriaElem.appendChild(codeElem); + } else { + Element codeElement = createCodeForDatatype(templateNode, dataCriteriaXMLProcessor); + if (codeElement != null) { + dataCriteriaElem.appendChild(codeElement); + } + } + } + + /** + * This method is called for populating version/expansion Identifier of value set when value set + * attribute mode is applied. If version is most recent, 1.0 or 1 is returned. + * + * @param qdmNode + * @return version + */ + private String valueSetVersionStringValue(Node qdmNode) { + String version = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); + if (!"1.0".equals(version) && !"1".equals(version) && StringUtils.isNotBlank(version)) { + version = qdmNode.getAttributes().getNamedItem("version").getNodeValue(); + } else { + version = null; + } + return version; + } + + /** + * Add SubTemplate defined in Template.xml to data criteria Element. + * + * @param templateNode - Node + * @param dataCriteriaXMLProcessor - XmlProcessor for Data Criteria + * @param templateXMLProcessor -XmlProcessor for Template Xml. + * @param dataCriteriaElem - Element + * @param qdmNode the qdm node + * @throws XPathExpressionException the x path expression exception + */ + private void appendSubTemplateNode( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor templateXMLProcessor, + Element dataCriteriaElem, + Node qdmNode) + throws XPathExpressionException { + String subTemplateName = + templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); + Node subTemplateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), "/templates/subtemplates/" + subTemplateName); + NodeList subTemplateNodeChilds = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "/child::node()"); + String qdmOidValue = qdmNode.getAttributes().getNamedItem(OID).getNodeValue(); + String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); + String qdmNameDataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmTaxonomy = qdmNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); + + if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { + String[] attributeToBeModified = + subTemplateNode.getAttributes().getNamedItem("changeAttribute").getNodeValue().split(","); + for (String changeAttribute : attributeToBeModified) { + NodeList attributedToBeChangedInNode = null; + attributedToBeChangedInNode = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); + if (changeAttribute.equalsIgnoreCase(ID)) { + String rootId = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("root") + .setNodeValue(rootId); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("extension") + .setNodeValue(java.util.UUID.randomUUID().toString()); + } else if (changeAttribute.equalsIgnoreCase(CODE)) { + if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("code") != null) { + attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("code"); + } + + if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("codeSystem") + != null) { + attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("codeSystem"); + } + + if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("codeSystemName") + != null) { + attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("codeSystemName"); + } + + if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("codeSystemVersion") + != null) { + attributedToBeChangedInNode + .item(0) + .getAttributes() + .removeNamedItem("codeSystemVersion"); + } + + if (attributedToBeChangedInNode.item(0).getAttributes().getNamedItem("valueSetVersion") + != null) { + attributedToBeChangedInNode.item(0).getAttributes().removeNamedItem("valueSetVersion"); + } + + Attr attrNodeValueSet = + attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("valueSet"); + attrNodeValueSet.setNodeValue(qdmOidValue); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attrNodeValueSet); + String valueSetVersion = valueSetVersionStringValue(qdmNode); + + if (valueSetVersion != null) { + Attr attrNode = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createAttribute("valueSetVersion"); + attrNode.setNodeValue(valueSetVersion); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attrNode); + } + + } else if (changeAttribute.equalsIgnoreCase(DISPLAY_NAME)) { + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("value") + .setNodeValue( + HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + + " " + + qdmTaxonomy + + " value set"); + } else if (changeAttribute.equalsIgnoreCase(TITLE)) { + attributedToBeChangedInNode + .item(0) + .getAttributes() + .getNamedItem("value") + .setNodeValue(qdmNameDataType); + } else if (changeAttribute.equalsIgnoreCase(ITEM)) { + for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { + Node itemNode = attributedToBeChangedInNode.item(count); + itemNode.getAttributes().getNamedItem("extension").setNodeValue(extensionValue); + } + + } else if (changeAttribute.equalsIgnoreCase("value")) { + Attr attrNode = + attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("valueSet"); + attrNode.setNodeValue(qdmOidValue); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(attrNode); + } + } + } + + for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { + Node childNode = subTemplateNodeChilds.item(i); + Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); + XmlProcessor.clean(nodeToAttach); + dataCriteriaElem.appendChild(nodeToAttach); + } + } + + /** + * Adds the data criteria comment. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + */ + private void addDataCriteriaComment(XmlProcessor dataCriteriaXMLProcessor) { + Element element = dataCriteriaXMLProcessor.getOriginalDoc().getDocumentElement(); + Comment comment = + dataCriteriaXMLProcessor.getOriginalDoc().createComment("Data Criteria Section"); + element.getParentNode().insertBefore(comment, element); + } + + /** + * Creates the code for datatype. + * + * @param templateNode the template node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @return the element + */ + protected Element createCodeForDatatype( + Node templateNode, XmlProcessor dataCriteriaXMLProcessor) { + Node codeAttr = templateNode.getAttributes().getNamedItem(CODE); + Node codeSystemAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM); + Node codeSystemNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_NAME); + Node codeDisplayNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_DISPLAY_NAME); + Element codeElement = null; + if (codeAttr != null + || codeSystemAttr != null + || codeSystemNameAttr != null + || codeDisplayNameAttr != null) { + codeElement = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + if (codeAttr != null) { + codeElement.setAttribute(CODE, codeAttr.getNodeValue()); + } + if (codeSystemAttr != null) { + codeElement.setAttribute(CODE_SYSTEM, codeSystemAttr.getNodeValue()); + } + if (codeSystemNameAttr != null) { + codeElement.setAttribute(CODE_SYSTEM_NAME, codeSystemNameAttr.getNodeValue()); + } + if (codeDisplayNameAttr != null) { + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + displayNameElem.setAttribute(VALUE, codeDisplayNameAttr.getNodeValue()); + codeElement.appendChild(displayNameElem); + } + } + return codeElement; + } +} diff --git a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaElementGeneratorForCodes.java b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaElementGeneratorForCodes.java index 1898cd1..7d80dfb 100644 --- a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaElementGeneratorForCodes.java +++ b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaElementGeneratorForCodes.java @@ -1,4 +1,3 @@ - package gov.cms.madie.hqmf.qdm_5_6; import gov.cms.madie.hqmf.Generator; @@ -13,521 +12,551 @@ import javax.xml.xpath.XPathExpressionException; -/** - * The Class CQLBasedHQMFDataCriteriaElementGenerator. - */ +/** The Class CQLBasedHQMFDataCriteriaElementGenerator. */ public class HQMFDataCriteriaElementGeneratorForCodes implements Generator { - protected String extensionValue = null; - - /** - * Generate hqm for measure. - * - * @param me - * the me - * @return the string - */ - @Override - public String generate(MeasureExport me) { - getExtensionValueBasedOnVersion(me); - XmlProcessor dataCriteriaXMLProcessor = me.getHqmfXmlProcessor(); - - createDataCriteriaForQDMELements(dataCriteriaXMLProcessor, me.getSimpleXmlProcessor()); - return dataCriteriaXMLProcessor.transform(dataCriteriaXMLProcessor.getOriginalDoc(), true); - } - - private String getDataCriteriaExtValueBasedOnVersion(MeasureExport me) { - // TODO: get rid of the parameter - even better, get rid of this method and use the constant! - return VERSION_5_0_ID; - } - - /** - * Creates the data criteria for qdm elements. - * - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - */ - private void createDataCriteriaForQDMELements(XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor simpleXmlprocessor) { - - String xPathForDirectReferenceCodes = "/measure/elementLookUp/qdm[@datatype and @code ='true']"; - - try { - NodeList directReferenceCodeNodeList = simpleXmlprocessor.findNodeList(simpleXmlprocessor.getOriginalDoc(), - xPathForDirectReferenceCodes); - generateCQLDRCNodeEntries(dataCriteriaXMLProcessor, simpleXmlprocessor, directReferenceCodeNodeList); - - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - - protected void getExtensionValueBasedOnVersion(MeasureExport me) { - // TODO: get rid of this function too...boil up the constant - if (me != null) { - extensionValue = getDataCriteriaExtValueBasedOnVersion(me); - } - } - - private void generateCQLDRCNodeEntries(XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor, - NodeList qdmNoAttributeNodeList) throws XPathExpressionException { - - if (qdmNoAttributeNodeList == null) { - return; - } - - for (int i = 0; i < qdmNoAttributeNodeList.getLength(); i++) { - Node qdmNode = qdmNoAttributeNodeList.item(i); - createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor); - } - } - - /** - * Create xml for data criteria. - * - * @param qdmNode - * the qdm node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param simpleXmlprocessor - * the simple xmlprocessor - */ - private void createXmlForDataCriteria(Node qdmNode, XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor simpleXmlprocessor) { - String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(5.6); - String xPathForTemplate = "/templates/template[text()='" + dataType.toLowerCase() + "']"; - String actNodeStr = ""; - try { - - Node templateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xPathForTemplate); - if (templateNode != null) { - String attrClass = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); - String xpathForAct = "/templates/acts/act[@a_id='" + attrClass + "']"; - Node actNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xpathForAct); - if (actNode != null) { - actNodeStr = actNode.getTextContent(); - } - - createDataCriteriaElementTag(actNodeStr, templateNode, qdmNode, dataCriteriaXMLProcessor, - templateXMLProcessor); - } - - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - - /** - * Gets the creates the data create element tag. - * - * @param actNodeStr - * the act node str - * @param templateNode - * the template node - * @param qdmNode - * the qdm node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @param templateXMLProcessor - * - templateXmlProcessor - * @throws XPathExpressionException - * the x path expression exception - */ - private void createDataCriteriaElementTag(String actNodeStr, - Node templateNode, - Node qdmNode, - XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor templateXMLProcessor) - throws XPathExpressionException { - String oidValue = templateNode.getAttributes().getNamedItem(OID).getNodeValue(); - String classCodeValue = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); - String moodValue = templateNode.getAttributes().getNamedItem(MOOD).getNodeValue(); - Node statusNode= templateNode.getAttributes().getNamedItem("status"); - String statusValue = statusNode != null ? statusNode.getNodeValue() : ""; - String rootValue = qdmNode.getAttributes().getNamedItem(ID).getNodeValue(); - String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - - Node actionNegInd = templateNode.getAttributes().getNamedItem("actionNegationInd"); - String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); - // Stan wants to generate unique id ( extension and root combination - // which is different from Value set). - String qdmLocalVariableName = codeOID + "_" + dataType; - - qdmLocalVariableName = StringUtils.deleteWhitespace(qdmLocalVariableName); - - Element dataCriteriaSectionElem = (Element) dataCriteriaXMLProcessor.getOriginalDoc() - .getElementsByTagName("dataCriteriaSection").item(0); - Element componentElem = (Element) dataCriteriaXMLProcessor.getOriginalDoc().getElementsByTagName("component") - .item(0); - Attr nameSpaceAttr = dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:xsi"); - nameSpaceAttr.setNodeValue(nameSpace); - componentElem.setAttributeNodeNS(nameSpaceAttr); - // xmlns:qdm="urn:hhs-qdm:hqmf-r2-extensions:v1" - Attr qdmNameSpaceAttr = dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:cql-ext"); - qdmNameSpaceAttr.setNodeValue("urn:hhs-cql:hqmf-n1-extensions:v1"); - componentElem.setAttributeNodeNS(qdmNameSpaceAttr); - // creating Entry Tag - Element entryElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("entry"); - entryElem.setAttribute(TYPE_CODE, "DRIV"); - - - Element dataCriteriaElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(actNodeStr); - entryElem.appendChild(dataCriteriaElem); - dataCriteriaElem.setAttribute(CLASS_CODE, classCodeValue); - dataCriteriaElem.setAttribute(MOOD_CODE, moodValue); - // adding actionNegationInd for Negative Datatypes - if (actionNegInd != null) { - dataCriteriaElem.setAttribute(ACTION_NEGATION_IND, actionNegInd.getNodeValue()); - } - Element templateId = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TEMPLATE_ID); - dataCriteriaElem.appendChild(templateId); - Element itemChild = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); - itemChild.setAttribute(ROOT, oidValue); - if(templateNode.getAttributes().getNamedItem("specificExtensionValue") != null){ - String specificExtensionValue = templateNode.getAttributes().getNamedItem("specificExtensionValue").getNodeValue(); - itemChild.setAttribute("extension", specificExtensionValue); - } - else if (templateNode.getAttributes().getNamedItem("addExtensionInTemplate") == null) { - itemChild.setAttribute("extension", extensionValue); - } - templateId.appendChild(itemChild); - Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); - idElem.setAttribute(ROOT, rootValue); - idElem.setAttribute("extension", qdmLocalVariableName); - dataCriteriaElem.appendChild(idElem); - - //boolean appendEntryElem = false; - - String isAddCodeTag = templateNode.getAttributes().getNamedItem("addCodeTag").getNodeValue(); - if ("true".equalsIgnoreCase(isAddCodeTag)) { // Add Code Element to - // DataCriteria Element. - addCodeElementToDataCriteriaElement(templateNode, dataCriteriaXMLProcessor, qdmNode, dataCriteriaElem); - } - Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); - titleElem.setAttribute(VALUE, dataType); - dataCriteriaElem.appendChild(titleElem); - if(StringUtils.isNotEmpty(statusValue)) { - Element statusCodeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("statusCode"); - statusCodeElem.setAttribute(CODE, statusValue); - dataCriteriaElem.appendChild(statusCodeElem); - } - - // Add value tag in entry element. - String addValueSetElement = templateNode.getAttributes().getNamedItem("addValueTag").getNodeValue(); - if ("true".equalsIgnoreCase(addValueSetElement)) { - Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(VALUE); - - Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); - if (valueTypeAttr != null) { - valueElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); - } - - Node valueCodeSystem = templateNode.getAttributes().getNamedItem("valueCodeSystem"); - Node valueCode = templateNode.getAttributes().getNamedItem("valueCode"); - Node valueCodeSystemName = templateNode.getAttributes().getNamedItem("valueCodeSystemName"); - - if (valueCode != null && valueCodeSystem != null) { - valueElem.setAttribute("code", valueCode.getNodeValue()); - valueElem.setAttribute("codeSystem", valueCodeSystem.getNodeValue()); - if (valueCodeSystemName != null) { - valueElem.setAttribute("codeSystemName", valueCodeSystemName.getNodeValue()); - } - } else { - String codeSystemOID = qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); - String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); - String codeSystemVersion = qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); - valueElem.setAttribute("code", codeOID); - valueElem.setAttribute("codeSystem", codeSystemOID); - valueElem.setAttribute("codeSystemName", codeSystemName); - - setCodeSystemVersion(qdmNode, valueElem, codeSystemVersion); - } - - dataCriteriaElem.appendChild(valueElem); - } - if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { - appendSubTemplateNode(templateNode, dataCriteriaXMLProcessor, templateXMLProcessor, dataCriteriaElem, - qdmNode); - } - - dataCriteriaSectionElem.appendChild(entryElem); - } - - - private void setCodeSystemVersion(Node qdmNode, Element valueElem, String codeSystemVersion) { - Node isCodeSystemVersionIncludedNode = qdmNode.getAttributes().getNamedItem("isCodeSystemVersionIncluded"); - boolean isCodeSystemVersionIncluded = true; - if(isCodeSystemVersionIncludedNode != null) { - isCodeSystemVersionIncluded = Boolean.parseBoolean(isCodeSystemVersionIncludedNode.getNodeValue()); - } - if(isCodeSystemVersionIncluded) { - valueElem.setAttribute("codeSystemVersion", codeSystemVersion); - } - } - - /** - * Add Code Element To data Criteria Element based on condition. - * - * @param templateNode - * - Node - * @param dataCriteriaXMLProcessor - * - XmlProcessor - * @param qdmNode - * the qdm node - * @param dataCriteriaElem - * - Element - */ - private void addCodeElementToDataCriteriaElement(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, - Node qdmNode, Element dataCriteriaElem) { - String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - - - // Patient Characteristic data type - contains code tag with valueSetId - // attribute and no title and value set tag. - boolean isPatientChar = templateNode.getAttributes().getNamedItem("valueSetId") != null; - boolean isAddValueSetInCodeTrue = templateNode.getAttributes().getNamedItem("addValueSetInCode") != null; - boolean isIntervention = "Intervention, Order".equalsIgnoreCase(dataType) - || "Intervention, Performed".equalsIgnoreCase(dataType) - || "Intervention, Recommended".equalsIgnoreCase(dataType) - || "Intervention, Not Ordered".equalsIgnoreCase(dataType) - || "Intervention, Not Performed".equalsIgnoreCase(dataType) - || "Intervention, Not Recommended".equalsIgnoreCase(dataType); - if (isAddValueSetInCodeTrue) { - Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); - if (valueTypeAttr != null) { - codeElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); - } - String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); - String codeSystemOID = qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); - String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); - String codeSystemVersion = qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); - - codeElem.setAttribute("code", codeOID); - codeElem.setAttribute("codeSystem", codeSystemOID); - codeElem.setAttribute("codeSystemName", codeSystemName); - setCodeSystemVersion(qdmNode, codeElem, codeSystemVersion); - - dataCriteriaElem.appendChild(codeElem); - - } else if (isPatientChar) { - Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - - String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); - String codeSystemOID = qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); - String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); - String codeSystemVersion = qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); - - codeElem.setAttribute("code", codeOID); - codeElem.setAttribute("codeSystem", codeSystemOID); - codeElem.setAttribute("codeSystemName", codeSystemName); - setCodeSystemVersion(qdmNode, codeElem, codeSystemVersion); - dataCriteriaElem.appendChild(codeElem); - } else if (isIntervention) { - Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); - String codeSystemOID = qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); - String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); - String codeSystemVersion = qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); - - codeElem.setAttribute("code", codeOID); - codeElem.setAttribute("codeSystem", codeSystemOID); - codeElem.setAttribute("codeSystemName", codeSystemName); - setCodeSystemVersion(qdmNode, codeElem, codeSystemVersion); - dataCriteriaElem.appendChild(codeElem); - } else { - Element codeElement = createCodeForDatatype(templateNode, dataCriteriaXMLProcessor); - if (codeElement != null) { - dataCriteriaElem.appendChild(codeElement); - } - } - } - - - /** - * Add SubTemplate defined in Template.xml to data criteria Element. - * - * @param templateNode - * - Node - * @param dataCriteriaXMLProcessor - * - XmlProcessor for Data Criteria - * @param templateXMLProcessor - * -XmlProcessor for Template Xml. - * @param dataCriteriaElem - * - Element - * @param qdmNode - * the qdm node - * @throws XPathExpressionException - * the x path expression exception - */ - private void appendSubTemplateNode(Node templateNode, XmlProcessor dataCriteriaXMLProcessor, - XmlProcessor templateXMLProcessor, Element dataCriteriaElem, Node qdmNode) throws XPathExpressionException { - String subTemplateName = templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); - Node subTemplateNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName); - String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); - String qdmNameDataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String qdmTaxonomy = qdmNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); - NodeList subTemplateNodeChilds = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), "/templates/subtemplates/" - + subTemplateName + "/child::node()"); - - if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { - String[] attributeToBeModified = subTemplateNode.getAttributes().getNamedItem("changeAttribute") - .getNodeValue().split(","); - - - - for (String changeAttribute : attributeToBeModified) { - NodeList attributedToBeChangedInNode; - attributedToBeChangedInNode = templateXMLProcessor.findNodeList(templateXMLProcessor.getOriginalDoc(), - "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); - - if (changeAttribute.equalsIgnoreCase(ID)) { - String rootId = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); - - Node clonedNode = attributedToBeChangedInNode.item(0).cloneNode(true); - clonedNode.getAttributes().getNamedItem("root").setNodeValue(rootId); - clonedNode.getAttributes().getNamedItem("extension").setNodeValue(java.util.UUID.randomUUID().toString()); - - replaceParentNodeWithClonedNode(attributedToBeChangedInNode.item(0), clonedNode); - } else if (changeAttribute.equalsIgnoreCase(CODE)) { - String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); - String codeSystemOID = qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); - String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); - String codeSystemVersion = qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); - Node isCodeSystemVersionIncludedNode = qdmNode.getAttributes().getNamedItem("isCodeSystemVersionIncluded"); - boolean isCodeSystemVersionIncluded = true; - if(isCodeSystemVersionIncludedNode != null) { - isCodeSystemVersionIncluded = Boolean.parseBoolean(isCodeSystemVersionIncludedNode.getNodeValue()); - } - - Node clonedNode = attributedToBeChangedInNode.item(0).cloneNode(true); - - if (clonedNode.getAttributes() - .getNamedItem("valueSetVersion") != null) { - clonedNode.getAttributes().removeNamedItem("valueSetVersion"); - } - - if (clonedNode.getAttributes().getNamedItem("valueSet") != null) { - clonedNode.getAttributes().removeNamedItem("valueSet"); - } - - Attr attrNodeCode = clonedNode.getOwnerDocument().createAttribute("code"); - attrNodeCode.setNodeValue(codeOID); - clonedNode.getAttributes().setNamedItem(attrNodeCode); - - Attr attrNodeCodeSystem = clonedNode.getOwnerDocument().createAttribute("codeSystem"); - attrNodeCodeSystem.setNodeValue(codeSystemOID); - clonedNode.getAttributes().setNamedItem(attrNodeCodeSystem); - - Attr attrNodeCodeSystemName = clonedNode.getOwnerDocument().createAttribute("codeSystemName"); - attrNodeCodeSystemName.setNodeValue(codeSystemName); - clonedNode.getAttributes().setNamedItem(attrNodeCodeSystemName); - - if(isCodeSystemVersionIncluded) { - Attr attrNodeCodeSystemVersion = clonedNode.getOwnerDocument().createAttribute("codeSystemVersion"); - attrNodeCodeSystemVersion.setNodeValue(codeSystemVersion); - clonedNode.getAttributes().setNamedItem(attrNodeCodeSystemVersion); - } - replaceParentNodeWithClonedNode(attributedToBeChangedInNode.item(0), clonedNode); - } else if (changeAttribute.equalsIgnoreCase(DISPLAY_NAME)) { - Node clonedNode = attributedToBeChangedInNode.item(0).cloneNode(true); - clonedNode.getAttributes().getNamedItem("value").setNodeValue(HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + " " + qdmTaxonomy + " value set"); - replaceParentNodeWithClonedNode(attributedToBeChangedInNode.item(0), clonedNode); - } else if (changeAttribute.equalsIgnoreCase(TITLE)) { - Node clonedNode = attributedToBeChangedInNode.item(0).cloneNode(true); - clonedNode.getAttributes().getNamedItem("value").setNodeValue(qdmNameDataType); - replaceParentNodeWithClonedNode(attributedToBeChangedInNode.item(0), clonedNode); - } else if (changeAttribute.equalsIgnoreCase(ITEM)) { - for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { - Node itemNode = attributedToBeChangedInNode.item(count); - Node clonedNode = itemNode.cloneNode(true); - clonedNode.getAttributes().getNamedItem("extension").setNodeValue(extensionValue); - replaceParentNodeWithClonedNode(attributedToBeChangedInNode.item(count), clonedNode); - } - } else if (changeAttribute.equalsIgnoreCase("value")) { - String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); - String codeSystemOID = qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); - String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); - String codeSystemVersion = qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); - Node isCodeSystemVersionIncludedNode = qdmNode.getAttributes().getNamedItem("isCodeSystemVersionIncluded"); - boolean isCodeSystemVersionIncluded = true; - if(isCodeSystemVersionIncludedNode != null) { - isCodeSystemVersionIncluded = Boolean.parseBoolean(isCodeSystemVersionIncludedNode.getNodeValue()); - } - - Attr codeAttribute = attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("code"); - codeAttribute.setNodeValue(codeOID); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(codeAttribute); - - Attr codeSystemAttribute = attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("codeSystem"); - codeSystemAttribute.setNodeValue(codeSystemOID); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(codeSystemAttribute); - - Attr codeSystemNameAttribute = attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("codeSystemName"); - codeSystemNameAttribute.setNodeValue(codeSystemName); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(codeSystemNameAttribute); - - if(isCodeSystemVersionIncluded) { - Attr codeSystemVersionAttribute = attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("codeSystemVersion"); - codeSystemVersionAttribute.setNodeValue(codeSystemVersion); - attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(codeSystemVersionAttribute); - } - } - } - } - for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { - Node childNode = subTemplateNodeChilds.item(i); - Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); - XmlProcessor.clean(nodeToAttach); - dataCriteriaElem.appendChild(nodeToAttach); - } - } - - - private void replaceParentNodeWithClonedNode(Node toBeChangedNode, Node clonedNode) { - Node parentNode = toBeChangedNode.getParentNode(); - parentNode.replaceChild(clonedNode, toBeChangedNode); - } - - /** - * Creates the code for datatype. - * - * @param templateNode - * the template node - * @param dataCriteriaXMLProcessor - * the data criteria xml processor - * @return the element - */ - protected Element createCodeForDatatype(Node templateNode, XmlProcessor dataCriteriaXMLProcessor) { - Node codeAttr = templateNode.getAttributes().getNamedItem(CODE); - Node codeSystemAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM); - Node codeSystemNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_NAME); - Node codeDisplayNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_DISPLAY_NAME); - Element codeElement = null; - if (codeAttr != null || codeSystemAttr != null || codeSystemNameAttr != null - || codeDisplayNameAttr != null) { - codeElement = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); - if (codeAttr != null) { - codeElement.setAttribute(CODE, codeAttr.getNodeValue()); - } - if (codeSystemAttr != null) { - codeElement.setAttribute(CODE_SYSTEM, codeSystemAttr.getNodeValue()); - } - if (codeSystemNameAttr != null) { - codeElement.setAttribute(CODE_SYSTEM_NAME, codeSystemNameAttr.getNodeValue()); - } - if (codeDisplayNameAttr != null) { - Element displayNameElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); - displayNameElem.setAttribute(VALUE, codeDisplayNameAttr.getNodeValue()); - codeElement.appendChild(displayNameElem); - } - } - return codeElement; - } - + protected String extensionValue = null; + + /** + * Generate hqm for measure. + * + * @param me the me + * @return the string + */ + @Override + public String generate(MeasureExport me) { + // This was previously determined by MAT version number, now directly using constant + extensionValue = VERSION_5_0_ID; + XmlProcessor dataCriteriaXMLProcessor = me.getHqmfXmlProcessor(); + + createDataCriteriaForQDMELements(dataCriteriaXMLProcessor, me.getSimpleXmlProcessor()); + return dataCriteriaXMLProcessor.transform(dataCriteriaXMLProcessor.getOriginalDoc(), true); + } + + /** + * Creates the data criteria for qdm elements. + * + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + */ + private void createDataCriteriaForQDMELements( + XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor) { + + String xPathForDirectReferenceCodes = "/measure/elementLookUp/qdm[@datatype and @code ='true']"; + + try { + NodeList directReferenceCodeNodeList = + simpleXmlprocessor.findNodeList( + simpleXmlprocessor.getOriginalDoc(), xPathForDirectReferenceCodes); + generateCQLDRCNodeEntries( + dataCriteriaXMLProcessor, simpleXmlprocessor, directReferenceCodeNodeList); + + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + + private void generateCQLDRCNodeEntries( + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor simpleXmlprocessor, + NodeList qdmNoAttributeNodeList) + throws XPathExpressionException { + + if (qdmNoAttributeNodeList == null) { + return; + } + + for (int i = 0; i < qdmNoAttributeNodeList.getLength(); i++) { + Node qdmNode = qdmNoAttributeNodeList.item(i); + createXmlForDataCriteria(qdmNode, dataCriteriaXMLProcessor, simpleXmlprocessor); + } + } + + /** + * Create xml for data criteria. + * + * @param qdmNode the qdm node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param simpleXmlprocessor the simple xmlprocessor + */ + private void createXmlForDataCriteria( + Node qdmNode, XmlProcessor dataCriteriaXMLProcessor, XmlProcessor simpleXmlprocessor) { + String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(5.6); + String xPathForTemplate = "/templates/template[text()='" + dataType.toLowerCase() + "']"; + String actNodeStr = ""; + try { + + Node templateNode = + templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xPathForTemplate); + if (templateNode != null) { + String attrClass = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); + String xpathForAct = "/templates/acts/act[@a_id='" + attrClass + "']"; + Node actNode = + templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xpathForAct); + if (actNode != null) { + actNodeStr = actNode.getTextContent(); + } + + createDataCriteriaElementTag( + actNodeStr, templateNode, qdmNode, dataCriteriaXMLProcessor, templateXMLProcessor); + } + + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + + /** + * Gets the creates the data create element tag. + * + * @param actNodeStr the act node str + * @param templateNode the template node + * @param qdmNode the qdm node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @param templateXMLProcessor - templateXmlProcessor + * @throws XPathExpressionException the x path expression exception + */ + private void createDataCriteriaElementTag( + String actNodeStr, + Node templateNode, + Node qdmNode, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor templateXMLProcessor) + throws XPathExpressionException { + String oidValue = templateNode.getAttributes().getNamedItem(OID).getNodeValue(); + String classCodeValue = templateNode.getAttributes().getNamedItem(CLASS).getNodeValue(); + String moodValue = templateNode.getAttributes().getNamedItem(MOOD).getNodeValue(); + Node statusNode = templateNode.getAttributes().getNamedItem("status"); + String statusValue = statusNode != null ? statusNode.getNodeValue() : ""; + String rootValue = qdmNode.getAttributes().getNamedItem(ID).getNodeValue(); + String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + + Node actionNegInd = templateNode.getAttributes().getNamedItem("actionNegationInd"); + String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); + // Stan wants to generate unique id ( extension and root combination + // which is different from Value set). + String qdmLocalVariableName = codeOID + "_" + dataType; + + qdmLocalVariableName = StringUtils.deleteWhitespace(qdmLocalVariableName); + + Element dataCriteriaSectionElem = + (Element) + dataCriteriaXMLProcessor + .getOriginalDoc() + .getElementsByTagName("dataCriteriaSection") + .item(0); + Element componentElem = + (Element) + dataCriteriaXMLProcessor.getOriginalDoc().getElementsByTagName("component").item(0); + Attr nameSpaceAttr = dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:xsi"); + nameSpaceAttr.setNodeValue(nameSpace); + componentElem.setAttributeNodeNS(nameSpaceAttr); + // xmlns:qdm="urn:hhs-qdm:hqmf-r2-extensions:v1" + Attr qdmNameSpaceAttr = + dataCriteriaXMLProcessor.getOriginalDoc().createAttribute("xmlns:cql-ext"); + qdmNameSpaceAttr.setNodeValue("urn:hhs-cql:hqmf-n1-extensions:v1"); + componentElem.setAttributeNodeNS(qdmNameSpaceAttr); + // creating Entry Tag + Element entryElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement("entry"); + entryElem.setAttribute(TYPE_CODE, "DRIV"); + + Element dataCriteriaElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(actNodeStr); + entryElem.appendChild(dataCriteriaElem); + dataCriteriaElem.setAttribute(CLASS_CODE, classCodeValue); + dataCriteriaElem.setAttribute(MOOD_CODE, moodValue); + // adding actionNegationInd for Negative Datatypes + if (actionNegInd != null) { + dataCriteriaElem.setAttribute(ACTION_NEGATION_IND, actionNegInd.getNodeValue()); + } + Element templateId = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TEMPLATE_ID); + dataCriteriaElem.appendChild(templateId); + Element itemChild = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ITEM); + itemChild.setAttribute(ROOT, oidValue); + if (templateNode.getAttributes().getNamedItem("specificExtensionValue") != null) { + String specificExtensionValue = + templateNode.getAttributes().getNamedItem("specificExtensionValue").getNodeValue(); + itemChild.setAttribute("extension", specificExtensionValue); + } else if (templateNode.getAttributes().getNamedItem("addExtensionInTemplate") == null) { + itemChild.setAttribute("extension", extensionValue); + } + templateId.appendChild(itemChild); + Element idElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(ID); + idElem.setAttribute(ROOT, rootValue); + idElem.setAttribute("extension", qdmLocalVariableName); + dataCriteriaElem.appendChild(idElem); + + // boolean appendEntryElem = false; + + String isAddCodeTag = templateNode.getAttributes().getNamedItem("addCodeTag").getNodeValue(); + if ("true".equalsIgnoreCase(isAddCodeTag)) { // Add Code Element to + // DataCriteria Element. + addCodeElementToDataCriteriaElement( + templateNode, dataCriteriaXMLProcessor, qdmNode, dataCriteriaElem); + } + Element titleElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, dataType); + dataCriteriaElem.appendChild(titleElem); + if (StringUtils.isNotEmpty(statusValue)) { + Element statusCodeElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement("statusCode"); + statusCodeElem.setAttribute(CODE, statusValue); + dataCriteriaElem.appendChild(statusCodeElem); + } + + // Add value tag in entry element. + String addValueSetElement = + templateNode.getAttributes().getNamedItem("addValueTag").getNodeValue(); + if ("true".equalsIgnoreCase(addValueSetElement)) { + Element valueElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(VALUE); + + Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); + if (valueTypeAttr != null) { + valueElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); + } + + Node valueCodeSystem = templateNode.getAttributes().getNamedItem("valueCodeSystem"); + Node valueCode = templateNode.getAttributes().getNamedItem("valueCode"); + Node valueCodeSystemName = templateNode.getAttributes().getNamedItem("valueCodeSystemName"); + + if (valueCode != null && valueCodeSystem != null) { + valueElem.setAttribute("code", valueCode.getNodeValue()); + valueElem.setAttribute("codeSystem", valueCodeSystem.getNodeValue()); + if (valueCodeSystemName != null) { + valueElem.setAttribute("codeSystemName", valueCodeSystemName.getNodeValue()); + } + } else { + String codeSystemOID = qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); + String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); + String codeSystemVersion = + qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); + valueElem.setAttribute("code", codeOID); + valueElem.setAttribute("codeSystem", codeSystemOID); + valueElem.setAttribute("codeSystemName", codeSystemName); + + setCodeSystemVersion(qdmNode, valueElem, codeSystemVersion); + } + + dataCriteriaElem.appendChild(valueElem); + } + if (templateNode.getAttributes().getNamedItem("includeSubTemplate") != null) { + appendSubTemplateNode( + templateNode, dataCriteriaXMLProcessor, templateXMLProcessor, dataCriteriaElem, qdmNode); + } + + dataCriteriaSectionElem.appendChild(entryElem); + } + + private void setCodeSystemVersion(Node qdmNode, Element valueElem, String codeSystemVersion) { + Node isCodeSystemVersionIncludedNode = + qdmNode.getAttributes().getNamedItem("isCodeSystemVersionIncluded"); + boolean isCodeSystemVersionIncluded = true; + if (isCodeSystemVersionIncludedNode != null) { + isCodeSystemVersionIncluded = + Boolean.parseBoolean(isCodeSystemVersionIncludedNode.getNodeValue()); + } + if (isCodeSystemVersionIncluded) { + valueElem.setAttribute("codeSystemVersion", codeSystemVersion); + } + } + + /** + * Add Code Element To data Criteria Element based on condition. + * + * @param templateNode - Node + * @param dataCriteriaXMLProcessor - XmlProcessor + * @param qdmNode the qdm node + * @param dataCriteriaElem - Element + */ + private void addCodeElementToDataCriteriaElement( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + Node qdmNode, + Element dataCriteriaElem) { + String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + + // Patient Characteristic data type - contains code tag with valueSetId + // attribute and no title and value set tag. + boolean isPatientChar = templateNode.getAttributes().getNamedItem("valueSetId") != null; + boolean isAddValueSetInCodeTrue = + templateNode.getAttributes().getNamedItem("addValueSetInCode") != null; + boolean isIntervention = + "Intervention, Order".equalsIgnoreCase(dataType) + || "Intervention, Performed".equalsIgnoreCase(dataType) + || "Intervention, Recommended".equalsIgnoreCase(dataType) + || "Intervention, Not Ordered".equalsIgnoreCase(dataType) + || "Intervention, Not Performed".equalsIgnoreCase(dataType) + || "Intervention, Not Recommended".equalsIgnoreCase(dataType); + if (isAddValueSetInCodeTrue) { + Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + Node valueTypeAttr = templateNode.getAttributes().getNamedItem("valueType"); + if (valueTypeAttr != null) { + codeElem.setAttribute(XSI_TYPE, valueTypeAttr.getNodeValue()); + } + String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); + String codeSystemOID = qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); + String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); + String codeSystemVersion = + qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); + + codeElem.setAttribute("code", codeOID); + codeElem.setAttribute("codeSystem", codeSystemOID); + codeElem.setAttribute("codeSystemName", codeSystemName); + setCodeSystemVersion(qdmNode, codeElem, codeSystemVersion); + + dataCriteriaElem.appendChild(codeElem); + + } else if (isPatientChar) { + Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + + String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); + String codeSystemOID = qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); + String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); + String codeSystemVersion = + qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); + + codeElem.setAttribute("code", codeOID); + codeElem.setAttribute("codeSystem", codeSystemOID); + codeElem.setAttribute("codeSystemName", codeSystemName); + setCodeSystemVersion(qdmNode, codeElem, codeSystemVersion); + dataCriteriaElem.appendChild(codeElem); + } else if (isIntervention) { + Element codeElem = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); + String codeSystemOID = qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); + String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); + String codeSystemVersion = + qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); + + codeElem.setAttribute("code", codeOID); + codeElem.setAttribute("codeSystem", codeSystemOID); + codeElem.setAttribute("codeSystemName", codeSystemName); + setCodeSystemVersion(qdmNode, codeElem, codeSystemVersion); + dataCriteriaElem.appendChild(codeElem); + } else { + Element codeElement = createCodeForDatatype(templateNode, dataCriteriaXMLProcessor); + if (codeElement != null) { + dataCriteriaElem.appendChild(codeElement); + } + } + } + + /** + * Add SubTemplate defined in Template.xml to data criteria Element. + * + * @param templateNode - Node + * @param dataCriteriaXMLProcessor - XmlProcessor for Data Criteria + * @param templateXMLProcessor -XmlProcessor for Template Xml. + * @param dataCriteriaElem - Element + * @param qdmNode the qdm node + * @throws XPathExpressionException the x path expression exception + */ + private void appendSubTemplateNode( + Node templateNode, + XmlProcessor dataCriteriaXMLProcessor, + XmlProcessor templateXMLProcessor, + Element dataCriteriaElem, + Node qdmNode) + throws XPathExpressionException { + String subTemplateName = + templateNode.getAttributes().getNamedItem("includeSubTemplate").getNodeValue(); + Node subTemplateNode = + templateXMLProcessor.findNode( + templateXMLProcessor.getOriginalDoc(), "/templates/subtemplates/" + subTemplateName); + String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); + String qdmNameDataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmTaxonomy = qdmNode.getAttributes().getNamedItem(TAXONOMY).getNodeValue(); + NodeList subTemplateNodeChilds = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "/child::node()"); + + if (subTemplateNode.getAttributes().getNamedItem("changeAttribute") != null) { + String[] attributeToBeModified = + subTemplateNode.getAttributes().getNamedItem("changeAttribute").getNodeValue().split(","); + + for (String changeAttribute : attributeToBeModified) { + NodeList attributedToBeChangedInNode; + attributedToBeChangedInNode = + templateXMLProcessor.findNodeList( + templateXMLProcessor.getOriginalDoc(), + "/templates/subtemplates/" + subTemplateName + "//" + changeAttribute); + + if (changeAttribute.equalsIgnoreCase(ID)) { + String rootId = qdmNode.getAttributes().getNamedItem("uuid").getNodeValue(); + + Node clonedNode = attributedToBeChangedInNode.item(0).cloneNode(true); + clonedNode.getAttributes().getNamedItem("root").setNodeValue(rootId); + clonedNode + .getAttributes() + .getNamedItem("extension") + .setNodeValue(java.util.UUID.randomUUID().toString()); + + replaceParentNodeWithClonedNode(attributedToBeChangedInNode.item(0), clonedNode); + } else if (changeAttribute.equalsIgnoreCase(CODE)) { + String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); + String codeSystemOID = + qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); + String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); + String codeSystemVersion = + qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); + Node isCodeSystemVersionIncludedNode = + qdmNode.getAttributes().getNamedItem("isCodeSystemVersionIncluded"); + boolean isCodeSystemVersionIncluded = true; + if (isCodeSystemVersionIncludedNode != null) { + isCodeSystemVersionIncluded = + Boolean.parseBoolean(isCodeSystemVersionIncludedNode.getNodeValue()); + } + + Node clonedNode = attributedToBeChangedInNode.item(0).cloneNode(true); + + if (clonedNode.getAttributes().getNamedItem("valueSetVersion") != null) { + clonedNode.getAttributes().removeNamedItem("valueSetVersion"); + } + + if (clonedNode.getAttributes().getNamedItem("valueSet") != null) { + clonedNode.getAttributes().removeNamedItem("valueSet"); + } + + Attr attrNodeCode = clonedNode.getOwnerDocument().createAttribute("code"); + attrNodeCode.setNodeValue(codeOID); + clonedNode.getAttributes().setNamedItem(attrNodeCode); + + Attr attrNodeCodeSystem = clonedNode.getOwnerDocument().createAttribute("codeSystem"); + attrNodeCodeSystem.setNodeValue(codeSystemOID); + clonedNode.getAttributes().setNamedItem(attrNodeCodeSystem); + + Attr attrNodeCodeSystemName = + clonedNode.getOwnerDocument().createAttribute("codeSystemName"); + attrNodeCodeSystemName.setNodeValue(codeSystemName); + clonedNode.getAttributes().setNamedItem(attrNodeCodeSystemName); + + if (isCodeSystemVersionIncluded) { + Attr attrNodeCodeSystemVersion = + clonedNode.getOwnerDocument().createAttribute("codeSystemVersion"); + attrNodeCodeSystemVersion.setNodeValue(codeSystemVersion); + clonedNode.getAttributes().setNamedItem(attrNodeCodeSystemVersion); + } + replaceParentNodeWithClonedNode(attributedToBeChangedInNode.item(0), clonedNode); + } else if (changeAttribute.equalsIgnoreCase(DISPLAY_NAME)) { + Node clonedNode = attributedToBeChangedInNode.item(0).cloneNode(true); + clonedNode + .getAttributes() + .getNamedItem("value") + .setNodeValue( + HQMFDataCriteriaGenerator.removeOccurrenceFromName(qdmName) + + " " + + qdmTaxonomy + + " value set"); + replaceParentNodeWithClonedNode(attributedToBeChangedInNode.item(0), clonedNode); + } else if (changeAttribute.equalsIgnoreCase(TITLE)) { + Node clonedNode = attributedToBeChangedInNode.item(0).cloneNode(true); + clonedNode.getAttributes().getNamedItem("value").setNodeValue(qdmNameDataType); + replaceParentNodeWithClonedNode(attributedToBeChangedInNode.item(0), clonedNode); + } else if (changeAttribute.equalsIgnoreCase(ITEM)) { + for (int count = 0; count < attributedToBeChangedInNode.getLength(); count++) { + Node itemNode = attributedToBeChangedInNode.item(count); + Node clonedNode = itemNode.cloneNode(true); + clonedNode.getAttributes().getNamedItem("extension").setNodeValue(extensionValue); + replaceParentNodeWithClonedNode(attributedToBeChangedInNode.item(count), clonedNode); + } + } else if (changeAttribute.equalsIgnoreCase("value")) { + String codeOID = qdmNode.getAttributes().getNamedItem("oid").getNodeValue(); + String codeSystemOID = + qdmNode.getAttributes().getNamedItem("codeSystemOID").getNodeValue(); + String codeSystemName = qdmNode.getAttributes().getNamedItem("taxonomy").getNodeValue(); + String codeSystemVersion = + qdmNode.getAttributes().getNamedItem("codeSystemVersion").getNodeValue(); + Node isCodeSystemVersionIncludedNode = + qdmNode.getAttributes().getNamedItem("isCodeSystemVersionIncluded"); + boolean isCodeSystemVersionIncluded = true; + if (isCodeSystemVersionIncludedNode != null) { + isCodeSystemVersionIncluded = + Boolean.parseBoolean(isCodeSystemVersionIncludedNode.getNodeValue()); + } + + Attr codeAttribute = + attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("code"); + codeAttribute.setNodeValue(codeOID); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(codeAttribute); + + Attr codeSystemAttribute = + attributedToBeChangedInNode.item(0).getOwnerDocument().createAttribute("codeSystem"); + codeSystemAttribute.setNodeValue(codeSystemOID); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(codeSystemAttribute); + + Attr codeSystemNameAttribute = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createAttribute("codeSystemName"); + codeSystemNameAttribute.setNodeValue(codeSystemName); + attributedToBeChangedInNode.item(0).getAttributes().setNamedItem(codeSystemNameAttribute); + + if (isCodeSystemVersionIncluded) { + Attr codeSystemVersionAttribute = + attributedToBeChangedInNode + .item(0) + .getOwnerDocument() + .createAttribute("codeSystemVersion"); + codeSystemVersionAttribute.setNodeValue(codeSystemVersion); + attributedToBeChangedInNode + .item(0) + .getAttributes() + .setNamedItem(codeSystemVersionAttribute); + } + } + } + } + for (int i = 0; i < subTemplateNodeChilds.getLength(); i++) { + Node childNode = subTemplateNodeChilds.item(i); + Node nodeToAttach = dataCriteriaXMLProcessor.getOriginalDoc().importNode(childNode, true); + XmlProcessor.clean(nodeToAttach); + dataCriteriaElem.appendChild(nodeToAttach); + } + } + + private void replaceParentNodeWithClonedNode(Node toBeChangedNode, Node clonedNode) { + Node parentNode = toBeChangedNode.getParentNode(); + parentNode.replaceChild(clonedNode, toBeChangedNode); + } + + /** + * Creates the code for datatype. + * + * @param templateNode the template node + * @param dataCriteriaXMLProcessor the data criteria xml processor + * @return the element + */ + protected Element createCodeForDatatype( + Node templateNode, XmlProcessor dataCriteriaXMLProcessor) { + Node codeAttr = templateNode.getAttributes().getNamedItem(CODE); + Node codeSystemAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM); + Node codeSystemNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_NAME); + Node codeDisplayNameAttr = templateNode.getAttributes().getNamedItem(CODE_SYSTEM_DISPLAY_NAME); + Element codeElement = null; + if (codeAttr != null + || codeSystemAttr != null + || codeSystemNameAttr != null + || codeDisplayNameAttr != null) { + codeElement = dataCriteriaXMLProcessor.getOriginalDoc().createElement(CODE); + if (codeAttr != null) { + codeElement.setAttribute(CODE, codeAttr.getNodeValue()); + } + if (codeSystemAttr != null) { + codeElement.setAttribute(CODE_SYSTEM, codeSystemAttr.getNodeValue()); + } + if (codeSystemNameAttr != null) { + codeElement.setAttribute(CODE_SYSTEM_NAME, codeSystemNameAttr.getNodeValue()); + } + if (codeDisplayNameAttr != null) { + Element displayNameElem = + dataCriteriaXMLProcessor.getOriginalDoc().createElement(DISPLAY_NAME); + displayNameElem.setAttribute(VALUE, codeDisplayNameAttr.getNodeValue()); + codeElement.appendChild(displayNameElem); + } + } + return codeElement; + } } diff --git a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaGenerator.java b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaGenerator.java index ba3106e..9fda873 100644 --- a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaGenerator.java +++ b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFDataCriteriaGenerator.java @@ -5,53 +5,58 @@ import gov.cms.madie.hqmf.dto.MeasureExport; import org.springframework.stereotype.Service; -/** - * The Class HQMFDataCriteriaGenerator. - */ +/** The Class HQMFDataCriteriaGenerator. */ @Service public class HQMFDataCriteriaGenerator implements Generator { - - /** - * Generate hqmf for measure. - * - * @param me the me - * @return the string - * @throws Exception the exception - */ - @Override - public String generate(MeasureExport me) throws Exception { - - HQMFDataCriteriaElementGenerator cqlBasedHQMFDataCriteriaElementGenerator = new HQMFDataCriteriaElementGenerator(); - cqlBasedHQMFDataCriteriaElementGenerator.generate(me); - - HQMFPopulationLogicGenerator cqlBasedHQMFPopulationLogicGenerator = new HQMFPopulationLogicGenerator(); - cqlBasedHQMFPopulationLogicGenerator.generate(me); - - HQMFMeasureObservationLogicGenerator cqlBasedHQMFMeasureObservationLogicGenerator = new HQMFMeasureObservationLogicGenerator(); - cqlBasedHQMFMeasureObservationLogicGenerator.generate(me); - - XmlProcessor dataCriteriaXMLProcessor = me.getHqmfXmlProcessor(); - return removePreambleAndRootTags(dataCriteriaXMLProcessor.transform(dataCriteriaXMLProcessor.getOriginalDoc(), true)); - } - - /** - * @param xmlString - * @return - */ - private String removePreambleAndRootTags(String xmlString) { - xmlString = xmlString.replaceAll("\\<\\?xml(.+?)\\?\\>", "").trim() - .replaceAll("(<\\?[^<]*\\?>)?", "");/* remove preamble */ - xmlString = xmlString.replaceAll("", "").replaceAll("",""); - return xmlString; - } - - //Strip out 'Occurrence A_' at the start of qdmName If found. - public static String removeOccurrenceFromName(String qdmName){ - String regExpression = "Occurrence [A-Z]_.*"; - String newQdmName = qdmName; - if(newQdmName.matches(regExpression)){ - newQdmName = newQdmName.substring(newQdmName.indexOf('_')+1); - } - return newQdmName; - } + + /** + * Generate hqmf for measure. + * + * @param me the me + * @return the string + * @throws Exception the exception + */ + @Override + public String generate(MeasureExport me) throws Exception { + + HQMFDataCriteriaElementGenerator cqlBasedHQMFDataCriteriaElementGenerator = + new HQMFDataCriteriaElementGenerator(); + cqlBasedHQMFDataCriteriaElementGenerator.generate(me); + + HQMFPopulationLogicGenerator cqlBasedHQMFPopulationLogicGenerator = + new HQMFPopulationLogicGenerator(); + cqlBasedHQMFPopulationLogicGenerator.generate(me); + + HQMFMeasureObservationLogicGenerator cqlBasedHQMFMeasureObservationLogicGenerator = + new HQMFMeasureObservationLogicGenerator(); + cqlBasedHQMFMeasureObservationLogicGenerator.generate(me); + + XmlProcessor dataCriteriaXMLProcessor = me.getHqmfXmlProcessor(); + return removePreambleAndRootTags( + dataCriteriaXMLProcessor.transform(dataCriteriaXMLProcessor.getOriginalDoc(), true)); + } + + /** + * @param xmlString + * @return + */ + private String removePreambleAndRootTags(String xmlString) { + xmlString = + xmlString + .replaceAll("\\<\\?xml(.+?)\\?\\>", "") + .trim() + .replaceAll("(<\\?[^<]*\\?>)?", ""); /* remove preamble */ + xmlString = xmlString.replaceAll("", "").replaceAll("", ""); + return xmlString; + } + + // Strip out 'Occurrence A_' at the start of qdmName If found. + public static String removeOccurrenceFromName(String qdmName) { + String regExpression = "Occurrence [A-Z]_.*"; + String newQdmName = qdmName; + if (newQdmName.matches(regExpression)) { + newQdmName = newQdmName.substring(newQdmName.indexOf('_') + 1); + } + return newQdmName; + } } diff --git a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFGenerator.java b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFGenerator.java index 830738a..5422c2a 100644 --- a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFGenerator.java +++ b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFGenerator.java @@ -5,7 +5,7 @@ import gov.cms.madie.hqmf.XmlProcessor; import gov.cms.madie.hqmf.dto.MeasureExport; import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; @@ -15,94 +15,94 @@ * * @author jmeyer */ +@Slf4j @Service @AllArgsConstructor -@NoArgsConstructor public class HQMFGenerator implements Generator { - private HQMFMeasureDetailsGenerator hqmfMeasureDetailsGenerator; - private HQMFDataCriteriaGenerator hqmfDataCriteriaGenerator; - - private final Logger logger = LoggerFactory.getLogger(HQMFDataCriteriaGenerator.class); + private HQMFMeasureDetailsGenerator hqmfMeasureDetailsGenerator; + private HQMFDataCriteriaGenerator hqmfDataCriteriaGenerator; - /** - * Generate hqmf for CQL Based measures (QDM version 5.5) - * - * @param me the me - * @return the string - */ - @Override - public String generate(MeasureExport me) throws Exception { - try { - // MAT 6911: Export CQL based HQMF w/ Meta Data Section - String hqmfXML = hqmfMeasureDetailsGenerator.generate(me); - // Inline comments are added after the end of last componentOf tag. - // This is removed in this method - hqmfXML = replaceInlineCommentFromEnd(hqmfXML); + private final Logger logger = LoggerFactory.getLogger(HQMFDataCriteriaGenerator.class); - String dataCriteriaXML = hqmfDataCriteriaGenerator.generate(me); - hqmfXML= appendToHQMF(dataCriteriaXML, hqmfXML); - - XmlProcessor hqmfProcessor = new XmlProcessor(hqmfXML); - me.setHqmfXmlProcessor(hqmfProcessor); - - //generateNarrative(me); - return finalCleanUp(me); - } catch (Exception e) { - logger.error("Unable to generate HQMF for QDM v5.6. Exception Stack Strace is as followed : "); - throw e; - } - } + /** + * Generate hqmf for CQL Based measures (QDM version 5.5) + * + * @param me the me + * @return the string + */ + @Override + public String generate(MeasureExport me) throws Exception { + try { + // MAT 6911: Export CQL based HQMF w/ Meta Data Section + String hqmfXML = hqmfMeasureDetailsGenerator.generate(me); + // Inline comments are added after the end of last componentOf tag. + // This is removed in this method + hqmfXML = replaceInlineCommentFromEnd(hqmfXML); - /** - * Inline comments are added after the end of last componentOf tag. This is - * removed in this method - * - * @param eMeasureDetailsXML - * - String eMeasureDetailsXML. - * @return String eMeasureDetailsXML. - */ - private String replaceInlineCommentFromEnd(String eMeasureDetailsXML) { - int indexOfComponentOf = eMeasureDetailsXML.lastIndexOf(""); - eMeasureDetailsXML = eMeasureDetailsXML.substring(0, indexOfComponentOf); - eMeasureDetailsXML = eMeasureDetailsXML.concat(""); - return eMeasureDetailsXML; - } - - /** - * Append to hqmf. - * - * @param dataCriteriaXML the data criteria xml - * @param hqmfXML the hqmf xml - * @return the string - */ - private String appendToHQMF(String dataCriteriaXML, String hqmfXML) { - int indexOfEnd = hqmfXML.indexOf(""); - if(indexOfEnd > -1){ - hqmfXML = hqmfXML.substring(0, indexOfEnd) + dataCriteriaXML + hqmfXML.substring(indexOfEnd); - } - return hqmfXML; - } - - /** - * Final clean up. - * - * @param me the me - * @return the string - */ - private String finalCleanUp(MeasureExport me) { - HQMFFinalCleanUp.clean(me); - return removeXmlTagNamespace(me.getHqmfXmlProcessor().transform(me.getHqmfXmlProcessor().getOriginalDoc(), true)); - } - - /** - * Removes the xml tag namespace. - * - * @param xmlString the xml string - * @return the string - */ - private String removeXmlTagNamespace(String xmlString) { - xmlString = xmlString.replaceAll(" xmlns=\"\"", "").replaceAll(""", """); - return xmlString; - } + String dataCriteriaXML = hqmfDataCriteriaGenerator.generate(me); + hqmfXML = appendToHQMF(dataCriteriaXML, hqmfXML); + + XmlProcessor hqmfProcessor = new XmlProcessor(hqmfXML); + me.setHqmfXmlProcessor(hqmfProcessor); + + // generateNarrative(me); + return finalCleanUp(me); + } catch (Exception e) { + logger.error( + "Unable to generate HQMF for QDM v5.6. Exception Stack Strace is as followed : "); + throw e; + } + } + + /** + * Inline comments are added after the end of last componentOf tag. This is removed in this method + * + * @param eMeasureDetailsXML - String eMeasureDetailsXML. + * @return String eMeasureDetailsXML. + */ + private String replaceInlineCommentFromEnd(String eMeasureDetailsXML) { + int indexOfComponentOf = eMeasureDetailsXML.lastIndexOf(""); + eMeasureDetailsXML = eMeasureDetailsXML.substring(0, indexOfComponentOf); + eMeasureDetailsXML = eMeasureDetailsXML.concat(""); + return eMeasureDetailsXML; + } + + /** + * Append to hqmf. + * + * @param dataCriteriaXML the data criteria xml + * @param hqmfXML the hqmf xml + * @return the string + */ + private String appendToHQMF(String dataCriteriaXML, String hqmfXML) { + int indexOfEnd = hqmfXML.indexOf(""); + if (indexOfEnd > -1) { + hqmfXML = hqmfXML.substring(0, indexOfEnd) + dataCriteriaXML + hqmfXML.substring(indexOfEnd); + } + return hqmfXML; + } + + /** + * Final clean up. + * + * @param me the me + * @return the string + */ + private String finalCleanUp(MeasureExport me) { + HQMFFinalCleanUp.clean(me); + return removeXmlTagNamespace( + me.getHqmfXmlProcessor().transform(me.getHqmfXmlProcessor().getOriginalDoc(), true)); + } + + /** + * Removes the xml tag namespace. + * + * @param xmlString the xml string + * @return the string + */ + private String removeXmlTagNamespace(String xmlString) { + xmlString = xmlString.replaceAll(" xmlns=\"\"", "").replaceAll(""", """); + return xmlString; + } } diff --git a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureDetailsGenerator.java b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureDetailsGenerator.java index d23dfc8..3a63a49 100644 --- a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureDetailsGenerator.java +++ b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureDetailsGenerator.java @@ -1,6 +1,5 @@ package gov.cms.madie.hqmf.qdm_5_6; - import gov.cms.madie.hqmf.Generator; import gov.cms.madie.hqmf.XMLUtility; import gov.cms.madie.hqmf.XmlProcessor; @@ -17,127 +16,139 @@ @Slf4j @Service public class HQMFMeasureDetailsGenerator implements Generator { - - private static final String CONVERSION_FILE_FOR_CQL_BASED_HQMF_HEADER = "xsl/qdm_v5_6_measure_details.xsl"; - @Override - public String generate(MeasureExport me) { - String simpleXML = me.getSimpleXml(); - String releaseVersion = me.getReleaseVersion(); + private static final String CONVERSION_FILE_FOR_CQL_BASED_HQMF_HEADER = + "xsl/qdm_v5_6_measure_details.xsl"; + + @Override + public String generate(MeasureExport me) { + String simpleXML = me.getSimpleXml(); + String releaseVersion = me.getReleaseVersion(); + + simpleXML = addReleaseVersionToSimpleXML(simpleXML); + String measureDetailsHQMF_XML = + XMLUtility.getInstance() + .applyXSL( + simpleXML, + XMLUtility.getInstance().getXMLResource(CONVERSION_FILE_FOR_CQL_BASED_HQMF_HEADER)); + measureDetailsHQMF_XML = incrementEndDatebyOne(measureDetailsHQMF_XML); + return measureDetailsHQMF_XML.replaceAll("xmlns=\"\"", ""); + } + + private String addReleaseVersionToSimpleXML(String simpleXML) { + // if(releaseVersion == null || releaseVersion.trim().length() == 0){ + // return simpleXML; + // } + + // TODO: CREATE CONSTANT Hardcoded to 5.6 for now...probably refactor to accept Measure Export, + // measure, and pull QDM model from measure? + String releaseVersion = "5.6"; // MATPropertiesService.get().getQdmVersion(); + int measureDetailsTagIndex = simpleXML.indexOf(""); + if (measureDetailsTagIndex > -1) { + simpleXML = + simpleXML.substring(0, measureDetailsTagIndex) + + "" + + simpleXML.substring(measureDetailsTagIndex); + } + + return simpleXML; + } + + /** + * Increment end date by one. + * + * @param measureDetailsHQMF_XML the measure details hqm f_ xml + * @return the string + */ + private String incrementEndDatebyOne(String measureDetailsHQMF_XML) { + XmlProcessor measureDetailsXml = new XmlProcessor(measureDetailsHQMF_XML); + String xpathMeasurementPeriodStr = + "/QualityMeasureDocument/controlVariable/measurePeriod/value/high"; + try { + Node endDateHigh = + measureDetailsXml.findNode(measureDetailsXml.getOriginalDoc(), xpathMeasurementPeriodStr); + if (endDateHigh != null) { + String highEndDate = endDateHigh.getAttributes().getNamedItem("value").getNodeValue(); + highEndDate = formatDate(highEndDate); + endDateHigh.getAttributes().getNamedItem("value").setNodeValue(highEndDate); + } + // to edit default startDate in HQMF measureDetails + editDefaultStartDate(measureDetailsXml); + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + + return measureDetailsXml.transform(measureDetailsXml.getOriginalDoc(), true); + } - simpleXML = addReleaseVersionToSimpleXML(simpleXML); - String measureDetailsHQMF_XML = XMLUtility.getInstance() - .applyXSL(simpleXML, XMLUtility.getInstance().getXMLResource(CONVERSION_FILE_FOR_CQL_BASED_HQMF_HEADER)); - measureDetailsHQMF_XML = incrementEndDatebyOne(measureDetailsHQMF_XML); - return measureDetailsHQMF_XML.replaceAll("xmlns=\"\"", ""); - } - - private String addReleaseVersionToSimpleXML(String simpleXML) { -// if(releaseVersion == null || releaseVersion.trim().length() == 0){ -// return simpleXML; -// } + /** + * Edits the default start date. + * + * @param measureDetailsXml the measure details xml + */ + private void editDefaultStartDate(XmlProcessor measureDetailsXml) { + String xpathMeasurementPeriodStr = + "/QualityMeasureDocument/controlVariable/measurePeriod/value/phase/low"; + try { + Node measurementPeriodLowNode = + measureDetailsXml.findNode(measureDetailsXml.getOriginalDoc(), xpathMeasurementPeriodStr); + if (measurementPeriodLowNode != null) { + String lowDateValue = + measurementPeriodLowNode.getAttributes().getNamedItem("value").getNodeValue(); + measurementPeriodLowNode + .getAttributes() + .getNamedItem("value") + .setNodeValue(getLowValue(lowDateValue)); + } + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } - // TODO: CREATE CONSTANT Hardcoded to 5.6 for now...probably refactor to accept Measure Export, measure, and pull QDM model from measure? - String releaseVersion = "5.6"; // MATPropertiesService.get().getQdmVersion(); - int measureDetailsTagIndex = simpleXML.indexOf(""); - if(measureDetailsTagIndex > -1){ - simpleXML = simpleXML.substring(0, measureDetailsTagIndex) + "" + simpleXML.substring(measureDetailsTagIndex); - } - - return simpleXML; - } - - /** - * Increment end date by one. - * - * @param measureDetailsHQMF_XML the measure details hqm f_ xml - * @return the string - */ - private String incrementEndDatebyOne(String measureDetailsHQMF_XML){ - XmlProcessor measureDetailsXml = new XmlProcessor(measureDetailsHQMF_XML); - String xpathMeasurementPeriodStr = "/QualityMeasureDocument/controlVariable/measurePeriod/value/high"; - try { - Node endDateHigh = measureDetailsXml.findNode(measureDetailsXml.getOriginalDoc(), - xpathMeasurementPeriodStr); - if(endDateHigh!=null){ - String highEndDate = endDateHigh.getAttributes().getNamedItem("value").getNodeValue(); - highEndDate = formatDate(highEndDate); - endDateHigh.getAttributes().getNamedItem("value").setNodeValue(highEndDate); - } - //to edit default startDate in HQMF measureDetails - editDefaultStartDate(measureDetailsXml); - } catch (XPathExpressionException e) { - e.printStackTrace(); - } + /** + * Gets the low value. + * + * @param lowValue the low value + * @return the low value + */ + private String getLowValue(String lowValue) { + String mm = lowValue.substring(4, 6); + String dd = lowValue.substring(6, 8); + String year = getCurrentYear(); + // Low date + return year + mm + dd; + } - return measureDetailsXml.transform(measureDetailsXml.getOriginalDoc(), true); - } - - /** - * Edits the default start date. - * - * @param measureDetailsXml the measure details xml - */ - private void editDefaultStartDate(XmlProcessor measureDetailsXml) { - String xpathMeasurementPeriodStr = "/QualityMeasureDocument/controlVariable/measurePeriod/value/phase/low"; - try { - Node measurementPeriodLowNode = measureDetailsXml.findNode(measureDetailsXml.getOriginalDoc(), - xpathMeasurementPeriodStr); - if(measurementPeriodLowNode!=null){ - String lowDateValue = measurementPeriodLowNode.getAttributes(). - getNamedItem("value").getNodeValue(); - measurementPeriodLowNode.getAttributes().getNamedItem("value"). - setNodeValue(getLowValue(lowDateValue)); - } - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - - /** - * Gets the low value. - * - * @param lowValue the low value - * @return the low value - */ - private String getLowValue(String lowValue){ - String mm = lowValue.substring(4,6); - String dd = lowValue.substring(6,8); - String year = getCurrentYear(); - // Low date - return year + mm + dd; - } - - /** - * Gets the current year. - * - * @return the current year - */ - private String getCurrentYear(){ - Calendar now = Calendar.getInstance(); - int year = now.get(Calendar.YEAR); - String currentYear = String.valueOf(year); - return currentYear; - } - - - /** - * Format date. - * - * @param date the date - * @return the string - */ - private String formatDate(String date){ - SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); - Calendar c = Calendar.getInstance(); - try { - c.setTime(sdf.parse(date)); - } catch (ParseException e) { - e.printStackTrace(); - } - c.add(Calendar.DATE, 1); // to add one to End Date - date = sdf.format(c.getTime()); - return date; - } + /** + * Gets the current year. + * + * @return the current year + */ + private String getCurrentYear() { + Calendar now = Calendar.getInstance(); + int year = now.get(Calendar.YEAR); + String currentYear = String.valueOf(year); + return currentYear; + } + /** + * Format date. + * + * @param date the date + * @return the string + */ + private String formatDate(String date) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + Calendar c = Calendar.getInstance(); + try { + c.setTime(sdf.parse(date)); + } catch (ParseException e) { + e.printStackTrace(); + } + c.add(Calendar.DATE, 1); // to add one to End Date + date = sdf.format(c.getTime()); + return date; + } } diff --git a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureObservationLogicGenerator.java b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureObservationLogicGenerator.java index a147583..acba644 100644 --- a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureObservationLogicGenerator.java +++ b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureObservationLogicGenerator.java @@ -1,6 +1,5 @@ package gov.cms.madie.hqmf.qdm_5_6; - import gov.cms.madie.hqmf.QDMTemplateProcessorFactory; import gov.cms.madie.hqmf.UUIDUtilClient; import gov.cms.madie.hqmf.XmlProcessor; @@ -22,1028 +21,1144 @@ import java.util.Map; import java.util.TreeMap; -/** - * The Class HQMFPopulationLogicGenerator. - */ +/** The Class HQMFPopulationLogicGenerator. */ public class HQMFMeasureObservationLogicGenerator extends HQMFClauseLogicGenerator { - private static final String MEASURE_OBSERVATION_EXTENSION_VALUE = "2018-05-01"; - - private static final int DATETIMEDIFF_CHILD_COUNT = 2; - - private Map clauseLogicMap = new HashMap<>(); - - private Map measureGroupingMap = new TreeMap<>(); - - private MeasureExport me; - - private String scoringType; - - private boolean clauseLogicHasElementRef = false; - - /** - * MAP of Functional Ops AGGREGATE that can be used in Measure Observation. - */ - private static final Map FUNCTIONAL_OPS_AGGREGATE = new TreeMap<>( - String.CASE_INSENSITIVE_ORDER); - - /** - * MAP of Functional Ops INCLUDED FUNCTIONS that can be used in Measure - * Observation. - */ - private static final Map INCLUDED_FUNCTIONAL_NAMES = new TreeMap<>( - String.CASE_INSENSITIVE_ORDER); - static { - FUNCTIONAL_OPS_AGGREGATE.put("MAX", "MAX"); - FUNCTIONAL_OPS_AGGREGATE.put("MIN", "MIN"); - FUNCTIONAL_OPS_AGGREGATE.put("SUM", "SUM"); - FUNCTIONAL_OPS_AGGREGATE.put("AVG", "AVERAGE"); - FUNCTIONAL_OPS_AGGREGATE.put("COUNT", "COUNT"); - FUNCTIONAL_OPS_AGGREGATE.put("MEDIAN", "MEDIAN"); - FUNCTIONAL_OPS_AGGREGATE.put("DATETIMEDIFF", null); - INCLUDED_FUNCTIONAL_NAMES.put("FIRST", "FIRST"); - INCLUDED_FUNCTIONAL_NAMES.put("SECOND", "SECOND"); - INCLUDED_FUNCTIONAL_NAMES.put("THIRD", "THIRD"); - INCLUDED_FUNCTIONAL_NAMES.put("FOURTH", "FOURTH"); - INCLUDED_FUNCTIONAL_NAMES.put("FIFTH", "FIFTH"); - INCLUDED_FUNCTIONAL_NAMES.put("MOST RECENT", "MOST RECENT"); - INCLUDED_FUNCTIONAL_NAMES.put("COUNT", "COUNT"); - INCLUDED_FUNCTIONAL_NAMES.put("DATETIMEDIFF", "DATETIMEDIFF"); - } - - @Override - public String generate(MeasureExport me) throws Exception { - this.me = me; - setMeasureExport(me); - getMeasureScoringType(me); - generateClauseLogicMap(me); - getAllMeasureGroupings(me); - generateMeasureObSection(me); - return null; - } - - /** - * Get DotNotation from templates.xml. - * - * @param attributeName - * -String - * @param dataTypeName - * - String - * @throws XPathExpressionException - * -Exception - * @return String dot notation. - */ - private String getQdmAttributeMapppingDotNotation(String attributeName, String dataTypeName) - throws XPathExpressionException { - XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(5.6); - String xPath = "/templates/attributeMappings/attributeMapping[@qdmAttribute=\"" + attributeName + "\"]"; - Node attributeMappingNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xPath); - if (attributeMappingNode == null) { - xPath = "/templates/attributeMappings/attributeMapping[@qdmAttribute='" + attributeName - + "' and @datatypes = \"" + dataTypeName.toLowerCase() + "\"]"; - attributeMappingNode = templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xPath); - } - if (attributeMappingNode != null) { - return attributeMappingNode.getAttributes().getNamedItem("dotNotation").getNodeValue(); - } else { - return null; - } - } - - /** - * Method to generate MeasureObservation Criteria Section. - * - * @param me - * - MeasureExport - * @throws XPathExpressionException - * - Exception - */ - private void generateMeasureObSection(MeasureExport me) throws XPathExpressionException { - String isInGrouping = ""; - for (Integer key : measureGroupingMap.keySet()) { - NodeList groupingChildList = measureGroupingMap.get(key); - for (int i = 0; i < groupingChildList.getLength(); i++) { - Node groupingChildListItem = groupingChildList.item(i); - - String popType = groupingChildListItem.getAttributes().getNamedItem(TYPE).getNodeValue(); - if (groupingChildList.item(i).getAttributes().getNamedItem(GROUPING_CHECK) != null) { - isInGrouping = groupingChildList.item(i).getAttributes().getNamedItem(GROUPING_CHECK) - .getNodeValue(); - } - switch (popType) { - case "measureObservation": - if (isInGrouping != null && !isInGrouping.isEmpty()) { - if (isInGrouping.equalsIgnoreCase("true")) { - - Node measureObSectionComponentElement = createMeasureObservationSection( - me.getHqmfXmlProcessor()); - - generateMeasureObDefinition(groupingChildListItem, measureObSectionComponentElement); - } - } else { - Node measureObSectionComponentElement = createMeasureObservationSection( - me.getHqmfXmlProcessor()); - - generateMeasureObDefinition(groupingChildListItem, measureObSectionComponentElement); - } - break; - case "denominator": - break; - case "numerator": - break; - default: - // do nothing. - break; - } - } - } - } - - /** - * Method to generate default criteriaTag for all population types included in - * measure grouping. - * - * @param measureObsClauseNode - * - Node - * @param measureObservationSecElement - * - Element - * @throws XPathExpressionException - * - Exception - */ - private void generateMeasureObDefinition(Node measureObsClauseNode, Node measureObservationSecElement) { - - if (!measureObsClauseNode.hasChildNodes()) { - return; - } - - Document doc = measureObservationSecElement.getOwnerDocument(); - Comment comment = doc.createComment( - "Definition for " + measureObsClauseNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); - Element definitionElement = doc.createElement("definition"); - Element measureObDefinitionElement = doc.createElement("measureObservationDefinition"); - measureObDefinitionElement.setAttribute(CLASS_CODE, "OBS"); - measureObDefinitionElement.setAttribute(MOOD_CODE, "DEF"); - Element idElem = doc.createElement(ID); - idElem.setAttribute(ROOT, measureObsClauseNode.getAttributes().getNamedItem("uuid").getNodeValue()); - idElem.setAttribute(EXTENSION, "MeasureObservation"); - measureObDefinitionElement.appendChild(idElem); - - Element codeElem = doc.createElement(CODE); - codeElem.setAttribute(CODE, "AGGREGATE"); - codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.5.4"); - measureObDefinitionElement.appendChild(codeElem); - generateCQLLogicForMeasureObservation(measureObsClauseNode, measureObDefinitionElement); - definitionElement.appendChild(measureObDefinitionElement); - Element measurObSectionElement = (Element) measureObservationSecElement.getFirstChild(); - measurObSectionElement.appendChild(comment); - measurObSectionElement.appendChild(definitionElement); - } - - private void generateCQLLogicForMeasureObservation(Node measureObservationNode, Element measureObservationElementNode) { - - if (!measureObservationNode.hasChildNodes()) { - return; - } - - String extensionAttribute = ""; - - Document doc = measureObservationElementNode.getOwnerDocument(); - - Element valueElement = doc.createElement(VALUE); - valueElement.setAttribute("xsi:type", "INT"); - valueElement.setAttribute("nullFlavor", "DER"); - - Node firstChildNode = measureObservationNode.getFirstChild(); - String firstChildNodeName = firstChildNode.getNodeName(); - - if ("cqlfunction".equals(firstChildNodeName)) { - - String functionName = firstChildNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - extensionAttribute += functionName; - - Element expressionElement = createExpressionTag(measureObservationNode, doc, firstChildNode); - valueElement.appendChild(expressionElement); - measureObservationElementNode.appendChild(valueElement); - - } else if ("cqlaggfunction".equals(firstChildNodeName)) { - - String aggFunctionName = firstChildNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - String aggFunctionHQMFName = getAggMethodCode(aggFunctionName); - - extensionAttribute += aggFunctionHQMFName + " Of "; - - Node aggNodeChild = firstChildNode.getFirstChild(); - if ("cqlfunction".equals(aggNodeChild.getNodeName())) { - - String functionName = aggNodeChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - extensionAttribute += functionName; - - Element expressionElement = createExpressionTag(measureObservationNode, doc, aggNodeChild); - valueElement.appendChild(expressionElement); - measureObservationElementNode.appendChild(valueElement); - } - - Element methodCodeElement = doc.createElement("methodCode"); - Element itemElement = doc.createElement(ITEM); - itemElement.setAttribute(CODE, aggFunctionHQMFName); - itemElement.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.5.84"); - - methodCodeElement.appendChild(itemElement); - measureObservationElementNode.appendChild(methodCodeElement); - } - - if (extensionAttribute.length() > 0) { - NodeList idList = measureObservationElementNode.getElementsByTagName(ID); - if (idList.getLength() > 0) { - Node id = idList.item(0); - id.getAttributes().getNamedItem(EXTENSION).setNodeValue(extensionAttribute); - } - } - - // check for associated population id and add related HQMF nodes. - handleMeasureObservationAssociations(measureObservationNode, measureObservationElementNode); - } - - private void handleMeasureObservationAssociations(Node measureObservationNode, Element measureObDefinitionElement) { - Node associatedPopulationNode = null; - try { - associatedPopulationNode = getAssociatedPopulationNode(measureObservationNode); - if (associatedPopulationNode != null && associatedPopulationNode.hasChildNodes()) { - - // the measure observation criteria reference root and extension should come from the root and extension values of the associated - // population - String measureObservationCriteriaReferenceIdRoot = associatedPopulationNode.getAttributes().getNamedItem("uuid").getNodeValue(); - String measureObservationCriteriaReferenceIdExtension = associatedPopulationNode.getAttributes().getNamedItem("type").getNodeValue(); - - Document doc = measureObDefinitionElement.getOwnerDocument(); - - Element component = doc.createElement("component"); - component.setAttribute(TYPE_CODE, "COMP"); - - Element criteriaReference = doc.createElement("criteriaReference"); - criteriaReference.setAttribute(CLASS_CODE, "OBS"); - criteriaReference.setAttribute(MOOD_CODE, "EVN"); - - Element id = doc.createElement(ID); - id.setAttribute(ROOT, measureObservationCriteriaReferenceIdRoot); - id.setAttribute(EXTENSION, measureObservationCriteriaReferenceIdExtension); - - measureObDefinitionElement.appendChild(component); - component.appendChild(criteriaReference); - criteriaReference.appendChild(id); - } - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - } - - private Node getAssociatedPopulationNode(Node measureObservationNode) throws XPathExpressionException { - String associatedPopulationUUID = getAssociatedPopulationUUID(measureObservationNode); - String associatedClauseXPath = "//measureGrouping/group/clause[@uuid = '" + associatedPopulationUUID + "']"; - - Node associatedPopulationNode = me.getSimpleXmlProcessor().findNode(measureObservationNode.getOwnerDocument(), - associatedClauseXPath); - return associatedPopulationNode; - } - - public String getAssociatedPopulationUUID(Node msrObsClauseNode) { - String associatedPopuUUID = ""; - - if (scoringType.equalsIgnoreCase("Continuous Variable")) { - associatedPopuUUID = findMeasurePopulationUUID(msrObsClauseNode.getParentNode()); - } else { - if (msrObsClauseNode.getAttributes().getNamedItem(ASSOCIATED_POPULATION_UUID) != null) { - associatedPopuUUID = msrObsClauseNode.getAttributes().getNamedItem(ASSOCIATED_POPULATION_UUID).getNodeValue(); - } - } - - return associatedPopuUUID; - } - - private String findMeasurePopulationUUID(Node parentNode) { - - String uuid = ""; - - NodeList nodeList = parentNode.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node node = nodeList.item(i); - if (MEASURE_POPULATION.equals(node.getAttributes().getNamedItem(TYPE).getNodeValue())) { - uuid = node.getAttributes().getNamedItem(UUID).getNodeValue(); - break; - } - } - - return uuid; - } - - /** - * Create tag for Measure Observation. - * - * @param item - * @param doc - * @param cqlFunctionNode - * @return - */ - public Element createExpressionTag(Node item, Document doc, Node cqlFunctionNode) { - - Element expressionElement = doc.createElement("expression"); - String cqlFunctionNameValue = cqlFunctionNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - - String cqlLibraryNameXPath = "//cqlLookUp/library"; - - try { - - Node cqlLibraryNameNode = me.getSimpleXmlProcessor().findNode(item.getOwnerDocument(), cqlLibraryNameXPath); - String libraryName = ""; - if (cqlLibraryNameNode != null) { - libraryName = cqlLibraryNameNode.getTextContent(); - } - String expressionValueAttribute = libraryName + ".\"" + cqlFunctionNameValue + "\""; - expressionElement.setAttribute(VALUE, expressionValueAttribute); - - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - - return expressionElement; - } - - private String getAggMethodCode(String aggregateFunctionName) { - - String hqmfCodeForAggFunction = ""; - switch (aggregateFunctionName) { - - case "Count": - case "Sum": - case "Average": - case "Median": - case "Mode": - hqmfCodeForAggFunction = aggregateFunctionName.toUpperCase(); - break; - - case "Sample Standard Deviation": - hqmfCodeForAggFunction = "STDEV.S"; - break; - case "Sample Variance": - hqmfCodeForAggFunction = "VARIANCE.S"; - break; - case "Population Standard Deviation": - hqmfCodeForAggFunction = "STDEV.P"; - break; - case "Population Variance": - hqmfCodeForAggFunction = "VARIANCE.P"; - break; - case "Minimum": - hqmfCodeForAggFunction = "MIN"; - break; - case "Maximum": - hqmfCodeForAggFunction = "MAX"; - break; - default: - break; - } - - return hqmfCodeForAggFunction; - } - - /** - * Method to find Node's Parent - Subtree Name. - * - * @param node - * - Node - * @return SubTree DisplayName. - */ - private String findSubTreeDisplayName(Node node) { - String displayName = null; - if (node != null) { - String nodeName = node.getNodeName(); - if ("subTree".equals(nodeName)) { - displayName = node.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - if (node.getAttributes().getNamedItem("qdmVariable") != null && - node.getAttributes().getNamedItem("qdmVariable").getNodeValue().equalsIgnoreCase("true")) { - displayName = "qdm_var_" + displayName.replace("$", ""); - } - } else { - displayName = findSubTreeDisplayName(node.getParentNode()); - } - } - return StringUtils.deleteWhitespace(displayName); - } - - /** - * Method to Evaluate Clause logic Node types and generate Clause Logic in Data - * Criteria section if applicable and generates value expression/precondition. - * - * @param clauseNodes - * - Clause Logic Nodes - * @param elementRefList - * - Element Ref List - * @param measureObDefinitionElement - * - DOM element - * @throws XPathExpressionException - * - Exception. - */ - private String generateMOClauseLogic(Node clauseNodes, List elementRefList, - Element measureObDefinitionElement, boolean isClauseLogicGeneratable, String variableName, - boolean checkIfDateTimeDiff) throws XPathExpressionException { - String localVariableName = null; - Node firstChildNode = null; - Node parentSubTreeNode = null; - String preCodExp = null; - if (variableName != null) { - localVariableName = variableName; - } - if (isClauseLogicGeneratable) { - firstChildNode = clauseNodes.getFirstChild(); - if (clauseNodes.getParentNode() != null) { - parentSubTreeNode = clauseNodes.getParentNode().cloneNode(false); - } else if (clauseNodes.getNodeName().equals("subTree")) { - parentSubTreeNode = clauseNodes.cloneNode(false); - } - } else { - if (checkIfParentSubTree(clauseNodes).getNodeName().equalsIgnoreCase("subTree")) { - if (clauseNodes.getNodeName().equals("elementRef")) { - firstChildNode = clauseNodes; - } else { - firstChildNode = clauseNodes.getFirstChild(); - } - parentSubTreeNode = clauseNodes.cloneNode(false); - } else { - firstChildNode = clauseNodes; - parentSubTreeNode = clauseNodes.getParentNode().cloneNode(false); - } - } - String firstChildNodeName = firstChildNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - switch (firstChildNode.getNodeName()) { - case "setOp": - generateForSetOp(measureObDefinitionElement, isClauseLogicGeneratable, checkIfDateTimeDiff, - localVariableName, firstChildNode, parentSubTreeNode); - break; - case "relationalOp": - preCodExp = generateForRelationalOperator(measureObDefinitionElement, isClauseLogicGeneratable, - checkIfDateTimeDiff, localVariableName, firstChildNode, parentSubTreeNode); - break; - case "elementRef": - elementRefList.add(firstChildNode); - if (localVariableName != null) { - preCodExp = generateValueAndExpressionTag(elementRefList, measureObDefinitionElement, - localVariableName); - } else { - preCodExp = generateValueAndExpressionTag(elementRefList, measureObDefinitionElement, - null); - } - break; - case "functionalOp": - if (INCLUDED_FUNCTIONAL_NAMES.containsKey(firstChildNodeName)) { - preCodExp = generateForFunctionalOperator(elementRefList, measureObDefinitionElement, - checkIfDateTimeDiff, firstChildNode, parentSubTreeNode, firstChildNodeName); - } - break; - case "subTreeRef": - generateForSubTreeRef(elementRefList, measureObDefinitionElement, isClauseLogicGeneratable, - checkIfDateTimeDiff, localVariableName, firstChildNode, parentSubTreeNode); - break; - default: - break; - } - return preCodExp; - } - - /** - * @param elementRefList - * @param measureObDefinitionElement - * @param isClauseLogicGeneratable - * @param checkIfDateTimeDiff - * @param localVariableName - * @param firstChildNode - * @param parentSubTreeNode - * @throws XPathExpressionException - */ - private void generateForSubTreeRef(List elementRefList, Element measureObDefinitionElement, - boolean isClauseLogicGeneratable, boolean checkIfDateTimeDiff, String localVariableName, - Node firstChildNode, Node parentSubTreeNode) throws XPathExpressionException { - Node subTreeRefNodeLogic = clauseLogicMap.get(firstChildNode.getAttributes().getNamedItem("id").getNodeValue()); - Node subTreeRefParentNode = parentSubTreeNode.cloneNode(false); - subTreeRefParentNode.appendChild(subTreeRefNodeLogic.cloneNode(true)); - String firstSubTreeNodeName = subTreeRefNodeLogic.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - if (subTreeRefNodeLogic.getNodeName().equalsIgnoreCase("functionalOp")) { - if (firstSubTreeNodeName.equalsIgnoreCase(DATETIMEDIFF)) { - generateMOClauseLogicForDateTimeDiff(subTreeRefNodeLogic, elementRefList, measureObDefinitionElement); - } else { - if (isClauseLogicGeneratable) { - localVariableName = generateClauseLogicForChildsInsideFnxOp(subTreeRefParentNode, - checkIfDateTimeDiff); - } - generateMOClauseLogic(subTreeRefParentNode, elementRefList, measureObDefinitionElement, false, - localVariableName, checkIfDateTimeDiff); - } - } else { - if (isClauseLogicGeneratable) { - localVariableName = generateClauseLogicForChildsInsideFnxOp(subTreeRefParentNode, checkIfDateTimeDiff); - } - generateMOClauseLogic(subTreeRefParentNode, elementRefList, measureObDefinitionElement, false, - localVariableName, checkIfDateTimeDiff); - } - } - - private String generateForFunctionalOperator(List elementRefList, Element measureObDefinitionElement, - boolean checkIfDateTimeDiff, Node firstChildNode, Node parentSubTreeNode, String firstChildNodeName) - throws XPathExpressionException { - String localVariableName; - String preCodExp = null; - if (DATETIMEDIFF.equalsIgnoreCase(firstChildNodeName)) { - generateMOClauseLogicForDateTimeDiff(firstChildNode, elementRefList, measureObDefinitionElement); - } else { - Node childNode = firstChildNode.getFirstChild().getFirstChild(); - String childNodeName = ""; - boolean isDateTimeDiff = false; - if (childNode != null) { - childNodeName = childNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - } - if (childNodeName.equalsIgnoreCase(DATETIMEDIFF)) { - isDateTimeDiff = true; - } - if (!isDateTimeDiff) { - Node functionalOp = firstChildNode.cloneNode(true); - parentSubTreeNode.appendChild(functionalOp); - localVariableName = generateClauseLogicForChildsInsideFnxOp(parentSubTreeNode, false); - preCodExp = generateMOClauseLogic(parentSubTreeNode.getFirstChild(), elementRefList, - measureObDefinitionElement, false, localVariableName, checkIfDateTimeDiff); - } - } - return preCodExp; - } - - private String generateForRelationalOperator(Element measureObDefinitionElement, boolean isClauseLogicGeneratable, - boolean checkIfDateTimeDiff, String localVariableName, Node firstChildNode, Node parentSubTreeNode) - throws XPathExpressionException { - String preConditionExpressionValue = null; - Node relOpsNode = firstChildNode.cloneNode(true); - parentSubTreeNode.appendChild(relOpsNode); - Node relOpsFirstChild = relOpsNode.getFirstChild(); - // will not generate clause logic with timing LHS as DATETIMEDIFF - if (!relOpsFirstChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue() - .equalsIgnoreCase(DATETIMEDIFF)) { - if (isClauseLogicGeneratable) { - localVariableName = generateClauseLogicForChildsInsideFnxOp(parentSubTreeNode, checkIfDateTimeDiff); - } - if (localVariableName != null) { - List relOpLHSQdm = findFirstLHSElementRef(firstChildNode, new ArrayList<>(), - measureObDefinitionElement); - if (relOpLHSQdm != null && relOpLHSQdm.size() > 0) { - clauseLogicHasElementRef = true; - preConditionExpressionValue = generateValueAndExpressionTag(relOpLHSQdm, measureObDefinitionElement, localVariableName); - } else { - Element valueElementRelOp = measureObDefinitionElement.getOwnerDocument().createElement("value"); - valueElementRelOp.setAttribute(XSI_TYPE, "PQ"); - Element expressionElementRelOp = measureObDefinitionElement.getOwnerDocument() - .createElement("expression"); - expressionElementRelOp.setAttribute(VALUE, localVariableName); - valueElementRelOp.appendChild(expressionElementRelOp); - measureObDefinitionElement.appendChild(valueElementRelOp); - } - } - } - return preConditionExpressionValue; - } - - private void generateForSetOp(Element measureObDefinitionElement, boolean isClauseLogicGeneratable, - boolean checkIfDateTimeDiff, String localVariableName, Node firstChildNode, Node parentSubTreeNode) - throws XPathExpressionException { - Node setOpsNode = firstChildNode.cloneNode(true); - parentSubTreeNode.appendChild(setOpsNode); - if (isClauseLogicGeneratable) { - localVariableName = generateClauseLogicForChildsInsideFnxOp(parentSubTreeNode, checkIfDateTimeDiff); - } - if (localVariableName != null) { - Element valueElement = measureObDefinitionElement.getOwnerDocument().createElement("value"); - valueElement.setAttribute(XSI_TYPE, "PQ"); - Element expressionElement = measureObDefinitionElement.getOwnerDocument().createElement("expression"); - expressionElement.setAttribute(VALUE, localVariableName); - valueElement.appendChild(expressionElement); - measureObDefinitionElement.appendChild(valueElement); - } - } - - private Node getSubTreeNode(Node parentNode) { - Node subTreeNode = null; - if (parentNode != null) { - String nodeName = parentNode.getNodeName(); - if ("subTree".equals(nodeName)) { - subTreeNode = parentNode; - } else { - subTreeNode = getSubTreeNode(parentNode.getParentNode()); - } - } - return subTreeNode; - } - - /** - * Method to generate Measure Observation Clause logic for Date TimeDiff. - * - * @param clauseNodes - * - CLause Logic Nodes - * @param elementRefList - * - Element Ref List - * @param measureObDefinitionElement - * - DOM Element. - * @throws XPathExpressionException - * - Exception. - */ - private void generateMOClauseLogicForDateTimeDiff(Node clauseNodes, List elementRefList, - Element measureObDefinitionElement) throws XPathExpressionException { - NodeList childNodes = clauseNodes.getChildNodes(); - if (childNodes.getLength() >= DATETIMEDIFF_CHILD_COUNT) { // DATETIMEDIFF SHOULD HAVE TWO OR MORE CHILDREN. - boolean generateValueExpression = false; - String localVariableName = StringUtils.EMPTY; - StringBuilder preCondExp = new StringBuilder(); - Node firstChildNode; - for (int i = 0; i < childNodes.getLength(); i++) { - firstChildNode = childNodes.item(i); - String firstChildNodeName = firstChildNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); - Node parentSubTreeNode = getSubTreeNode(clauseNodes.getParentNode()); - switch (firstChildNode.getNodeName()) { - case "relationalOp": - Node relOpsNode = firstChildNode.cloneNode(true); - parentSubTreeNode = parentSubTreeNode.cloneNode(false); - parentSubTreeNode.appendChild(relOpsNode); - localVariableName = generateClauseLogicForChildsInsideFnxOp(parentSubTreeNode, true); - if (localVariableName != null) { - List relOpLHSQDM = findFirstLHSElementRef(firstChildNode, new ArrayList<>(), - measureObDefinitionElement); - if (relOpLHSQDM != null && relOpLHSQDM.size() > 0) { - preCondExp.append(generateValueAndExpressionTag(relOpLHSQDM, measureObDefinitionElement, localVariableName)); - clauseLogicHasElementRef = true; - } else { - Element valueElementRelOp = measureObDefinitionElement.getOwnerDocument() - .createElement("value"); - valueElementRelOp.setAttribute(XSI_TYPE, "PQ"); - Element expressionElementRelOp = measureObDefinitionElement.getOwnerDocument() - .createElement("expression"); - expressionElementRelOp.setAttribute(VALUE, localVariableName); - valueElementRelOp.appendChild(expressionElementRelOp); - measureObDefinitionElement.appendChild(valueElementRelOp); - } - } - break; - case "elementRef": - elementRefList.add(firstChildNode); - generateValueExpression = true; - break; - case "functionalOp": - if (INCLUDED_FUNCTIONAL_NAMES.containsKey(firstChildNodeName)) { - parentSubTreeNode = parentSubTreeNode.cloneNode(false); - if (!DATETIMEDIFF.equalsIgnoreCase(firstChildNodeName)) { - Node functionalOp = firstChildNode.cloneNode(true); - parentSubTreeNode.appendChild(functionalOp); - localVariableName = generateClauseLogicForChildsInsideFnxOp(parentSubTreeNode, true); - if (localVariableName != null) { - preCondExp.append(generateMOClauseLogic(functionalOp.getFirstChild(), new ArrayList<>(), - measureObDefinitionElement, false, localVariableName, false)); - } - } - } - break; - case "subTreeRef": - Node subTreeRefNodeLogic = clauseLogicMap.get(firstChildNode.getAttributes().getNamedItem("id").getNodeValue()); - if (!subTreeRefNodeLogic.getNodeName().equalsIgnoreCase("setOp") - && !subTreeRefNodeLogic.getNodeName().equalsIgnoreCase("elementRef")) { - Node subTreeRefParentNode = parentSubTreeNode.cloneNode(false); - subTreeRefParentNode.appendChild(subTreeRefNodeLogic); - preCondExp.append(generateMOClauseLogic(subTreeRefParentNode, new ArrayList<>(), - measureObDefinitionElement, true, localVariableName, true)); - } else if (subTreeRefNodeLogic.getNodeName().equalsIgnoreCase("elementRef")) { - elementRefList.add(subTreeRefNodeLogic); - generateValueExpression = true; - break; - } - break; - default: - break; - } - } - if (generateValueExpression || StringUtils.isNotEmpty(preCondExp)) { - String preConditionExpression = generateValueAndExpressionTag(elementRefList, measureObDefinitionElement, null); - if (StringUtils.isNotEmpty(preCondExp)) { - preConditionExpression = preCondExp.toString() + preConditionExpression; - } - generatePreCondition(measureObDefinitionElement, preConditionExpression, elementRefList); - } - } - } - - /** - * Method to find First QDM Element used in Clause Logic. - * - * @param firstChildNode - * - Clause Logic First Child Node. - * @param arrayList - * - Element Ref List - * @param measureObDefinitionElement - * - DOM Element. - * @return - Element Ref List - */ - private List findFirstLHSElementRef(Node firstChildNode, List arrayList, - Element measureObDefinitionElement) { - if (firstChildNode.hasChildNodes()) { - Node lhsNode = firstChildNode.getFirstChild(); - switch (lhsNode.getNodeName()) { - case "elementRef": - arrayList.add(lhsNode); - break; - case "setOp": - arrayList = null; - break; - case "relationalOp": - arrayList = findFirstLHSElementRef(lhsNode, arrayList, measureObDefinitionElement); - break; - case "functionalOp": - if (!lhsNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue().equalsIgnoreCase(DATETIMEDIFF)) { - if (lhsNode.hasChildNodes()) { - arrayList = findFirstLHSElementRef(lhsNode, arrayList, - measureObDefinitionElement); - break; - } else { - arrayList = null; - break; - } - } - break; - case "subTreeRef": - Node subTreeRefNodeLogic = clauseLogicMap - .get(lhsNode.getAttributes().getNamedItem("id").getNodeValue()); - arrayList = findFirstLHSElementRef(subTreeRefNodeLogic.getParentNode(), arrayList, - measureObDefinitionElement); - break; - default: - break; - } - } - return arrayList; - } - - /** - * This method generates clause logic For Functional Op. - * - * @param clauseNodes - * - Clause Logic Nodes. - * @param checkIfDatimeDiff - * - Boolean - * @return - LocalVariable Name. - * @throws XPathExpressionException - * - Exception - */ - private String generateClauseLogicForChildsInsideFnxOp(Node clauseNodes, boolean checkIfDatimeDiff) - throws XPathExpressionException { - Node generatedClauseEntryNode = generateSubTreeXML(clauseNodes, checkIfDatimeDiff); - String localVariableNameValue = null; - if (generatedClauseEntryNode != null) { - localVariableNameValue = findSubTreeDisplayName(clauseNodes); - localVariableNameValue = localVariableNameValue + "_" + UUIDUtilClient.uuid(5); - NodeList localVariableNode = ((Element) generatedClauseEntryNode) - .getElementsByTagName("localVariableName"); - if (localVariableNode != null) { - Element localVariableElement = (Element) localVariableNode.item(0); - if (localVariableElement != null) { - localVariableElement.setAttribute(VALUE, localVariableNameValue); - } else { - localVariableElement = generatedClauseEntryNode.getOwnerDocument() - .createElement("localVariableName"); - localVariableElement.setAttribute(VALUE, localVariableNameValue); - generatedClauseEntryNode.insertBefore(localVariableElement, - generatedClauseEntryNode.getFirstChild()); - } - } else { - Element localVariableElement = generatedClauseEntryNode.getOwnerDocument() - .createElement("localVariableName"); - localVariableElement.setAttribute(VALUE, localVariableNameValue); - generatedClauseEntryNode.insertBefore(localVariableElement, generatedClauseEntryNode.getFirstChild()); - } - } else { - if (getSubTreeNodeMap().containsKey(clauseNodes.getAttributes().getNamedItem("uuid").getNodeValue())) { - localVariableNameValue = findSubTreeDisplayName(clauseNodes); - } - } - return localVariableNameValue; - } - - /** - * Method to Generate precondition Tag. - * - * @param measureObDefinitionElement - * - DOM Element - * @param preConditionJoinExpressionValue - * - Expression String. - * @param elementRefList - * - Element Ref List. - */ - private void generatePreCondition(Element measureObDefinitionElement, String preConditionJoinExpressionValue, - List elementRefList) { - // precondition is created if and only if more than 1 qdm is applied. - if (elementRefList.size() > 1 && preConditionJoinExpressionValue != null - && preConditionJoinExpressionValue.length() > 0 || clauseLogicHasElementRef) { - Element preConditionElement = measureObDefinitionElement.getOwnerDocument().createElement("precondition"); - preConditionElement.setAttribute(TYPE_CODE, "PRCN"); - Element joinElement = measureObDefinitionElement.getOwnerDocument().createElement("join"); - joinElement.setAttribute(CLASS_CODE, "OBS"); - joinElement.setAttribute(MOOD_CODE, "DEF"); - Element valueElement = measureObDefinitionElement.getOwnerDocument().createElement("value"); - valueElement.setAttribute(XSI_TYPE, "ED"); - valueElement.setAttribute(VALUE, preConditionJoinExpressionValue); - joinElement.appendChild(valueElement); - preConditionElement.appendChild(joinElement); - measureObDefinitionElement.appendChild(preConditionElement); - } - } - - /** - * Method to Generate Value/Expression tags.This method also returns - * precondition Expression value. - * - * @param elementRefList - * -List - * @param measureObDefinitionElement - * -Element - * @param clauseLocalVariableName - * - Local Variable Name. - * @throws XPathExpressionException - * Exception - * @return String -String. - */ - private String generateValueAndExpressionTag(List elementRefList, - Element measureObDefinitionElement, - String clauseLocalVariableName) throws XPathExpressionException { - Node valueExpressionList = measureObDefinitionElement.getElementsByTagName("expression").item(0); - Element expressionElement; - if (valueExpressionList != null) { - expressionElement = (Element) valueExpressionList; - } else { - Element valueElement = measureObDefinitionElement.getOwnerDocument().createElement("value"); - valueElement.setAttribute(XSI_TYPE, "PQ"); - expressionElement = measureObDefinitionElement.getOwnerDocument().createElement("expression"); - valueElement.appendChild(expressionElement); - measureObDefinitionElement.appendChild(valueElement); - } - String expressionValue = ""; - if (expressionElement.getAttributes().getNamedItem("value") != null) { - expressionValue = expressionElement.getAttributes().getNamedItem("value").getNodeValue(); - } - String preConditionJoinExpressionValue = ""; - for (Node node : elementRefList) { - String qdmUUID = node.getAttributes().getNamedItem("id").getNodeValue(); - String xPath = "/measure/elementLookUp/qdm[@uuid ='" + qdmUUID + "']"; - Node qdmNode = me.getSimpleXmlProcessor().findNode(me.getSimpleXmlProcessor().getOriginalDoc(), xPath); - String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); - String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); - String ext = qdmName + "_" + dataType; - if (qdmNode.getAttributes().getNamedItem(INSTANCE) != null) { - ext = qdmNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + "_" + ext; - } - String qdmAttributeName = ""; - ext = StringUtils.deleteWhitespace(ext); - String root = node.getAttributes().getNamedItem(ID).getNodeValue(); - if (node.hasChildNodes()) { - ext = node.getFirstChild().getAttributes().getNamedItem("attrUUID").getNodeValue(); - qdmAttributeName = node.getFirstChild().getAttributes().getNamedItem(NAME).getNodeValue(); - } - Node idNodeQDM = me.getHqmfXmlProcessor().findNode(me.getHqmfXmlProcessor().getOriginalDoc(), - "//entry/*/id[@root='" + root + "'][@extension=\"" + ext + "\"]"); - if (idNodeQDM != null) { - Node entryNodeForElementRef = idNodeQDM.getParentNode().getParentNode(); - String localVariableName = clauseLocalVariableName; - if (clauseLocalVariableName == null) { - localVariableName = entryNodeForElementRef.getFirstChild().getAttributes().getNamedItem("value") - .getNodeValue(); - } - String attributeMapping = ""; - // if the parent of elementRef is setOp then we'll not - // be generating attribute Mapping for that particular QDM - // in value Expression - if (qdmAttributeName.length() != 0 && !node.getParentNode().getNodeName().equals("setOp")) { - attributeMapping = getQdmAttributeMapppingDotNotation(qdmAttributeName, dataType); - } - if (expressionValue.length() == 0) { - expressionValue = localVariableName; - preConditionJoinExpressionValue = localVariableName + ".getPatient().id"; - } else { - expressionValue += " - " + localVariableName; - preConditionJoinExpressionValue += " == " + localVariableName + ".getPatient().id"; - } - // appending attributeMapping for expressionValue - if (attributeMapping != null && attributeMapping.length() != 0) { - expressionValue += "." + attributeMapping; - } - } - } - expressionElement.setAttribute(VALUE, expressionValue); - return preConditionJoinExpressionValue; - } - - /** - * Method to generate component and MeasureObservationSection default tags. - * - * @param outputProcessor - * - XmlProcessor. - * @return - Node. - * @throws XPathExpressionException - * -Exception - */ - private Node createMeasureObservationSection(XmlProcessor outputProcessor) throws XPathExpressionException { - Node measureObservationSection = outputProcessor.findNode(outputProcessor.getOriginalDoc(), - "//component/measureObservationSection"); - if (measureObservationSection == null) { - return createNewMeasureObservationSection(outputProcessor); - } else { - return measureObservationSection.getParentNode(); - } - } - - public Node createNewMeasureObservationSection(XmlProcessor outputProcessor) { - Element componentElement = outputProcessor.getOriginalDoc().createElement("component"); - Attr nameSpaceAttr = outputProcessor.getOriginalDoc().createAttribute("xmlns:xsi"); - nameSpaceAttr.setNodeValue(nameSpace); - componentElement.setAttributeNodeNS(nameSpaceAttr); - Node measureObSectionElem = outputProcessor.getOriginalDoc().createElement("measureObservationSection"); - Element templateId = outputProcessor.getOriginalDoc().createElement(TEMPLATE_ID); - measureObSectionElem.appendChild(templateId); - Element itemChild = outputProcessor.getOriginalDoc().createElement(ITEM); - itemChild.setAttribute(ROOT, "2.16.840.1.113883.10.20.28.2.4"); - itemChild.setAttribute(EXTENSION, MEASURE_OBSERVATION_EXTENSION_VALUE); - templateId.appendChild(itemChild); - Element idElement = outputProcessor.getOriginalDoc().createElement(ID); - idElement.setAttribute(ROOT, java.util.UUID.randomUUID().toString()); - idElement.setAttribute(EXTENSION, "MeasureObservations"); - measureObSectionElem.appendChild(idElement); - Element codeElem = outputProcessor.getOriginalDoc().createElement(CODE); - codeElem.setAttribute(CODE, "57027-5"); - codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.6.1"); - codeElem.setAttribute(CODE_SYSTEM_NAME, "LOINC"); - measureObSectionElem.appendChild(codeElem); - Element titleElem = outputProcessor.getOriginalDoc().createElement(TITLE); - titleElem.setAttribute(VALUE, "Measure Observation Section"); - measureObSectionElem.appendChild(titleElem); - - // creating text for PopulationCriteria - Element textElem = outputProcessor.getOriginalDoc().createElement("text"); - - measureObSectionElem.appendChild(textElem); - componentElement.appendChild(measureObSectionElem); - outputProcessor.getOriginalDoc().getDocumentElement().appendChild(componentElement); - return componentElement; - } - - /** - * Get Measure Scoring type. - * - * @param me - * - MeasureExport - * @throws XPathExpressionException - * - {@link Exception} - */ - private void getMeasureScoringType(MeasureExport me) throws XPathExpressionException { - String xPathScoringType = "/measure/measureDetails/scoring/text()"; - javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); - scoringType = (String) xPath.evaluate(xPathScoringType, me.getSimpleXmlProcessor().getOriginalDoc(), - XPathConstants.STRING); - } - - /** - * Method to populate clause UUID and displayName. - * - * @param me - * - MeasureExport - * @throws XPathExpressionException - * - {@link Exception} - */ - private void generateClauseLogicMap(MeasureExport me) throws XPathExpressionException { - String xPath = "/measure/subTreeLookUp/subTree"; - NodeList subTreeNodeList = me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), - xPath); - for (int i = 0; i < subTreeNodeList.getLength(); i++) { - String uuid = subTreeNodeList.item(i).getAttributes().getNamedItem(UUID).getNodeValue(); - Node firstChildNode = subTreeNodeList.item(i).getFirstChild(); - if (firstChildNode != null) { - clauseLogicMap.put(uuid, firstChildNode); - } - } - } - - /** - * Method to populate all measure groupings in measureGroupingMap. - * - * @param me - * - MeasureExport - * @throws XPathExpressionException - * - {@link Exception} - */ - private void getAllMeasureGroupings(MeasureExport me) throws XPathExpressionException { - String xPath = "/measure/measureGrouping/group"; - NodeList measureGroupings = me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), - xPath); - for (int i = 0; i < measureGroupings.getLength(); i++) { - String measureGroupingSequence = measureGroupings.item(i).getAttributes().getNamedItem("sequence") - .getNodeValue(); - NodeList childNodeList = measureGroupings.item(i).getChildNodes(); - measureGroupingMap.put(Integer.parseInt(measureGroupingSequence), childNodeList); - } - } + private static final String MEASURE_OBSERVATION_EXTENSION_VALUE = "2018-05-01"; + + private static final int DATETIMEDIFF_CHILD_COUNT = 2; + + private Map clauseLogicMap = new HashMap<>(); + + private Map measureGroupingMap = new TreeMap<>(); + + private MeasureExport me; + + private String scoringType; + + private boolean clauseLogicHasElementRef = false; + + /** MAP of Functional Ops AGGREGATE that can be used in Measure Observation. */ + private static final Map FUNCTIONAL_OPS_AGGREGATE = + new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + /** MAP of Functional Ops INCLUDED FUNCTIONS that can be used in Measure Observation. */ + private static final Map INCLUDED_FUNCTIONAL_NAMES = + new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + static { + FUNCTIONAL_OPS_AGGREGATE.put("MAX", "MAX"); + FUNCTIONAL_OPS_AGGREGATE.put("MIN", "MIN"); + FUNCTIONAL_OPS_AGGREGATE.put("SUM", "SUM"); + FUNCTIONAL_OPS_AGGREGATE.put("AVG", "AVERAGE"); + FUNCTIONAL_OPS_AGGREGATE.put("COUNT", "COUNT"); + FUNCTIONAL_OPS_AGGREGATE.put("MEDIAN", "MEDIAN"); + FUNCTIONAL_OPS_AGGREGATE.put("DATETIMEDIFF", null); + INCLUDED_FUNCTIONAL_NAMES.put("FIRST", "FIRST"); + INCLUDED_FUNCTIONAL_NAMES.put("SECOND", "SECOND"); + INCLUDED_FUNCTIONAL_NAMES.put("THIRD", "THIRD"); + INCLUDED_FUNCTIONAL_NAMES.put("FOURTH", "FOURTH"); + INCLUDED_FUNCTIONAL_NAMES.put("FIFTH", "FIFTH"); + INCLUDED_FUNCTIONAL_NAMES.put("MOST RECENT", "MOST RECENT"); + INCLUDED_FUNCTIONAL_NAMES.put("COUNT", "COUNT"); + INCLUDED_FUNCTIONAL_NAMES.put("DATETIMEDIFF", "DATETIMEDIFF"); + } + + @Override + public String generate(MeasureExport me) throws Exception { + this.me = me; + setMeasureExport(me); + getMeasureScoringType(me); + generateClauseLogicMap(me); + getAllMeasureGroupings(me); + generateMeasureObSection(me); + return null; + } + + /** + * Get DotNotation from templates.xml. + * + * @param attributeName -String + * @param dataTypeName - String + * @throws XPathExpressionException -Exception + * @return String dot notation. + */ + private String getQdmAttributeMapppingDotNotation(String attributeName, String dataTypeName) + throws XPathExpressionException { + XmlProcessor templateXMLProcessor = QDMTemplateProcessorFactory.getTemplateProcessor(5.6); + String xPath = + "/templates/attributeMappings/attributeMapping[@qdmAttribute=\"" + attributeName + "\"]"; + Node attributeMappingNode = + templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xPath); + if (attributeMappingNode == null) { + xPath = + "/templates/attributeMappings/attributeMapping[@qdmAttribute='" + + attributeName + + "' and @datatypes = \"" + + dataTypeName.toLowerCase() + + "\"]"; + attributeMappingNode = + templateXMLProcessor.findNode(templateXMLProcessor.getOriginalDoc(), xPath); + } + if (attributeMappingNode != null) { + return attributeMappingNode.getAttributes().getNamedItem("dotNotation").getNodeValue(); + } else { + return null; + } + } + + /** + * Method to generate MeasureObservation Criteria Section. + * + * @param me - MeasureExport + * @throws XPathExpressionException - Exception + */ + private void generateMeasureObSection(MeasureExport me) throws XPathExpressionException { + String isInGrouping = ""; + for (Integer key : measureGroupingMap.keySet()) { + NodeList groupingChildList = measureGroupingMap.get(key); + for (int i = 0; i < groupingChildList.getLength(); i++) { + Node groupingChildListItem = groupingChildList.item(i); + + String popType = groupingChildListItem.getAttributes().getNamedItem(TYPE).getNodeValue(); + if (groupingChildList.item(i).getAttributes().getNamedItem(GROUPING_CHECK) != null) { + isInGrouping = + groupingChildList.item(i).getAttributes().getNamedItem(GROUPING_CHECK).getNodeValue(); + } + switch (popType) { + case "measureObservation": + if (isInGrouping != null && !isInGrouping.isEmpty()) { + if (isInGrouping.equalsIgnoreCase("true")) { + + Node measureObSectionComponentElement = + createMeasureObservationSection(me.getHqmfXmlProcessor()); + + generateMeasureObDefinition( + groupingChildListItem, measureObSectionComponentElement); + } + } else { + Node measureObSectionComponentElement = + createMeasureObservationSection(me.getHqmfXmlProcessor()); + + generateMeasureObDefinition(groupingChildListItem, measureObSectionComponentElement); + } + break; + case "denominator": + break; + case "numerator": + break; + default: + // do nothing. + break; + } + } + } + } + + /** + * Method to generate default criteriaTag for all population types included in measure grouping. + * + * @param measureObsClauseNode - Node + * @param measureObservationSecElement - Element + * @throws XPathExpressionException - Exception + */ + private void generateMeasureObDefinition( + Node measureObsClauseNode, Node measureObservationSecElement) { + + if (!measureObsClauseNode.hasChildNodes()) { + return; + } + + Document doc = measureObservationSecElement.getOwnerDocument(); + Comment comment = + doc.createComment( + "Definition for " + + measureObsClauseNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue()); + Element definitionElement = doc.createElement("definition"); + Element measureObDefinitionElement = doc.createElement("measureObservationDefinition"); + measureObDefinitionElement.setAttribute(CLASS_CODE, "OBS"); + measureObDefinitionElement.setAttribute(MOOD_CODE, "DEF"); + Element idElem = doc.createElement(ID); + idElem.setAttribute( + ROOT, measureObsClauseNode.getAttributes().getNamedItem("uuid").getNodeValue()); + idElem.setAttribute(EXTENSION, "MeasureObservation"); + measureObDefinitionElement.appendChild(idElem); + + Element codeElem = doc.createElement(CODE); + codeElem.setAttribute(CODE, "AGGREGATE"); + codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.5.4"); + measureObDefinitionElement.appendChild(codeElem); + generateCQLLogicForMeasureObservation(measureObsClauseNode, measureObDefinitionElement); + definitionElement.appendChild(measureObDefinitionElement); + Element measurObSectionElement = (Element) measureObservationSecElement.getFirstChild(); + measurObSectionElement.appendChild(comment); + measurObSectionElement.appendChild(definitionElement); + } + + private void generateCQLLogicForMeasureObservation( + Node measureObservationNode, Element measureObservationElementNode) { + + if (!measureObservationNode.hasChildNodes()) { + return; + } + + String extensionAttribute = ""; + + Document doc = measureObservationElementNode.getOwnerDocument(); + + Element valueElement = doc.createElement(VALUE); + valueElement.setAttribute("xsi:type", "INT"); + valueElement.setAttribute("nullFlavor", "DER"); + + Node firstChildNode = measureObservationNode.getFirstChild(); + String firstChildNodeName = firstChildNode.getNodeName(); + + if ("cqlfunction".equals(firstChildNodeName)) { + + String functionName = + firstChildNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + extensionAttribute += functionName; + + Element expressionElement = createExpressionTag(measureObservationNode, doc, firstChildNode); + valueElement.appendChild(expressionElement); + measureObservationElementNode.appendChild(valueElement); + + } else if ("cqlaggfunction".equals(firstChildNodeName)) { + + String aggFunctionName = + firstChildNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + String aggFunctionHQMFName = getAggMethodCode(aggFunctionName); + + extensionAttribute += aggFunctionHQMFName + " Of "; + + Node aggNodeChild = firstChildNode.getFirstChild(); + if ("cqlfunction".equals(aggNodeChild.getNodeName())) { + + String functionName = + aggNodeChild.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + extensionAttribute += functionName; + + Element expressionElement = createExpressionTag(measureObservationNode, doc, aggNodeChild); + valueElement.appendChild(expressionElement); + measureObservationElementNode.appendChild(valueElement); + } + + Element methodCodeElement = doc.createElement("methodCode"); + Element itemElement = doc.createElement(ITEM); + itemElement.setAttribute(CODE, aggFunctionHQMFName); + itemElement.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.5.84"); + + methodCodeElement.appendChild(itemElement); + measureObservationElementNode.appendChild(methodCodeElement); + } + + if (extensionAttribute.length() > 0) { + NodeList idList = measureObservationElementNode.getElementsByTagName(ID); + if (idList.getLength() > 0) { + Node id = idList.item(0); + id.getAttributes().getNamedItem(EXTENSION).setNodeValue(extensionAttribute); + } + } + + // check for associated population id and add related HQMF nodes. + handleMeasureObservationAssociations(measureObservationNode, measureObservationElementNode); + } + + private void handleMeasureObservationAssociations( + Node measureObservationNode, Element measureObDefinitionElement) { + Node associatedPopulationNode = null; + try { + associatedPopulationNode = getAssociatedPopulationNode(measureObservationNode); + if (associatedPopulationNode != null && associatedPopulationNode.hasChildNodes()) { + + // the measure observation criteria reference root and extension should come from the root + // and extension values of the associated + // population + String measureObservationCriteriaReferenceIdRoot = + associatedPopulationNode.getAttributes().getNamedItem("uuid").getNodeValue(); + String measureObservationCriteriaReferenceIdExtension = + associatedPopulationNode.getAttributes().getNamedItem("type").getNodeValue(); + + Document doc = measureObDefinitionElement.getOwnerDocument(); + + Element component = doc.createElement("component"); + component.setAttribute(TYPE_CODE, "COMP"); + + Element criteriaReference = doc.createElement("criteriaReference"); + criteriaReference.setAttribute(CLASS_CODE, "OBS"); + criteriaReference.setAttribute(MOOD_CODE, "EVN"); + + Element id = doc.createElement(ID); + id.setAttribute(ROOT, measureObservationCriteriaReferenceIdRoot); + id.setAttribute(EXTENSION, measureObservationCriteriaReferenceIdExtension); + + measureObDefinitionElement.appendChild(component); + component.appendChild(criteriaReference); + criteriaReference.appendChild(id); + } + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + } + + private Node getAssociatedPopulationNode(Node measureObservationNode) + throws XPathExpressionException { + String associatedPopulationUUID = getAssociatedPopulationUUID(measureObservationNode); + String associatedClauseXPath = + "//measureGrouping/group/clause[@uuid = '" + associatedPopulationUUID + "']"; + + Node associatedPopulationNode = + me.getSimpleXmlProcessor() + .findNode(measureObservationNode.getOwnerDocument(), associatedClauseXPath); + return associatedPopulationNode; + } + + public String getAssociatedPopulationUUID(Node msrObsClauseNode) { + String associatedPopuUUID = ""; + + if (scoringType.equalsIgnoreCase("Continuous Variable")) { + associatedPopuUUID = findMeasurePopulationUUID(msrObsClauseNode.getParentNode()); + } else { + if (msrObsClauseNode.getAttributes().getNamedItem(ASSOCIATED_POPULATION_UUID) != null) { + associatedPopuUUID = + msrObsClauseNode + .getAttributes() + .getNamedItem(ASSOCIATED_POPULATION_UUID) + .getNodeValue(); + } + } + + return associatedPopuUUID; + } + + private String findMeasurePopulationUUID(Node parentNode) { + + String uuid = ""; + + NodeList nodeList = parentNode.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + if (MEASURE_POPULATION.equals(node.getAttributes().getNamedItem(TYPE).getNodeValue())) { + uuid = node.getAttributes().getNamedItem(UUID).getNodeValue(); + break; + } + } + + return uuid; + } + + /** + * Create tag for Measure Observation. + * + * @param item + * @param doc + * @param cqlFunctionNode + * @return + */ + public Element createExpressionTag(Node item, Document doc, Node cqlFunctionNode) { + + Element expressionElement = doc.createElement("expression"); + String cqlFunctionNameValue = + cqlFunctionNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + + String cqlLibraryNameXPath = "//cqlLookUp/library"; + + try { + + Node cqlLibraryNameNode = + me.getSimpleXmlProcessor().findNode(item.getOwnerDocument(), cqlLibraryNameXPath); + String libraryName = ""; + if (cqlLibraryNameNode != null) { + libraryName = cqlLibraryNameNode.getTextContent(); + } + String expressionValueAttribute = libraryName + ".\"" + cqlFunctionNameValue + "\""; + expressionElement.setAttribute(VALUE, expressionValueAttribute); + + } catch (XPathExpressionException e) { + e.printStackTrace(); + } + + return expressionElement; + } + + private String getAggMethodCode(String aggregateFunctionName) { + + String hqmfCodeForAggFunction = ""; + switch (aggregateFunctionName) { + case "Count": + case "Sum": + case "Average": + case "Median": + case "Mode": + hqmfCodeForAggFunction = aggregateFunctionName.toUpperCase(); + break; + + case "Sample Standard Deviation": + hqmfCodeForAggFunction = "STDEV.S"; + break; + case "Sample Variance": + hqmfCodeForAggFunction = "VARIANCE.S"; + break; + case "Population Standard Deviation": + hqmfCodeForAggFunction = "STDEV.P"; + break; + case "Population Variance": + hqmfCodeForAggFunction = "VARIANCE.P"; + break; + case "Minimum": + hqmfCodeForAggFunction = "MIN"; + break; + case "Maximum": + hqmfCodeForAggFunction = "MAX"; + break; + default: + break; + } + + return hqmfCodeForAggFunction; + } + + /** + * Method to find Node's Parent - Subtree Name. + * + * @param node - Node + * @return SubTree DisplayName. + */ + private String findSubTreeDisplayName(Node node) { + String displayName = null; + if (node != null) { + String nodeName = node.getNodeName(); + if ("subTree".equals(nodeName)) { + displayName = node.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + if (node.getAttributes().getNamedItem("qdmVariable") != null + && node.getAttributes() + .getNamedItem("qdmVariable") + .getNodeValue() + .equalsIgnoreCase("true")) { + displayName = "qdm_var_" + displayName.replace("$", ""); + } + } else { + displayName = findSubTreeDisplayName(node.getParentNode()); + } + } + return StringUtils.deleteWhitespace(displayName); + } + + /** + * Method to Evaluate Clause logic Node types and generate Clause Logic in Data Criteria section + * if applicable and generates value expression/precondition. + * + * @param clauseNodes - Clause Logic Nodes + * @param elementRefList - Element Ref List + * @param measureObDefinitionElement - DOM element + * @throws XPathExpressionException - Exception. + */ + private String generateMOClauseLogic( + Node clauseNodes, + List elementRefList, + Element measureObDefinitionElement, + boolean isClauseLogicGeneratable, + String variableName, + boolean checkIfDateTimeDiff) + throws XPathExpressionException { + String localVariableName = null; + Node firstChildNode = null; + Node parentSubTreeNode = null; + String preCodExp = null; + if (variableName != null) { + localVariableName = variableName; + } + if (isClauseLogicGeneratable) { + firstChildNode = clauseNodes.getFirstChild(); + if (clauseNodes.getParentNode() != null) { + parentSubTreeNode = clauseNodes.getParentNode().cloneNode(false); + } else if (clauseNodes.getNodeName().equals("subTree")) { + parentSubTreeNode = clauseNodes.cloneNode(false); + } + } else { + if (checkIfParentSubTree(clauseNodes).getNodeName().equalsIgnoreCase("subTree")) { + if (clauseNodes.getNodeName().equals("elementRef")) { + firstChildNode = clauseNodes; + } else { + firstChildNode = clauseNodes.getFirstChild(); + } + parentSubTreeNode = clauseNodes.cloneNode(false); + } else { + firstChildNode = clauseNodes; + parentSubTreeNode = clauseNodes.getParentNode().cloneNode(false); + } + } + String firstChildNodeName = + firstChildNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + switch (firstChildNode.getNodeName()) { + case "setOp": + generateForSetOp( + measureObDefinitionElement, + isClauseLogicGeneratable, + checkIfDateTimeDiff, + localVariableName, + firstChildNode, + parentSubTreeNode); + break; + case "relationalOp": + preCodExp = + generateForRelationalOperator( + measureObDefinitionElement, + isClauseLogicGeneratable, + checkIfDateTimeDiff, + localVariableName, + firstChildNode, + parentSubTreeNode); + break; + case "elementRef": + elementRefList.add(firstChildNode); + if (localVariableName != null) { + preCodExp = + generateValueAndExpressionTag( + elementRefList, measureObDefinitionElement, localVariableName); + } else { + preCodExp = + generateValueAndExpressionTag(elementRefList, measureObDefinitionElement, null); + } + break; + case "functionalOp": + if (INCLUDED_FUNCTIONAL_NAMES.containsKey(firstChildNodeName)) { + preCodExp = + generateForFunctionalOperator( + elementRefList, + measureObDefinitionElement, + checkIfDateTimeDiff, + firstChildNode, + parentSubTreeNode, + firstChildNodeName); + } + break; + case "subTreeRef": + generateForSubTreeRef( + elementRefList, + measureObDefinitionElement, + isClauseLogicGeneratable, + checkIfDateTimeDiff, + localVariableName, + firstChildNode, + parentSubTreeNode); + break; + default: + break; + } + return preCodExp; + } + + /** + * @param elementRefList + * @param measureObDefinitionElement + * @param isClauseLogicGeneratable + * @param checkIfDateTimeDiff + * @param localVariableName + * @param firstChildNode + * @param parentSubTreeNode + * @throws XPathExpressionException + */ + private void generateForSubTreeRef( + List elementRefList, + Element measureObDefinitionElement, + boolean isClauseLogicGeneratable, + boolean checkIfDateTimeDiff, + String localVariableName, + Node firstChildNode, + Node parentSubTreeNode) + throws XPathExpressionException { + Node subTreeRefNodeLogic = + clauseLogicMap.get(firstChildNode.getAttributes().getNamedItem("id").getNodeValue()); + Node subTreeRefParentNode = parentSubTreeNode.cloneNode(false); + subTreeRefParentNode.appendChild(subTreeRefNodeLogic.cloneNode(true)); + String firstSubTreeNodeName = + subTreeRefNodeLogic.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + if (subTreeRefNodeLogic.getNodeName().equalsIgnoreCase("functionalOp")) { + if (firstSubTreeNodeName.equalsIgnoreCase(DATETIMEDIFF)) { + generateMOClauseLogicForDateTimeDiff( + subTreeRefNodeLogic, elementRefList, measureObDefinitionElement); + } else { + if (isClauseLogicGeneratable) { + localVariableName = + generateClauseLogicForChildsInsideFnxOp(subTreeRefParentNode, checkIfDateTimeDiff); + } + generateMOClauseLogic( + subTreeRefParentNode, + elementRefList, + measureObDefinitionElement, + false, + localVariableName, + checkIfDateTimeDiff); + } + } else { + if (isClauseLogicGeneratable) { + localVariableName = + generateClauseLogicForChildsInsideFnxOp(subTreeRefParentNode, checkIfDateTimeDiff); + } + generateMOClauseLogic( + subTreeRefParentNode, + elementRefList, + measureObDefinitionElement, + false, + localVariableName, + checkIfDateTimeDiff); + } + } + + private String generateForFunctionalOperator( + List elementRefList, + Element measureObDefinitionElement, + boolean checkIfDateTimeDiff, + Node firstChildNode, + Node parentSubTreeNode, + String firstChildNodeName) + throws XPathExpressionException { + String localVariableName; + String preCodExp = null; + if (DATETIMEDIFF.equalsIgnoreCase(firstChildNodeName)) { + generateMOClauseLogicForDateTimeDiff( + firstChildNode, elementRefList, measureObDefinitionElement); + } else { + Node childNode = firstChildNode.getFirstChild().getFirstChild(); + String childNodeName = ""; + boolean isDateTimeDiff = false; + if (childNode != null) { + childNodeName = childNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + } + if (childNodeName.equalsIgnoreCase(DATETIMEDIFF)) { + isDateTimeDiff = true; + } + if (!isDateTimeDiff) { + Node functionalOp = firstChildNode.cloneNode(true); + parentSubTreeNode.appendChild(functionalOp); + localVariableName = generateClauseLogicForChildsInsideFnxOp(parentSubTreeNode, false); + preCodExp = + generateMOClauseLogic( + parentSubTreeNode.getFirstChild(), + elementRefList, + measureObDefinitionElement, + false, + localVariableName, + checkIfDateTimeDiff); + } + } + return preCodExp; + } + + private String generateForRelationalOperator( + Element measureObDefinitionElement, + boolean isClauseLogicGeneratable, + boolean checkIfDateTimeDiff, + String localVariableName, + Node firstChildNode, + Node parentSubTreeNode) + throws XPathExpressionException { + String preConditionExpressionValue = null; + Node relOpsNode = firstChildNode.cloneNode(true); + parentSubTreeNode.appendChild(relOpsNode); + Node relOpsFirstChild = relOpsNode.getFirstChild(); + // will not generate clause logic with timing LHS as DATETIMEDIFF + if (!relOpsFirstChild + .getAttributes() + .getNamedItem(DISPLAY_NAME) + .getNodeValue() + .equalsIgnoreCase(DATETIMEDIFF)) { + if (isClauseLogicGeneratable) { + localVariableName = + generateClauseLogicForChildsInsideFnxOp(parentSubTreeNode, checkIfDateTimeDiff); + } + if (localVariableName != null) { + List relOpLHSQdm = + findFirstLHSElementRef(firstChildNode, new ArrayList<>(), measureObDefinitionElement); + if (relOpLHSQdm != null && relOpLHSQdm.size() > 0) { + clauseLogicHasElementRef = true; + preConditionExpressionValue = + generateValueAndExpressionTag( + relOpLHSQdm, measureObDefinitionElement, localVariableName); + } else { + Element valueElementRelOp = + measureObDefinitionElement.getOwnerDocument().createElement("value"); + valueElementRelOp.setAttribute(XSI_TYPE, "PQ"); + Element expressionElementRelOp = + measureObDefinitionElement.getOwnerDocument().createElement("expression"); + expressionElementRelOp.setAttribute(VALUE, localVariableName); + valueElementRelOp.appendChild(expressionElementRelOp); + measureObDefinitionElement.appendChild(valueElementRelOp); + } + } + } + return preConditionExpressionValue; + } + + private void generateForSetOp( + Element measureObDefinitionElement, + boolean isClauseLogicGeneratable, + boolean checkIfDateTimeDiff, + String localVariableName, + Node firstChildNode, + Node parentSubTreeNode) + throws XPathExpressionException { + Node setOpsNode = firstChildNode.cloneNode(true); + parentSubTreeNode.appendChild(setOpsNode); + if (isClauseLogicGeneratable) { + localVariableName = + generateClauseLogicForChildsInsideFnxOp(parentSubTreeNode, checkIfDateTimeDiff); + } + if (localVariableName != null) { + Element valueElement = measureObDefinitionElement.getOwnerDocument().createElement("value"); + valueElement.setAttribute(XSI_TYPE, "PQ"); + Element expressionElement = + measureObDefinitionElement.getOwnerDocument().createElement("expression"); + expressionElement.setAttribute(VALUE, localVariableName); + valueElement.appendChild(expressionElement); + measureObDefinitionElement.appendChild(valueElement); + } + } + + private Node getSubTreeNode(Node parentNode) { + Node subTreeNode = null; + if (parentNode != null) { + String nodeName = parentNode.getNodeName(); + if ("subTree".equals(nodeName)) { + subTreeNode = parentNode; + } else { + subTreeNode = getSubTreeNode(parentNode.getParentNode()); + } + } + return subTreeNode; + } + + /** + * Method to generate Measure Observation Clause logic for Date TimeDiff. + * + * @param clauseNodes - CLause Logic Nodes + * @param elementRefList - Element Ref List + * @param measureObDefinitionElement - DOM Element. + * @throws XPathExpressionException - Exception. + */ + private void generateMOClauseLogicForDateTimeDiff( + Node clauseNodes, List elementRefList, Element measureObDefinitionElement) + throws XPathExpressionException { + NodeList childNodes = clauseNodes.getChildNodes(); + if (childNodes.getLength() + >= DATETIMEDIFF_CHILD_COUNT) { // DATETIMEDIFF SHOULD HAVE TWO OR MORE CHILDREN. + boolean generateValueExpression = false; + String localVariableName = StringUtils.EMPTY; + StringBuilder preCondExp = new StringBuilder(); + Node firstChildNode; + for (int i = 0; i < childNodes.getLength(); i++) { + firstChildNode = childNodes.item(i); + String firstChildNodeName = + firstChildNode.getAttributes().getNamedItem(DISPLAY_NAME).getNodeValue(); + Node parentSubTreeNode = getSubTreeNode(clauseNodes.getParentNode()); + switch (firstChildNode.getNodeName()) { + case "relationalOp": + Node relOpsNode = firstChildNode.cloneNode(true); + parentSubTreeNode = parentSubTreeNode.cloneNode(false); + parentSubTreeNode.appendChild(relOpsNode); + localVariableName = generateClauseLogicForChildsInsideFnxOp(parentSubTreeNode, true); + if (localVariableName != null) { + List relOpLHSQDM = + findFirstLHSElementRef( + firstChildNode, new ArrayList<>(), measureObDefinitionElement); + if (relOpLHSQDM != null && relOpLHSQDM.size() > 0) { + preCondExp.append( + generateValueAndExpressionTag( + relOpLHSQDM, measureObDefinitionElement, localVariableName)); + clauseLogicHasElementRef = true; + } else { + Element valueElementRelOp = + measureObDefinitionElement.getOwnerDocument().createElement("value"); + valueElementRelOp.setAttribute(XSI_TYPE, "PQ"); + Element expressionElementRelOp = + measureObDefinitionElement.getOwnerDocument().createElement("expression"); + expressionElementRelOp.setAttribute(VALUE, localVariableName); + valueElementRelOp.appendChild(expressionElementRelOp); + measureObDefinitionElement.appendChild(valueElementRelOp); + } + } + break; + case "elementRef": + elementRefList.add(firstChildNode); + generateValueExpression = true; + break; + case "functionalOp": + if (INCLUDED_FUNCTIONAL_NAMES.containsKey(firstChildNodeName)) { + parentSubTreeNode = parentSubTreeNode.cloneNode(false); + if (!DATETIMEDIFF.equalsIgnoreCase(firstChildNodeName)) { + Node functionalOp = firstChildNode.cloneNode(true); + parentSubTreeNode.appendChild(functionalOp); + localVariableName = + generateClauseLogicForChildsInsideFnxOp(parentSubTreeNode, true); + if (localVariableName != null) { + preCondExp.append( + generateMOClauseLogic( + functionalOp.getFirstChild(), + new ArrayList<>(), + measureObDefinitionElement, + false, + localVariableName, + false)); + } + } + } + break; + case "subTreeRef": + Node subTreeRefNodeLogic = + clauseLogicMap.get( + firstChildNode.getAttributes().getNamedItem("id").getNodeValue()); + if (!subTreeRefNodeLogic.getNodeName().equalsIgnoreCase("setOp") + && !subTreeRefNodeLogic.getNodeName().equalsIgnoreCase("elementRef")) { + Node subTreeRefParentNode = parentSubTreeNode.cloneNode(false); + subTreeRefParentNode.appendChild(subTreeRefNodeLogic); + preCondExp.append( + generateMOClauseLogic( + subTreeRefParentNode, + new ArrayList<>(), + measureObDefinitionElement, + true, + localVariableName, + true)); + } else if (subTreeRefNodeLogic.getNodeName().equalsIgnoreCase("elementRef")) { + elementRefList.add(subTreeRefNodeLogic); + generateValueExpression = true; + break; + } + break; + default: + break; + } + } + if (generateValueExpression || StringUtils.isNotEmpty(preCondExp)) { + String preConditionExpression = + generateValueAndExpressionTag(elementRefList, measureObDefinitionElement, null); + if (StringUtils.isNotEmpty(preCondExp)) { + preConditionExpression = preCondExp.toString() + preConditionExpression; + } + generatePreCondition(measureObDefinitionElement, preConditionExpression, elementRefList); + } + } + } + + /** + * Method to find First QDM Element used in Clause Logic. + * + * @param firstChildNode - Clause Logic First Child Node. + * @param arrayList - Element Ref List + * @param measureObDefinitionElement - DOM Element. + * @return - Element Ref List + */ + private List findFirstLHSElementRef( + Node firstChildNode, List arrayList, Element measureObDefinitionElement) { + if (firstChildNode.hasChildNodes()) { + Node lhsNode = firstChildNode.getFirstChild(); + switch (lhsNode.getNodeName()) { + case "elementRef": + arrayList.add(lhsNode); + break; + case "setOp": + arrayList = null; + break; + case "relationalOp": + arrayList = findFirstLHSElementRef(lhsNode, arrayList, measureObDefinitionElement); + break; + case "functionalOp": + if (!lhsNode + .getAttributes() + .getNamedItem(DISPLAY_NAME) + .getNodeValue() + .equalsIgnoreCase(DATETIMEDIFF)) { + if (lhsNode.hasChildNodes()) { + arrayList = findFirstLHSElementRef(lhsNode, arrayList, measureObDefinitionElement); + break; + } else { + arrayList = null; + break; + } + } + break; + case "subTreeRef": + Node subTreeRefNodeLogic = + clauseLogicMap.get(lhsNode.getAttributes().getNamedItem("id").getNodeValue()); + arrayList = + findFirstLHSElementRef( + subTreeRefNodeLogic.getParentNode(), arrayList, measureObDefinitionElement); + break; + default: + break; + } + } + return arrayList; + } + + /** + * This method generates clause logic For Functional Op. + * + * @param clauseNodes - Clause Logic Nodes. + * @param checkIfDatimeDiff - Boolean + * @return - LocalVariable Name. + * @throws XPathExpressionException - Exception + */ + private String generateClauseLogicForChildsInsideFnxOp( + Node clauseNodes, boolean checkIfDatimeDiff) throws XPathExpressionException { + Node generatedClauseEntryNode = generateSubTreeXML(clauseNodes, checkIfDatimeDiff); + String localVariableNameValue = null; + if (generatedClauseEntryNode != null) { + localVariableNameValue = findSubTreeDisplayName(clauseNodes); + localVariableNameValue = localVariableNameValue + "_" + UUIDUtilClient.uuid(5); + NodeList localVariableNode = + ((Element) generatedClauseEntryNode).getElementsByTagName("localVariableName"); + if (localVariableNode != null) { + Element localVariableElement = (Element) localVariableNode.item(0); + if (localVariableElement != null) { + localVariableElement.setAttribute(VALUE, localVariableNameValue); + } else { + localVariableElement = + generatedClauseEntryNode.getOwnerDocument().createElement("localVariableName"); + localVariableElement.setAttribute(VALUE, localVariableNameValue); + generatedClauseEntryNode.insertBefore( + localVariableElement, generatedClauseEntryNode.getFirstChild()); + } + } else { + Element localVariableElement = + generatedClauseEntryNode.getOwnerDocument().createElement("localVariableName"); + localVariableElement.setAttribute(VALUE, localVariableNameValue); + generatedClauseEntryNode.insertBefore( + localVariableElement, generatedClauseEntryNode.getFirstChild()); + } + } else { + if (getSubTreeNodeMap() + .containsKey(clauseNodes.getAttributes().getNamedItem("uuid").getNodeValue())) { + localVariableNameValue = findSubTreeDisplayName(clauseNodes); + } + } + return localVariableNameValue; + } + + /** + * Method to Generate precondition Tag. + * + * @param measureObDefinitionElement - DOM Element + * @param preConditionJoinExpressionValue - Expression String. + * @param elementRefList - Element Ref List. + */ + private void generatePreCondition( + Element measureObDefinitionElement, + String preConditionJoinExpressionValue, + List elementRefList) { + // precondition is created if and only if more than 1 qdm is applied. + if (elementRefList.size() > 1 + && preConditionJoinExpressionValue != null + && preConditionJoinExpressionValue.length() > 0 + || clauseLogicHasElementRef) { + Element preConditionElement = + measureObDefinitionElement.getOwnerDocument().createElement("precondition"); + preConditionElement.setAttribute(TYPE_CODE, "PRCN"); + Element joinElement = measureObDefinitionElement.getOwnerDocument().createElement("join"); + joinElement.setAttribute(CLASS_CODE, "OBS"); + joinElement.setAttribute(MOOD_CODE, "DEF"); + Element valueElement = measureObDefinitionElement.getOwnerDocument().createElement("value"); + valueElement.setAttribute(XSI_TYPE, "ED"); + valueElement.setAttribute(VALUE, preConditionJoinExpressionValue); + joinElement.appendChild(valueElement); + preConditionElement.appendChild(joinElement); + measureObDefinitionElement.appendChild(preConditionElement); + } + } + + /** + * Method to Generate Value/Expression tags.This method also returns precondition Expression + * value. + * + * @param elementRefList -List + * @param measureObDefinitionElement -Element + * @param clauseLocalVariableName - Local Variable Name. + * @throws XPathExpressionException Exception + * @return String -String. + */ + private String generateValueAndExpressionTag( + List elementRefList, Element measureObDefinitionElement, String clauseLocalVariableName) + throws XPathExpressionException { + Node valueExpressionList = + measureObDefinitionElement.getElementsByTagName("expression").item(0); + Element expressionElement; + if (valueExpressionList != null) { + expressionElement = (Element) valueExpressionList; + } else { + Element valueElement = measureObDefinitionElement.getOwnerDocument().createElement("value"); + valueElement.setAttribute(XSI_TYPE, "PQ"); + expressionElement = measureObDefinitionElement.getOwnerDocument().createElement("expression"); + valueElement.appendChild(expressionElement); + measureObDefinitionElement.appendChild(valueElement); + } + String expressionValue = ""; + if (expressionElement.getAttributes().getNamedItem("value") != null) { + expressionValue = expressionElement.getAttributes().getNamedItem("value").getNodeValue(); + } + String preConditionJoinExpressionValue = ""; + for (Node node : elementRefList) { + String qdmUUID = node.getAttributes().getNamedItem("id").getNodeValue(); + String xPath = "/measure/elementLookUp/qdm[@uuid ='" + qdmUUID + "']"; + Node qdmNode = + me.getSimpleXmlProcessor().findNode(me.getSimpleXmlProcessor().getOriginalDoc(), xPath); + String dataType = qdmNode.getAttributes().getNamedItem("datatype").getNodeValue(); + String qdmName = qdmNode.getAttributes().getNamedItem(NAME).getNodeValue(); + String ext = qdmName + "_" + dataType; + if (qdmNode.getAttributes().getNamedItem(INSTANCE) != null) { + ext = qdmNode.getAttributes().getNamedItem(INSTANCE).getNodeValue() + "_" + ext; + } + String qdmAttributeName = ""; + ext = StringUtils.deleteWhitespace(ext); + String root = node.getAttributes().getNamedItem(ID).getNodeValue(); + if (node.hasChildNodes()) { + ext = node.getFirstChild().getAttributes().getNamedItem("attrUUID").getNodeValue(); + qdmAttributeName = node.getFirstChild().getAttributes().getNamedItem(NAME).getNodeValue(); + } + Node idNodeQDM = + me.getHqmfXmlProcessor() + .findNode( + me.getHqmfXmlProcessor().getOriginalDoc(), + "//entry/*/id[@root='" + root + "'][@extension=\"" + ext + "\"]"); + if (idNodeQDM != null) { + Node entryNodeForElementRef = idNodeQDM.getParentNode().getParentNode(); + String localVariableName = clauseLocalVariableName; + if (clauseLocalVariableName == null) { + localVariableName = + entryNodeForElementRef + .getFirstChild() + .getAttributes() + .getNamedItem("value") + .getNodeValue(); + } + String attributeMapping = ""; + // if the parent of elementRef is setOp then we'll not + // be generating attribute Mapping for that particular QDM + // in value Expression + if (qdmAttributeName.length() != 0 && !node.getParentNode().getNodeName().equals("setOp")) { + attributeMapping = getQdmAttributeMapppingDotNotation(qdmAttributeName, dataType); + } + if (expressionValue.length() == 0) { + expressionValue = localVariableName; + preConditionJoinExpressionValue = localVariableName + ".getPatient().id"; + } else { + expressionValue += " - " + localVariableName; + preConditionJoinExpressionValue += " == " + localVariableName + ".getPatient().id"; + } + // appending attributeMapping for expressionValue + if (attributeMapping != null && attributeMapping.length() != 0) { + expressionValue += "." + attributeMapping; + } + } + } + expressionElement.setAttribute(VALUE, expressionValue); + return preConditionJoinExpressionValue; + } + + /** + * Method to generate component and MeasureObservationSection default tags. + * + * @param outputProcessor - XmlProcessor. + * @return - Node. + * @throws XPathExpressionException -Exception + */ + private Node createMeasureObservationSection(XmlProcessor outputProcessor) + throws XPathExpressionException { + Node measureObservationSection = + outputProcessor.findNode( + outputProcessor.getOriginalDoc(), "//component/measureObservationSection"); + if (measureObservationSection == null) { + return createNewMeasureObservationSection(outputProcessor); + } else { + return measureObservationSection.getParentNode(); + } + } + + public Node createNewMeasureObservationSection(XmlProcessor outputProcessor) { + Element componentElement = outputProcessor.getOriginalDoc().createElement("component"); + Attr nameSpaceAttr = outputProcessor.getOriginalDoc().createAttribute("xmlns:xsi"); + nameSpaceAttr.setNodeValue(nameSpace); + componentElement.setAttributeNodeNS(nameSpaceAttr); + Node measureObSectionElem = + outputProcessor.getOriginalDoc().createElement("measureObservationSection"); + Element templateId = outputProcessor.getOriginalDoc().createElement(TEMPLATE_ID); + measureObSectionElem.appendChild(templateId); + Element itemChild = outputProcessor.getOriginalDoc().createElement(ITEM); + itemChild.setAttribute(ROOT, "2.16.840.1.113883.10.20.28.2.4"); + itemChild.setAttribute(EXTENSION, MEASURE_OBSERVATION_EXTENSION_VALUE); + templateId.appendChild(itemChild); + Element idElement = outputProcessor.getOriginalDoc().createElement(ID); + idElement.setAttribute(ROOT, java.util.UUID.randomUUID().toString()); + idElement.setAttribute(EXTENSION, "MeasureObservations"); + measureObSectionElem.appendChild(idElement); + Element codeElem = outputProcessor.getOriginalDoc().createElement(CODE); + codeElem.setAttribute(CODE, "57027-5"); + codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.6.1"); + codeElem.setAttribute(CODE_SYSTEM_NAME, "LOINC"); + measureObSectionElem.appendChild(codeElem); + Element titleElem = outputProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, "Measure Observation Section"); + measureObSectionElem.appendChild(titleElem); + + // creating text for PopulationCriteria + Element textElem = outputProcessor.getOriginalDoc().createElement("text"); + + measureObSectionElem.appendChild(textElem); + componentElement.appendChild(measureObSectionElem); + outputProcessor.getOriginalDoc().getDocumentElement().appendChild(componentElement); + return componentElement; + } + + /** + * Get Measure Scoring type. + * + * @param me - MeasureExport + * @throws XPathExpressionException - {@link Exception} + */ + private void getMeasureScoringType(MeasureExport me) throws XPathExpressionException { + String xPathScoringType = "/measure/measureDetails/scoring/text()"; + javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); + scoringType = + (String) + xPath.evaluate( + xPathScoringType, + me.getSimpleXmlProcessor().getOriginalDoc(), + XPathConstants.STRING); + } + + /** + * Method to populate clause UUID and displayName. + * + * @param me - MeasureExport + * @throws XPathExpressionException - {@link Exception} + */ + private void generateClauseLogicMap(MeasureExport me) throws XPathExpressionException { + String xPath = "/measure/subTreeLookUp/subTree"; + NodeList subTreeNodeList = + me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), xPath); + for (int i = 0; i < subTreeNodeList.getLength(); i++) { + String uuid = subTreeNodeList.item(i).getAttributes().getNamedItem(UUID).getNodeValue(); + Node firstChildNode = subTreeNodeList.item(i).getFirstChild(); + if (firstChildNode != null) { + clauseLogicMap.put(uuid, firstChildNode); + } + } + } + + /** + * Method to populate all measure groupings in measureGroupingMap. + * + * @param me - MeasureExport + * @throws XPathExpressionException - {@link Exception} + */ + private void getAllMeasureGroupings(MeasureExport me) throws XPathExpressionException { + String xPath = "/measure/measureGrouping/group"; + NodeList measureGroupings = + me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), xPath); + for (int i = 0; i < measureGroupings.getLength(); i++) { + String measureGroupingSequence = + measureGroupings.item(i).getAttributes().getNamedItem("sequence").getNodeValue(); + NodeList childNodeList = measureGroupings.item(i).getChildNodes(); + measureGroupingMap.put(Integer.parseInt(measureGroupingSequence), childNodeList); + } + } } diff --git a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFPopulationLogicGenerator.java b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFPopulationLogicGenerator.java index ebde8a4..6648c4c 100644 --- a/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFPopulationLogicGenerator.java +++ b/src/main/java/gov/cms/madie/hqmf/qdm_5_6/HQMFPopulationLogicGenerator.java @@ -24,611 +24,680 @@ // TODO: Auto-generated Javadoc -/** - * The Class HQMFPopulationLogicGenerator. - */ +/** The Class HQMFPopulationLogicGenerator. */ @Slf4j public class HQMFPopulationLogicGenerator extends HQMFClauseLogicGenerator { - private Map measureGroupingMap = new TreeMap<>(); - - /** The scoring type. */ - private String scoringType; - - /** The initial population. */ - private Node initialPopulation; - - /* (non-Javadoc) - * @see mat.server.simplexml.hqmf.HQMFClauseLogicGenerator#generate(mat.model.clause.MeasureExport) - */ - @Override - public String generate(MeasureExport me) throws Exception { - /*1. Fetch all Clause Logic HQMF in MAP. - 2. Fetch all groupings. - 3. For Each Grouping : - 1.Generate component tag. - 2.Generate populationCriteriaSection tag. - 3.Generate id tag with root and extension as attributes - 4. Generate code tag with code and codesystem as attributes. - 5. Generate title tag with value as attribute. - 6. Generate text tag with value as attribute defining the populations used in current section. - 7. For each population used : - 1.Generate component tag as child of populationCriteriaSection with typeCode COMP. - 2.Generate for ex : initialPopulationCriteria tag for IP with classCode="OBS" moodCode="EVN" as attributes. - 3.Generate id tag with root and extension as attributes - 4. Generate code tag with ccodeSystem="2.16.840.1.113883.5.4" codeSystemName="HL7 Observation Value" - code="IPOP" as attributes. - 5.Generate displayName as child tag of code with value = name of population as in Simple Xml. - 6. Generate precondition tag typeCode="PRCN". - 7. Based on top AND/OR/ANDNOT/ORNOT generate "AllTrue", "AllFalse", "AtLeastOneTrue" tag. Generate id empty tag inside it. - 8. Generate precondition tag typeCode="PRCN" for all children inside top Logical Op and add criteriaRef to it with id and extension. - */ - measureExport = me; - getMeasureScoringType(me); - getAllMeasureGroupings(me); - generatePopulationCriteria(me); - return null; - } - - /** - * Method to generate population Criteria. - * @param me - MeasureExport - * @throws XPathExpressionException - Exception - */ - private void generatePopulationCriteria(MeasureExport me) throws XPathExpressionException { - for (Integer key : measureGroupingMap.keySet()) { - Node populationCriteriaComponentElement = createPopulationCriteriaSection(key.toString() , me.getHqmfXmlProcessor()); - NodeList groupingChildList = measureGroupingMap.get(key).getPackageClauses(); - log.info("measureGroupingMap: {}", measureGroupingMap); - log.info("groupingChildList: {}", groupingChildList); - - for (int i = 0; i < groupingChildList.getLength(); i++) { - String popType = groupingChildList.item(i).getAttributes().getNamedItem(TYPE).getNodeValue(); - switch(popType) { - case "initialPopulation" : - initialPopulation = groupingChildList.item(i); - generatePopulationTypeCriteria(groupingChildList.item(i) - , populationCriteriaComponentElement , me - , "initialPopulationCriteria", "IPOP"); - break; - case "denominator" : - if(checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))){ - generatePopulationTypeCriteria(groupingChildList.item(i) - , populationCriteriaComponentElement , me - , "denominatorCriteria", "DENOM"); - } - break; - case "denominatorExclusions" : - // top Logical Op is OR - if(checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))){ - generatePopulationTypeCriteria(groupingChildList.item(i) - , populationCriteriaComponentElement , me - , "denominatorExclusionCriteria", "DENEX"); - } - break; - case "denominatorExceptions" : - // top Logical Op is OR - if(checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))){ - generatePopulationTypeCriteria(groupingChildList.item(i) - , populationCriteriaComponentElement , me - , "denominatorExceptionCriteria", "DENEXCEP"); - } - break; - case "numerator" : - if(checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))){ - generatePopulationTypeCriteria(groupingChildList.item(i) - , populationCriteriaComponentElement , me - , "numeratorCriteria", "NUMER"); - } - break; - case "numeratorExclusions" : - // top Logical Op is OR - if(checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))){ - generatePopulationTypeCriteria(groupingChildList.item(i) - , populationCriteriaComponentElement , me - , "numeratorExclusionCriteria", "NUMEX"); - } - break; - case "measurePopulation" : - if(checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))){ - generatePopulationTypeCriteria(groupingChildList.item(i) - , populationCriteriaComponentElement , me - , "measurePopulationCriteria", "MSRPOPL"); - } - break; - case "measurePopulationExclusions" : - //If measurePopulationExclusions has no logic added - //then it should not be included in populationCriteria as per Stan. - if(checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))){ - generatePopulationTypeCriteria(groupingChildList.item(i) - , populationCriteriaComponentElement , me - , "measurePopulationExclusionCriteria", "MSRPOPLEX"); - } - break; - case "measureObservation" : - break; - case "stratum" : - if(checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))){ - generatePopulationTypeCriteria(groupingChildList.item(i) - , populationCriteriaComponentElement, me, "stratifierCriteria", "STRAT"); - } - break; - default: - //do nothing. - break; - } - } - // for creating SupplementalDataElements Criteria Section - createSupplementalDataElmStratifier(me,populationCriteriaComponentElement.getFirstChild()); - createRiskAdjustmentStratifier(me, populationCriteriaComponentElement.getFirstChild()); - createScoreUnit(me, populationCriteriaComponentElement.getFirstChild(), measureGroupingMap.get(key).getScoreUnit()); - } - } - - private void createScoreUnit(MeasureExport me, Node populationCriteriaSection, String scoreUnit) { - if (StringUtils.isBlank(scoreUnit)) { - // No Score Unit provided in measure group - return; - } - Document doc = me.getHqmfXmlProcessor().getOriginalDoc(); - - Element componentElement = doc.createElement("component"); - componentElement.setAttribute(TYPE_CODE, "COMP"); - Attr qdmNameSpaceAttr = doc.createAttribute("xmlns:cql-ext"); - qdmNameSpaceAttr.setNodeValue("urn:hhs-cql:hqmf-n1-extensions:v1"); - componentElement.setAttributeNodeNS(qdmNameSpaceAttr); - - Element scoreUnitElement = doc.createElement("cql-ext:scoreUnit"); - scoreUnitElement.setAttribute("nullFlavor","DER"); - scoreUnitElement.setAttribute("xsi:type","PQ"); - - Element unit = doc.createElement("unit"); - unit.setAttribute("value", scoreUnit); - - scoreUnitElement.appendChild(unit); - componentElement.appendChild(scoreUnitElement); - populationCriteriaSection.appendChild(componentElement); - } - - /** - * Method to generate default criteriaTag for all population types included in measure grouping. - * @param item - Node - * @param populationCriteriaComponentElement - Element - * @param me - MeasureExport - * @param criteriaTagName - String. - * @param criteriaTagCodeName - String code value. - * @throws XPathExpressionException - Exception - */ - private void generatePopulationTypeCriteria(Node item, Node populationCriteriaComponentElement - , MeasureExport me, String criteriaTagName, String criteriaTagCodeName) throws XPathExpressionException { - String idExtension; - /*String displayValue = "";*/ - Document doc = populationCriteriaComponentElement.getOwnerDocument(); - Element populationCriteriaElement = (Element) populationCriteriaComponentElement.getFirstChild(); - Element componentElement = doc.createElement("component"); - componentElement.setAttribute(TYPE_CODE, "COMP"); - Element initialPopCriteriaElement = doc.createElement(criteriaTagName); - - if(criteriaTagName.equalsIgnoreCase("stratifierCriteria")){ - idExtension = "Stratifiers"; - // displayValue = "Stratification"; - } else { - initialPopCriteriaElement.setAttribute(CLASS_CODE, "OBS"); - initialPopCriteriaElement.setAttribute(MOOD_CODE, "EVN"); - idExtension = StringUtils.deleteWhitespace(item.getAttributes().getNamedItem(TYPE).getNodeValue()); - //displayValue = item.getAttributes().getNamedItem(TYPE).getNodeValue(); - } - Element idElement = doc.createElement(ID); - idElement.setAttribute(ROOT, item.getAttributes().getNamedItem(UUID).getNodeValue()); - idElement.setAttribute("extension", idExtension); - initialPopCriteriaElement.appendChild(idElement); - Element codeElem = doc.createElement(CODE); - codeElem.setAttribute(CODE, criteriaTagCodeName); - codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.5.4"); - codeElem.setAttribute(CODE_SYSTEM_NAME, "Act Code"); - // displayName inside not needed for populations as per stan - /* Element displayNameElement = doc.createElement(DISPLAY_NAME); - displayNameElement.setAttribute(VALUE, displayValue); - codeElem.appendChild(displayNameElement);*/ - initialPopCriteriaElement.appendChild(codeElem); - /*Element preConditionElem = doc.createElement("precondition"); - preConditionElem.setAttribute(TYPE_CODE, "PRCN");*/ - if (item.getChildNodes() != null) { - for(int i=0;i getRequiredClauses(String type){ - List list = new ArrayList<>(); - if("Cohort".equalsIgnoreCase(type)){ - list.add("initialPopulation"); - }else if("Continuous Variable".equalsIgnoreCase(type)){ - list.add("initialPopulation"); - list.add("measurePopulation"); - list.add("measureObservation"); - }else if("Proportion".equalsIgnoreCase(type) || - "Ratio".equalsIgnoreCase(type)){ - list.add("initialPopulation"); - list.add("denominator"); - list.add("numerator"); - } - return list; - } - - /** - * Check for required clause by scoring. - * - * @param me the me - * @param popType the pop type - * @param node the node - * @return true, if successful - * @throws XPathExpressionException the x path expression exception - */ - private static boolean checkForRequiredClauseByScoring(MeasureExport me, String popType, Node node) throws XPathExpressionException{ - boolean isRequiredClause = false; - Node scoringType = me.getSimpleXmlProcessor().findNode(me.getSimpleXmlProcessor().getOriginalDoc(), - "/measure/measureDetails/scoring"); - List clauseList = new ArrayList<>(); - clauseList = getRequiredClauses(scoringType.getTextContent()); - if(clauseList.contains(popType)){ - isRequiredClause = true; - } else { - isRequiredClause = checkForPackageClauseLogic(node, popType); - } - return isRequiredClause; - } - - /** - * Check for package clause logic. - * - * @param node the node - * @param popType the pop type - * @return true, if successful - */ - private static boolean checkForPackageClauseLogic(Node node, - String popType) { - switch(popType) { - - case "measurePopulation": - case "numerator": - case "denominator": - case "denominatorExclusions": - case "numeratorExclusions": - case "measureObservation": - case "stratum": - case "denominatorExceptions": - case "measurePopulationExclusions": - if(node.hasChildNodes()) { - return true; - } - break; - - default: //do Nothing - break; - - } - return false; - } - - /** - * Create the risk adjustment components. This will create a create a component tag underneath - * population critiera section for risk adjustment variables. - * @param me the measure export - * @param parentNode the parent node - * @throws XPathExpressionException - */ - private void createRiskAdjustmentStratifier(MeasureExport me, Node parentNode) throws XPathExpressionException { - - String xPathForRiskAdjustmentVariables = "/measure/riskAdjustmentVariables/cqldefinition"; - XmlProcessor simpleXmlProcessor = me.getSimpleXmlProcessor(); - NodeList riskAdjustmentVariables = simpleXmlProcessor.findNodeList(simpleXmlProcessor.getOriginalDoc(), - xPathForRiskAdjustmentVariables); - String xPathForLibraryName = "/measure/cqlLookUp/library"; - Node libraryNode = simpleXmlProcessor.findNode(simpleXmlProcessor.getOriginalDoc(), xPathForLibraryName); - String libraryName = libraryNode.getTextContent(); - - String xPathForCQLUUID = "/measure/measureDetails/cqlUUID"; - Node cqluuidNode = simpleXmlProcessor.findNode(simpleXmlProcessor.getOriginalDoc(), xPathForCQLUUID); - String cqlUUID = cqluuidNode.getTextContent(); - - for (int i = 0; i < riskAdjustmentVariables.getLength(); i++) { - Node current = riskAdjustmentVariables.item(i); - String riskAdjustmentDefName = current.getAttributes().getNamedItem("displayName").getNodeValue(); - - Element component = createRiskAdjustmentComponentNode(me, cqlUUID, libraryName, riskAdjustmentDefName, "MSRADJ"); - parentNode.appendChild(component); - } - } - - /** - * Creates the component for a risk adjustment variable in the hqmf document - * @param me the measure export - * @param cqlUUID the cql file uuid - * @param libraryName the cql library name - * @param riskAdjustmentDefName the risk adjustment definition name - * @return the component element - */ - private Element createRiskAdjustmentComponentNode(MeasureExport me, String cqlUUID, String libraryName, String riskAdjustmentDefName, String type) { - XmlProcessor processor = me.getHqmfXmlProcessor(); - - Element component = processor.getOriginalDoc().createElement("component"); - component.setAttribute(TYPE_CODE, "COMP"); - - Attr qdmNameSpaceAttr = processor.getOriginalDoc().createAttribute("xmlns:cql-ext"); - qdmNameSpaceAttr.setNodeValue("urn:hhs-cql:hqmf-n1-extensions:v1"); - component.setAttributeNodeNS(qdmNameSpaceAttr); - - Element stratifierCriteria = processor.getOriginalDoc().createElement("cql-ext:supplementalDataElement"); - - String extensionStr = ""; - String codeStr = ""; - if(type.equalsIgnoreCase("MSRADJ")){ - extensionStr = "Risk Adjustment Variables"; - codeStr = "MSRADJ"; - } else { - extensionStr = "Supplemental Data Elements"; - codeStr = "SDE"; - } - - Element id = processor.getOriginalDoc().createElement("id"); - id.setAttribute("extension", extensionStr); - id.setAttribute("root", java.util.UUID.randomUUID().toString()); - stratifierCriteria.appendChild(id); - - Element code = processor.getOriginalDoc().createElement("code"); - code.setAttribute("code", codeStr); - code.setAttribute("codeSystem", "2.16.840.1.113883.5.4"); - code.setAttribute("codeSystemName", "Act Code"); - stratifierCriteria.appendChild(code); - - Element precondition = processor.getOriginalDoc().createElement("precondition"); - precondition.setAttribute("typeCode", "PRCN"); - stratifierCriteria.appendChild(precondition); - - Element criteriaReference = processor.getOriginalDoc().createElement("criteriaReference"); - criteriaReference.setAttribute("moodCode", "EVN"); - criteriaReference.setAttribute("classCode", "OBS"); - precondition.appendChild(criteriaReference); - - Element criteriaReferenceId = processor.getOriginalDoc().createElement("id"); - criteriaReferenceId.setAttribute("root", cqlUUID); - String extensionString = String.format("%s.\"%s\"", libraryName, riskAdjustmentDefName); - criteriaReferenceId.setAttribute("extension", extensionString); - criteriaReference.appendChild(criteriaReferenceId); - component.appendChild(stratifierCriteria); - - return component; - - } - /** - * Creates Logic for Each Supplemental Data Element Nodes. - * - * @param me the me - * @param parentNode - PopulationCriteria First Child Node. - * @throws XPathExpressionException the x path expression exception - */ - private void createSupplementalDataElmStratifier(MeasureExport me, Node parentNode) throws XPathExpressionException { - String xpathForOtherSupplementalQDMs = "/measure/supplementalDataElements/cqldefinition/@uuid"; - NodeList supplementalDataElements = me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), - xpathForOtherSupplementalQDMs); - String xPathForLibraryName = "/measure/cqlLookUp/library"; - Node libraryNode = me.getSimpleXmlProcessor().findNode(me.getSimpleXmlProcessor().getOriginalDoc(), xPathForLibraryName); - String libraryName = libraryNode.getTextContent(); - - String xPathForCQLUUID = "/measure/measureDetails/cqlUUID"; - Node cqluuidNode = me.getSimpleXmlProcessor().findNode(me.getSimpleXmlProcessor().getOriginalDoc(), xPathForCQLUUID); - String cqlUUID = cqluuidNode.getTextContent(); - - - if (supplementalDataElements == null || supplementalDataElements.getLength() < 1) { - return; - } - List supplementalElementRefIds = new ArrayList<>(); - for (int i = 0; i < supplementalDataElements.getLength(); i++) { - supplementalElementRefIds.add(supplementalDataElements.item(i).getNodeValue()); - } - - StringBuilder uuidXPathString = new StringBuilder(); - for (String uuidString: supplementalElementRefIds) { - uuidXPathString.append("@id = '").append(uuidString).append("' or "); - } - uuidXPathString = new StringBuilder(uuidXPathString.substring(0, uuidXPathString.lastIndexOf(" or "))); - String xpathforOtherSupplementalDataElements = "/measure/cqlLookUp/definitions/definition[" + uuidXPathString + "]"; - NodeList supplementalQDMNodeList = me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), - xpathforOtherSupplementalDataElements); - if (supplementalQDMNodeList.getLength() < 1) { - return; - } - - for (int i = 0; i < supplementalQDMNodeList.getLength(); i++) { - Node qdmNode = supplementalQDMNodeList.item(i); - String qdmName = qdmNode.getAttributes().getNamedItem("name").getNodeValue(); - - //createRiskAdjustmentComponentNode is good enough for this too. - Element componentElement = createRiskAdjustmentComponentNode(me, cqlUUID, libraryName, qdmName, "SDE"); - parentNode.appendChild(componentElement); - } - - } - - @Data - @Builder - static class MeasureGroup { - private NodeList packageClauses; - private String scoreUnit; - private int sequence; - } + private Map measureGroupingMap = new TreeMap<>(); + + /** The scoring type. */ + private String scoringType; + + /** The initial population. */ + private Node initialPopulation; + + /* (non-Javadoc) + * @see mat.server.simplexml.hqmf.HQMFClauseLogicGenerator#generate(mat.model.clause.MeasureExport) + */ + @Override + public String generate(MeasureExport me) throws Exception { + /*1. Fetch all Clause Logic HQMF in MAP. + 2. Fetch all groupings. + 3. For Each Grouping : + 1.Generate component tag. + 2.Generate populationCriteriaSection tag. + 3.Generate id tag with root and extension as attributes + 4. Generate code tag with code and codesystem as attributes. + 5. Generate title tag with value as attribute. + 6. Generate text tag with value as attribute defining the populations used in current section. + 7. For each population used : + 1.Generate component tag as child of populationCriteriaSection with typeCode COMP. + 2.Generate for ex : initialPopulationCriteria tag for IP with classCode="OBS" moodCode="EVN" as attributes. + 3.Generate id tag with root and extension as attributes + 4. Generate code tag with ccodeSystem="2.16.840.1.113883.5.4" codeSystemName="HL7 Observation Value" + code="IPOP" as attributes. + 5.Generate displayName as child tag of code with value = name of population as in Simple Xml. + 6. Generate precondition tag typeCode="PRCN". + 7. Based on top AND/OR/ANDNOT/ORNOT generate "AllTrue", "AllFalse", "AtLeastOneTrue" tag. Generate id empty tag inside it. + 8. Generate precondition tag typeCode="PRCN" for all children inside top Logical Op and add criteriaRef to it with id and extension. + */ + measureExport = me; + getMeasureScoringType(me); + getAllMeasureGroupings(me); + generatePopulationCriteria(me); + return null; + } + + /** + * Method to generate population Criteria. + * + * @param me - MeasureExport + * @throws XPathExpressionException - Exception + */ + private void generatePopulationCriteria(MeasureExport me) throws XPathExpressionException { + for (Integer key : measureGroupingMap.keySet()) { + Node populationCriteriaComponentElement = + createPopulationCriteriaSection(key.toString(), me.getHqmfXmlProcessor()); + NodeList groupingChildList = measureGroupingMap.get(key).getPackageClauses(); + log.info("measureGroupingMap: {}", measureGroupingMap); + log.info("groupingChildList: {}", groupingChildList); + + for (int i = 0; i < groupingChildList.getLength(); i++) { + String popType = + groupingChildList.item(i).getAttributes().getNamedItem(TYPE).getNodeValue(); + switch (popType) { + case "initialPopulation": + initialPopulation = groupingChildList.item(i); + generatePopulationTypeCriteria( + groupingChildList.item(i), + populationCriteriaComponentElement, + me, + "initialPopulationCriteria", + "IPOP"); + break; + case "denominator": + if (checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))) { + generatePopulationTypeCriteria( + groupingChildList.item(i), + populationCriteriaComponentElement, + me, + "denominatorCriteria", + "DENOM"); + } + break; + case "denominatorExclusions": + // top Logical Op is OR + if (checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))) { + generatePopulationTypeCriteria( + groupingChildList.item(i), + populationCriteriaComponentElement, + me, + "denominatorExclusionCriteria", + "DENEX"); + } + break; + case "denominatorExceptions": + // top Logical Op is OR + if (checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))) { + generatePopulationTypeCriteria( + groupingChildList.item(i), + populationCriteriaComponentElement, + me, + "denominatorExceptionCriteria", + "DENEXCEP"); + } + break; + case "numerator": + if (checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))) { + generatePopulationTypeCriteria( + groupingChildList.item(i), + populationCriteriaComponentElement, + me, + "numeratorCriteria", + "NUMER"); + } + break; + case "numeratorExclusions": + // top Logical Op is OR + if (checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))) { + generatePopulationTypeCriteria( + groupingChildList.item(i), + populationCriteriaComponentElement, + me, + "numeratorExclusionCriteria", + "NUMEX"); + } + break; + case "measurePopulation": + if (checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))) { + generatePopulationTypeCriteria( + groupingChildList.item(i), + populationCriteriaComponentElement, + me, + "measurePopulationCriteria", + "MSRPOPL"); + } + break; + case "measurePopulationExclusions": + // If measurePopulationExclusions has no logic added + // then it should not be included in populationCriteria as per Stan. + if (checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))) { + generatePopulationTypeCriteria( + groupingChildList.item(i), + populationCriteriaComponentElement, + me, + "measurePopulationExclusionCriteria", + "MSRPOPLEX"); + } + break; + case "measureObservation": + break; + case "stratum": + if (checkForRequiredClauseByScoring(me, popType, groupingChildList.item(i))) { + generatePopulationTypeCriteria( + groupingChildList.item(i), + populationCriteriaComponentElement, + me, + "stratifierCriteria", + "STRAT"); + } + break; + default: + // do nothing. + break; + } + } + // for creating SupplementalDataElements Criteria Section + createSupplementalDataElmStratifier(me, populationCriteriaComponentElement.getFirstChild()); + createRiskAdjustmentStratifier(me, populationCriteriaComponentElement.getFirstChild()); + createScoreUnit( + me, + populationCriteriaComponentElement.getFirstChild(), + measureGroupingMap.get(key).getScoreUnit()); + } + } + + private void createScoreUnit(MeasureExport me, Node populationCriteriaSection, String scoreUnit) { + if (StringUtils.isBlank(scoreUnit)) { + // No Score Unit provided in measure group + return; + } + Document doc = me.getHqmfXmlProcessor().getOriginalDoc(); + + Element componentElement = doc.createElement("component"); + componentElement.setAttribute(TYPE_CODE, "COMP"); + Attr qdmNameSpaceAttr = doc.createAttribute("xmlns:cql-ext"); + qdmNameSpaceAttr.setNodeValue("urn:hhs-cql:hqmf-n1-extensions:v1"); + componentElement.setAttributeNodeNS(qdmNameSpaceAttr); + + Element scoreUnitElement = doc.createElement("cql-ext:scoreUnit"); + scoreUnitElement.setAttribute("nullFlavor", "DER"); + scoreUnitElement.setAttribute("xsi:type", "PQ"); + + Element unit = doc.createElement("unit"); + unit.setAttribute("value", scoreUnit); + + scoreUnitElement.appendChild(unit); + componentElement.appendChild(scoreUnitElement); + populationCriteriaSection.appendChild(componentElement); + } + + /** + * Method to generate default criteriaTag for all population types included in measure grouping. + * + * @param item - Node + * @param populationCriteriaComponentElement - Element + * @param me - MeasureExport + * @param criteriaTagName - String. + * @param criteriaTagCodeName - String code value. + * @throws XPathExpressionException - Exception + */ + private void generatePopulationTypeCriteria( + Node item, + Node populationCriteriaComponentElement, + MeasureExport me, + String criteriaTagName, + String criteriaTagCodeName) + throws XPathExpressionException { + String idExtension; + /*String displayValue = "";*/ + Document doc = populationCriteriaComponentElement.getOwnerDocument(); + Element populationCriteriaElement = + (Element) populationCriteriaComponentElement.getFirstChild(); + Element componentElement = doc.createElement("component"); + componentElement.setAttribute(TYPE_CODE, "COMP"); + Element initialPopCriteriaElement = doc.createElement(criteriaTagName); + + if (criteriaTagName.equalsIgnoreCase("stratifierCriteria")) { + idExtension = "Stratifiers"; + // displayValue = "Stratification"; + } else { + initialPopCriteriaElement.setAttribute(CLASS_CODE, "OBS"); + initialPopCriteriaElement.setAttribute(MOOD_CODE, "EVN"); + idExtension = + StringUtils.deleteWhitespace(item.getAttributes().getNamedItem(TYPE).getNodeValue()); + // displayValue = item.getAttributes().getNamedItem(TYPE).getNodeValue(); + } + Element idElement = doc.createElement(ID); + idElement.setAttribute(ROOT, item.getAttributes().getNamedItem(UUID).getNodeValue()); + idElement.setAttribute("extension", idExtension); + initialPopCriteriaElement.appendChild(idElement); + Element codeElem = doc.createElement(CODE); + codeElem.setAttribute(CODE, criteriaTagCodeName); + codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.5.4"); + codeElem.setAttribute(CODE_SYSTEM_NAME, "Act Code"); + // displayName inside not needed for populations as per stan + /* Element displayNameElement = doc.createElement(DISPLAY_NAME); + displayNameElement.setAttribute(VALUE, displayValue); + codeElem.appendChild(displayNameElement);*/ + initialPopCriteriaElement.appendChild(codeElem); + /*Element preConditionElem = doc.createElement("precondition"); + preConditionElem.setAttribute(TYPE_CODE, "PRCN");*/ + if (item.getChildNodes() != null) { + for (int i = 0; i < item.getChildNodes().getLength(); i++) { + generatePopulationLogic(initialPopCriteriaElement, item.getChildNodes().item(i), me); + } + } + checkScoringTypeToAssociateIP(initialPopCriteriaElement, item); + /*initialPopCriteriaElement.appendChild(preConditionElem);*/ + componentElement.appendChild(initialPopCriteriaElement); + populationCriteriaElement.appendChild(componentElement); + } + + /** + * Associate IP with Deno in Proportion Measures, With MeasurePopulation In Continous Variable and + * based on association in Ratio Measures with Deno and NUm. + * + * @param populationCritieriaElem the pre condition elem + * @param item the item + */ + private void checkScoringTypeToAssociateIP(Element populationCritieriaElem, Node item) { + String nodeType = item.getAttributes().getNamedItem(TYPE).getNodeValue(); + Document mainDocument = populationCritieriaElem.getOwnerDocument(); + Element preConditionElem = mainDocument.createElement("subject"); + preConditionElem.setAttribute(TYPE_CODE, "SUBJ"); + + if (scoringType.equalsIgnoreCase("Ratio") + && (nodeType.equalsIgnoreCase("denominator") || nodeType.equalsIgnoreCase("numerator"))) { + + String associatedIPUUID = initialPopulation.getAttributes().getNamedItem(UUID).getNodeValue(); + + if (item.getAttributes().getNamedItem("associatedPopulationUUID") != null) { + associatedIPUUID = + item.getAttributes().getNamedItem("associatedPopulationUUID").getNodeValue(); + } + Element criteriaRef = mainDocument.createElement("criteriaReference"); + criteriaRef.setAttribute(CLASS_CODE, "OBS"); + criteriaRef.setAttribute(MOOD_CODE, "EVN"); + Element idElement = mainDocument.createElement(ID); + idElement.setAttribute(ROOT, associatedIPUUID); + idElement.setAttribute("extension", StringUtils.deleteWhitespace("initialPopulation")); + criteriaRef.appendChild(idElement); + preConditionElem.appendChild(criteriaRef); + populationCritieriaElem.appendChild(preConditionElem); + } + } + + /** + * Method to generate tags for logic used inside population. + * + * @param populationTypeCriteriaElement - Element. + * @param me - MeasureExport. + * @throws XPathExpressionException - Exception. + */ + private void generatePopulationLogic( + Element populationTypeCriteriaElement, Node childNode, MeasureExport me) + throws XPathExpressionException { + + String nodeType; + if (childNode.getAttributes().getNamedItem(TYPE) != null) { + nodeType = childNode.getAttributes().getNamedItem(TYPE).getNodeValue(); + } else { + nodeType = childNode.getNodeName(); + } + Element preConditionElement = + populationTypeCriteriaElement.getOwnerDocument().createElement("precondition"); + preConditionElement.setAttribute(TYPE_CODE, "PRCN"); + switch (nodeType) { + case "cqldefinition": + generateCritRefCQLDefine(preConditionElement, childNode, me.getHqmfXmlProcessor()); + break; + case "comment": + // skipping comment node as of now. + break; + case "cqlfunction": + break; + + default: + break; + } + if (preConditionElement.hasChildNodes()) { + populationTypeCriteriaElement.appendChild(preConditionElement); + } + } + + /** + * Method to generate component and populationCriteria default tags. + * + * @param sequenceNumber - Measure Grouping sequence number. + * @param outputProcessor - XmlProcessor. + * @return - Node. + */ + private Node createPopulationCriteriaSection( + String sequenceNumber, XmlProcessor outputProcessor) { + Element componentElement = outputProcessor.getOriginalDoc().createElement("component"); + Attr nameSpaceAttr = outputProcessor.getOriginalDoc().createAttribute("xmlns:xsi"); + nameSpaceAttr.setNodeValue(nameSpace); + componentElement.setAttributeNodeNS(nameSpaceAttr); + Node popCriteriaElem = + outputProcessor.getOriginalDoc().createElement("populationCriteriaSection"); + Element templateId = outputProcessor.getOriginalDoc().createElement(TEMPLATE_ID); + popCriteriaElem.appendChild(templateId); + Element itemChild = outputProcessor.getOriginalDoc().createElement(ITEM); + itemChild.setAttribute(ROOT, "2.16.840.1.113883.10.20.28.2.7"); + itemChild.setAttribute("extension", POPULATION_CRITERIA_EXTENSION_CQL); + templateId.appendChild(itemChild); + Element idElement = outputProcessor.getOriginalDoc().createElement(ID); + idElement.setAttribute(ROOT, java.util.UUID.randomUUID().toString()); + idElement.setAttribute("extension", "PopulationCriteria" + sequenceNumber); + popCriteriaElem.appendChild(idElement); + Element codeElem = outputProcessor.getOriginalDoc().createElement(CODE); + codeElem.setAttribute(CODE, "57026-7"); + codeElem.setAttribute(CODE_SYSTEM, "2.16.840.1.113883.6.1"); + popCriteriaElem.appendChild(codeElem); + Element titleElem = outputProcessor.getOriginalDoc().createElement(TITLE); + titleElem.setAttribute(VALUE, "Population Criteria Section"); + popCriteriaElem.appendChild(titleElem); + // creating text for PopulationCriteria + Element textElem = outputProcessor.getOriginalDoc().createElement("text"); + // textElem.setAttribute(VALUE, "Population Criteria text"); + popCriteriaElem.appendChild(textElem); + componentElement.appendChild(popCriteriaElem); + outputProcessor.getOriginalDoc().getDocumentElement().appendChild(componentElement); + return componentElement; + } + + /** + * Get Measure Scoring type. + * + * @param me - MeasureExport + * @return the measure scoring type + * @throws XPathExpressionException - {@link Exception} + */ + private void getMeasureScoringType(MeasureExport me) throws XPathExpressionException { + String xPathScoringType = "/measure/measureDetails/scoring/text()"; + javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath(); + + scoringType = + (String) + xPath.evaluate( + xPathScoringType, + me.getSimpleXmlProcessor().getOriginalDoc(), + XPathConstants.STRING); + } + + /** + * Method to populate all measure groupings in measureGroupingMap. + * + * @param me - MeasureExport + * @return the all measure groupings + * @throws XPathExpressionException - {@link Exception} + */ + private void getAllMeasureGroupings(MeasureExport me) throws XPathExpressionException { + String xPath = "/measure/measureGrouping/group"; + NodeList measureGroupings = + me.getSimpleXmlProcessor().findNodeList(me.getSimpleXmlProcessor().getOriginalDoc(), xPath); + for (int i = 0; i < measureGroupings.getLength(); i++) { + int measureGroupingSequence = + Integer.parseInt( + measureGroupings.item(i).getAttributes().getNamedItem("sequence").getNodeValue()); + Node measureGroupNode = measureGroupings.item(i); + // Added to remove text nodes with only newlines that make later processing blow up + XmlProcessor.clean(measureGroupNode); + + MeasureGroup measureGroup = + MeasureGroup.builder() + .sequence(measureGroupingSequence) + .packageClauses(measureGroupNode.getChildNodes()) + .build(); + + Node ucum = measureGroupings.item(i).getAttributes().getNamedItem("ucum"); + if (ucum != null && isNotBlank(ucum.getNodeValue().strip())) { + measureGroup.setScoreUnit(ucum.getNodeValue().strip()); + } + + measureGroupingMap.put(measureGroupingSequence, measureGroup); + } + } + + /** + * Gets the required clauses. + * + * @param type the type + * @return the required clauses + */ + private static List getRequiredClauses(String type) { + List list = new ArrayList<>(); + if ("Cohort".equalsIgnoreCase(type)) { + list.add("initialPopulation"); + } else if ("Continuous Variable".equalsIgnoreCase(type)) { + list.add("initialPopulation"); + list.add("measurePopulation"); + list.add("measureObservation"); + } else if ("Proportion".equalsIgnoreCase(type) || "Ratio".equalsIgnoreCase(type)) { + list.add("initialPopulation"); + list.add("denominator"); + list.add("numerator"); + } + return list; + } + + /** + * Check for required clause by scoring. + * + * @param me the me + * @param popType the pop type + * @param node the node + * @return true, if successful + * @throws XPathExpressionException the x path expression exception + */ + private static boolean checkForRequiredClauseByScoring( + MeasureExport me, String popType, Node node) throws XPathExpressionException { + boolean isRequiredClause = false; + Node scoringType = + me.getSimpleXmlProcessor() + .findNode( + me.getSimpleXmlProcessor().getOriginalDoc(), "/measure/measureDetails/scoring"); + List clauseList = new ArrayList<>(); + clauseList = getRequiredClauses(scoringType.getTextContent()); + if (clauseList.contains(popType)) { + isRequiredClause = true; + } else { + isRequiredClause = checkForPackageClauseLogic(node, popType); + } + return isRequiredClause; + } + + /** + * Check for package clause logic. + * + * @param node the node + * @param popType the pop type + * @return true, if successful + */ + private static boolean checkForPackageClauseLogic(Node node, String popType) { + switch (popType) { + case "measurePopulation": + case "numerator": + case "denominator": + case "denominatorExclusions": + case "numeratorExclusions": + case "measureObservation": + case "stratum": + case "denominatorExceptions": + case "measurePopulationExclusions": + if (node.hasChildNodes()) { + return true; + } + break; + + default: // do Nothing + break; + } + return false; + } + + /** + * Create the risk adjustment components. This will create a create a component tag underneath + * population critiera section for risk adjustment variables. + * + * @param me the measure export + * @param parentNode the parent node + * @throws XPathExpressionException + */ + private void createRiskAdjustmentStratifier(MeasureExport me, Node parentNode) + throws XPathExpressionException { + + String xPathForRiskAdjustmentVariables = "/measure/riskAdjustmentVariables/cqldefinition"; + XmlProcessor simpleXmlProcessor = me.getSimpleXmlProcessor(); + NodeList riskAdjustmentVariables = + simpleXmlProcessor.findNodeList( + simpleXmlProcessor.getOriginalDoc(), xPathForRiskAdjustmentVariables); + String xPathForLibraryName = "/measure/cqlLookUp/library"; + Node libraryNode = + simpleXmlProcessor.findNode(simpleXmlProcessor.getOriginalDoc(), xPathForLibraryName); + String libraryName = libraryNode.getTextContent(); + + String xPathForCQLUUID = "/measure/measureDetails/cqlUUID"; + Node cqluuidNode = + simpleXmlProcessor.findNode(simpleXmlProcessor.getOriginalDoc(), xPathForCQLUUID); + String cqlUUID = cqluuidNode.getTextContent(); + + for (int i = 0; i < riskAdjustmentVariables.getLength(); i++) { + Node current = riskAdjustmentVariables.item(i); + String riskAdjustmentDefName = + current.getAttributes().getNamedItem("displayName").getNodeValue(); + + Element component = + createRiskAdjustmentComponentNode( + me, cqlUUID, libraryName, riskAdjustmentDefName, "MSRADJ"); + parentNode.appendChild(component); + } + } + + /** + * Creates the component for a risk adjustment variable in the hqmf document + * + * @param me the measure export + * @param cqlUUID the cql file uuid + * @param libraryName the cql library name + * @param riskAdjustmentDefName the risk adjustment definition name + * @return the component element + */ + private Element createRiskAdjustmentComponentNode( + MeasureExport me, + String cqlUUID, + String libraryName, + String riskAdjustmentDefName, + String type) { + XmlProcessor processor = me.getHqmfXmlProcessor(); + + Element component = processor.getOriginalDoc().createElement("component"); + component.setAttribute(TYPE_CODE, "COMP"); + + Attr qdmNameSpaceAttr = processor.getOriginalDoc().createAttribute("xmlns:cql-ext"); + qdmNameSpaceAttr.setNodeValue("urn:hhs-cql:hqmf-n1-extensions:v1"); + component.setAttributeNodeNS(qdmNameSpaceAttr); + + Element stratifierCriteria = + processor.getOriginalDoc().createElement("cql-ext:supplementalDataElement"); + + String extensionStr = ""; + String codeStr = ""; + if (type.equalsIgnoreCase("MSRADJ")) { + extensionStr = "Risk Adjustment Variables"; + codeStr = "MSRADJ"; + } else { + extensionStr = "Supplemental Data Elements"; + codeStr = "SDE"; + } + + Element id = processor.getOriginalDoc().createElement("id"); + id.setAttribute("extension", extensionStr); + id.setAttribute("root", java.util.UUID.randomUUID().toString()); + stratifierCriteria.appendChild(id); + + Element code = processor.getOriginalDoc().createElement("code"); + code.setAttribute("code", codeStr); + code.setAttribute("codeSystem", "2.16.840.1.113883.5.4"); + code.setAttribute("codeSystemName", "Act Code"); + stratifierCriteria.appendChild(code); + + Element precondition = processor.getOriginalDoc().createElement("precondition"); + precondition.setAttribute("typeCode", "PRCN"); + stratifierCriteria.appendChild(precondition); + + Element criteriaReference = processor.getOriginalDoc().createElement("criteriaReference"); + criteriaReference.setAttribute("moodCode", "EVN"); + criteriaReference.setAttribute("classCode", "OBS"); + precondition.appendChild(criteriaReference); + + Element criteriaReferenceId = processor.getOriginalDoc().createElement("id"); + criteriaReferenceId.setAttribute("root", cqlUUID); + String extensionString = String.format("%s.\"%s\"", libraryName, riskAdjustmentDefName); + criteriaReferenceId.setAttribute("extension", extensionString); + criteriaReference.appendChild(criteriaReferenceId); + component.appendChild(stratifierCriteria); + + return component; + } + + /** + * Creates Logic for Each Supplemental Data Element Nodes. + * + * @param me the me + * @param parentNode - PopulationCriteria First Child Node. + * @throws XPathExpressionException the x path expression exception + */ + private void createSupplementalDataElmStratifier(MeasureExport me, Node parentNode) + throws XPathExpressionException { + String xpathForOtherSupplementalQDMs = "/measure/supplementalDataElements/cqldefinition/@uuid"; + NodeList supplementalDataElements = + me.getSimpleXmlProcessor() + .findNodeList( + me.getSimpleXmlProcessor().getOriginalDoc(), xpathForOtherSupplementalQDMs); + String xPathForLibraryName = "/measure/cqlLookUp/library"; + Node libraryNode = + me.getSimpleXmlProcessor() + .findNode(me.getSimpleXmlProcessor().getOriginalDoc(), xPathForLibraryName); + String libraryName = libraryNode.getTextContent(); + + String xPathForCQLUUID = "/measure/measureDetails/cqlUUID"; + Node cqluuidNode = + me.getSimpleXmlProcessor() + .findNode(me.getSimpleXmlProcessor().getOriginalDoc(), xPathForCQLUUID); + String cqlUUID = cqluuidNode.getTextContent(); + + if (supplementalDataElements == null || supplementalDataElements.getLength() < 1) { + return; + } + List supplementalElementRefIds = new ArrayList<>(); + for (int i = 0; i < supplementalDataElements.getLength(); i++) { + supplementalElementRefIds.add(supplementalDataElements.item(i).getNodeValue()); + } + + StringBuilder uuidXPathString = new StringBuilder(); + for (String uuidString : supplementalElementRefIds) { + uuidXPathString.append("@id = '").append(uuidString).append("' or "); + } + uuidXPathString = + new StringBuilder(uuidXPathString.substring(0, uuidXPathString.lastIndexOf(" or "))); + String xpathforOtherSupplementalDataElements = + "/measure/cqlLookUp/definitions/definition[" + uuidXPathString + "]"; + NodeList supplementalQDMNodeList = + me.getSimpleXmlProcessor() + .findNodeList( + me.getSimpleXmlProcessor().getOriginalDoc(), xpathforOtherSupplementalDataElements); + if (supplementalQDMNodeList.getLength() < 1) { + return; + } + + for (int i = 0; i < supplementalQDMNodeList.getLength(); i++) { + Node qdmNode = supplementalQDMNodeList.item(i); + String qdmName = qdmNode.getAttributes().getNamedItem("name").getNodeValue(); + + // createRiskAdjustmentComponentNode is good enough for this too. + Element componentElement = + createRiskAdjustmentComponentNode(me, cqlUUID, libraryName, qdmName, "SDE"); + parentNode.appendChild(componentElement); + } + } + + @Data + @Builder + static class MeasureGroup { + private NodeList packageClauses; + private String scoreUnit; + private int sequence; + } } diff --git a/src/main/java/gov/cms/madie/resources/PackageController.java b/src/main/java/gov/cms/madie/resources/PackageController.java index 328cbbe..63c8788 100644 --- a/src/main/java/gov/cms/madie/resources/PackageController.java +++ b/src/main/java/gov/cms/madie/resources/PackageController.java @@ -3,7 +3,6 @@ import gov.cms.madie.Exceptions.UnsupportedModelException; import gov.cms.madie.hqmf.Generator; import gov.cms.madie.hqmf.HQMFGeneratorFactory; -import gov.cms.madie.hqmf.XmlProcessor; import gov.cms.madie.hqmf.dto.MeasureExport; import gov.cms.madie.services.PackagingService; import gov.cms.madie.models.measure.Measure; @@ -55,6 +54,7 @@ public String generateHqmf(@RequestBody MeasureExport measureExport) throws Exce Generator hqmfGenerator = hqmfGeneratorFactory.getHQMFGenerator(); return hqmfGenerator.generate(measureExport); } - throw new UnsupportedModelException("Unsupported model type: " + (measure == null ? "NONE" : measure.getModel())); + throw new UnsupportedModelException( + "Unsupported model type: " + (measure == null ? "NONE" : measure.getModel())); } } diff --git a/src/test/java/gov/cms/madie/hqmf/HQMFGeneratorFactoryTest.java b/src/test/java/gov/cms/madie/hqmf/HQMFGeneratorFactoryTest.java index c26ec4f..36eabbe 100644 --- a/src/test/java/gov/cms/madie/hqmf/HQMFGeneratorFactoryTest.java +++ b/src/test/java/gov/cms/madie/hqmf/HQMFGeneratorFactoryTest.java @@ -14,14 +14,13 @@ @ExtendWith(MockitoExtension.class) class HQMFGeneratorFactoryTest { - @Mock - HQMFGenerator qdm_5_6_generator; + @Mock HQMFGenerator qdm_5_6_generator; - @InjectMocks - HQMFGeneratorFactory factory; - @Test - void getHQMFGenerator() { - Generator hqmfGenerator = factory.getHQMFGenerator(); - assertThat(hqmfGenerator, is(equalTo(qdm_5_6_generator))); - } -} \ No newline at end of file + @InjectMocks HQMFGeneratorFactory factory; + + @Test + void getHQMFGenerator() { + Generator hqmfGenerator = factory.getHQMFGenerator(); + assertThat(hqmfGenerator, is(equalTo(qdm_5_6_generator))); + } +} diff --git a/src/test/java/gov/cms/madie/hqmf/XMLUtilityTest.java b/src/test/java/gov/cms/madie/hqmf/XMLUtilityTest.java index ea764c1..ac158a2 100644 --- a/src/test/java/gov/cms/madie/hqmf/XMLUtilityTest.java +++ b/src/test/java/gov/cms/madie/hqmf/XMLUtilityTest.java @@ -3,7 +3,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; @@ -21,63 +20,55 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class XMLUtilityTest { - XMLUtility xmlUtility; + XMLUtility xmlUtility; - @BeforeEach - public void setup() { - xmlUtility = XMLUtility.getInstance(); - } + @BeforeEach + public void setup() { + xmlUtility = XMLUtility.getInstance(); + } - @Test - void testGetXmlResource() { - String xmlResource = xmlUtility.getXMLResource("xsl/qdm_v5_6_measure_details.xsl"); - assertThat(xmlResource, is(notNullValue())); - } + @Test + void testGetXmlResource() { + String xmlResource = xmlUtility.getXMLResource("xsl/qdm_v5_6_measure_details.xsl"); + assertThat(xmlResource, is(notNullValue())); + } - @Test - void testBuildTransformerFactory() { - TransformerFactory transformerFactory = xmlUtility.buildTransformerFactory(); - assertThat(transformerFactory, is(notNullValue())); - } + @Test + void testBuildTransformerFactory() { + TransformerFactory transformerFactory = xmlUtility.buildTransformerFactory(); + assertThat(transformerFactory, is(notNullValue())); + } - @Test - void testBuildDocumentBuilderFactory() throws ParserConfigurationException { - DocumentBuilderFactory documentBuilderFactory = xmlUtility.buildDocumentBuilderFactory(); - assertThat(documentBuilderFactory, is(notNullValue())); - } + @Test + void testBuildDocumentBuilderFactory() throws ParserConfigurationException { + DocumentBuilderFactory documentBuilderFactory = xmlUtility.buildDocumentBuilderFactory(); + assertThat(documentBuilderFactory, is(notNullValue())); + } - @Test - void testBuildSaxParserFactory() throws SAXNotSupportedException, SAXNotRecognizedException, ParserConfigurationException { - SAXParserFactory saxParserFactory = xmlUtility.buildSaxParserFactory(); - assertThat(saxParserFactory, is(notNullValue())); - } + @Test + void testBuildSaxParserFactory() + throws SAXNotSupportedException, SAXNotRecognizedException, ParserConfigurationException { + SAXParserFactory saxParserFactory = xmlUtility.buildSaxParserFactory(); + assertThat(saxParserFactory, is(notNullValue())); + } - @Test - void testBuildSchemaFactory() throws SAXNotSupportedException, SAXNotRecognizedException { - SchemaFactory schemaFactory = xmlUtility.buildSchemaFactory(); - assertThat(schemaFactory, is(notNullValue())); - } + @Test + void testBuildSchemaFactory() throws SAXNotSupportedException, SAXNotRecognizedException { + SchemaFactory schemaFactory = xmlUtility.buildSchemaFactory(); + assertThat(schemaFactory, is(notNullValue())); + } - @Test - void testGetXmlReader() throws SAXException { - SAXParser parser = mock(SAXParser.class); - XMLReader reader = mock(XMLReader.class); - when(parser.getXMLReader()).thenReturn(reader); - XMLReader xmlReader = xmlUtility.getXMLReader(parser); - assertThat(xmlReader, is(equalTo(reader))); - } - -} \ No newline at end of file + @Test + void testGetXmlReader() throws SAXException { + SAXParser parser = mock(SAXParser.class); + XMLReader reader = mock(XMLReader.class); + when(parser.getXMLReader()).thenReturn(reader); + XMLReader xmlReader = xmlUtility.getXMLReader(parser); + assertThat(xmlReader, is(equalTo(reader))); + } +} diff --git a/src/test/java/gov/cms/madie/hqmf/qdm_5_6/HQMFGeneratorTest.java b/src/test/java/gov/cms/madie/hqmf/qdm_5_6/HQMFGeneratorTest.java index 9fe7ca6..49215e5 100644 --- a/src/test/java/gov/cms/madie/hqmf/qdm_5_6/HQMFGeneratorTest.java +++ b/src/test/java/gov/cms/madie/hqmf/qdm_5_6/HQMFGeneratorTest.java @@ -2,39 +2,67 @@ import gov.cms.madie.hqmf.dto.MeasureExport; import gov.cms.madie.packaging.utils.ResourceFileUtil; -import org.junit.jupiter.api.BeforeEach; +import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +@Slf4j @ExtendWith(MockitoExtension.class) class HQMFGeneratorTest implements ResourceFileUtil { - @Mock - HQMFMeasureDetailsGenerator hqmfMeasureDetailsGenerator; - @Mock - HQMFDataCriteriaGenerator hqmfDataCriteriaGenerator; - - @InjectMocks - HQMFGenerator hqmfGenerator; - - @Test - void generate() throws Exception { - String simpleXml = getStringFromTestResource("/simplexml/BMAT1644A-v0-0-001-QDM-5-6.xml"); - MeasureExport measureExport = MeasureExport.builder() - .simpleXml(simpleXml) - .releaseVersion("1.3.1") - .build(); - String hqmf = hqmfGenerator.generate(measureExport); - assertThat(hqmf, is(notNullValue())); - } -} \ No newline at end of file + @Mock HQMFMeasureDetailsGenerator hqmfMeasureDetailsGenerator; + @Mock HQMFDataCriteriaGenerator hqmfDataCriteriaGenerator; + + @InjectMocks HQMFGenerator hqmfGenerator; + + final String baseHqmf = + """ + + + + + + </qualityMeasureSet> + </componentOf> +</QualityMeasureDocument> +"""; + + final String dataCriteriaXml = + """ +<component xmlns:cql-ext="urn:hhs-cql:hqmf-n1-extensions:v1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <dataCriteriaSection> + <templateId> + <item extension="2021-02-01" root="2.16.840.1.113883.10.20.28.2.6"/> + </templateId> + <code code="57025-9" codeSystem="2.16.840.1.113883.6.1"/> + <title value="Data Criteria Section"/> + <text/> + </dataCriteriaSection> +</component> + """; + + @Test + void generate() throws Exception { + String simpleXml = getStringFromTestResource("/simplexml/BMAT1644A-v0-0-001-QDM-5-6.xml"); + MeasureExport measureExport = + MeasureExport.builder().simpleXml(simpleXml).releaseVersion("1.3.1").build(); + when(hqmfMeasureDetailsGenerator.generate(any(MeasureExport.class))).thenReturn(baseHqmf); + when(hqmfDataCriteriaGenerator.generate(any(MeasureExport.class))).thenReturn(dataCriteriaXml); + String hqmf = hqmfGenerator.generate(measureExport); + assertThat(hqmf, is(notNullValue())); + assertThat( + hqmf.trim().startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"), + is(true)); + assertThat(hqmf.contains("<dataCriteriaSection>"), is(true)); + } +} diff --git a/src/test/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureDetailsGeneratorTest.java b/src/test/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureDetailsGeneratorTest.java index 5da53e9..71183bc 100644 --- a/src/test/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureDetailsGeneratorTest.java +++ b/src/test/java/gov/cms/madie/hqmf/qdm_5_6/HQMFMeasureDetailsGeneratorTest.java @@ -18,26 +18,27 @@ @Slf4j @ExtendWith(MockitoExtension.class) class HQMFMeasureDetailsGeneratorTest implements ResourceFileUtil { - HQMFMeasureDetailsGenerator hqmfMeasureDetailsGenerator; + HQMFMeasureDetailsGenerator hqmfMeasureDetailsGenerator; - @BeforeEach - void setUp() { - hqmfMeasureDetailsGenerator = new HQMFMeasureDetailsGenerator(); - } + @BeforeEach + void setUp() { + hqmfMeasureDetailsGenerator = new HQMFMeasureDetailsGenerator(); + } - @Test - void generate() { - String simpleXml = getStringFromTestResource("/simplexml/BMAT1644A-v0-0-001-QDM-5-6.xml"); - MeasureExport measureExport = MeasureExport.builder() - .simpleXml(simpleXml) - .releaseVersion("1.3.1") - .build(); - String hqmf = hqmfMeasureDetailsGenerator.generate(measureExport); - log.info(hqmf); - assertThat(hqmf, is(notNullValue())); - assertThat(hqmf, is(not(equalTo(simpleXml)))); - assertThat(hqmf.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + - "<QualityMeasureDocument"), is(true)); - assertThat(hqmf.contains("<low value=\"20240101\"/>"), is(true)); - } -} \ No newline at end of file + @Test + void generate() { + String simpleXml = getStringFromTestResource("/simplexml/BMAT1644A-v0-0-001-QDM-5-6.xml"); + MeasureExport measureExport = + MeasureExport.builder().simpleXml(simpleXml).releaseVersion("1.3.1").build(); + String hqmf = hqmfMeasureDetailsGenerator.generate(measureExport); + log.info(hqmf); + assertThat(hqmf, is(notNullValue())); + assertThat(hqmf, is(not(equalTo(simpleXml)))); + assertThat( + hqmf.startsWith( + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + + "<QualityMeasureDocument"), + is(true)); + assertThat(hqmf.contains("<low value=\"20240101\"/>"), is(true)); + } +} diff --git a/src/test/java/gov/cms/madie/resources/PackageControllerTest.java b/src/test/java/gov/cms/madie/resources/PackageControllerTest.java index 2866038..45fea05 100644 --- a/src/test/java/gov/cms/madie/resources/PackageControllerTest.java +++ b/src/test/java/gov/cms/madie/resources/PackageControllerTest.java @@ -13,7 +13,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import static org.hamcrest.CoreMatchers.equalTo; @@ -82,10 +81,10 @@ void testGenerateHqmfForUnsupportedModel() { MeasureExport measureExport = MeasureExport.builder().measure(measure).build(); String errorMessage = "Unsupported model type: " + measure.getModel(); Exception ex = - Assertions.assertThrows( - UnsupportedModelException.class, - () -> packageController.generateHqmf(measureExport), - errorMessage); + Assertions.assertThrows( + UnsupportedModelException.class, + () -> packageController.generateHqmf(measureExport), + errorMessage); assertThat(ex.getMessage(), is(equalTo(errorMessage))); } @@ -94,21 +93,20 @@ void testGenerateHqmfForUnsupportedModelMissingMeasure() { MeasureExport measureExport = MeasureExport.builder().build(); String errorMessage = "Unsupported model type: NONE"; Exception ex = - Assertions.assertThrows( - UnsupportedModelException.class, - () -> packageController.generateHqmf(measureExport), - errorMessage); + Assertions.assertThrows( + UnsupportedModelException.class, + () -> packageController.generateHqmf(measureExport), + errorMessage); assertThat(ex.getMessage(), is(equalTo(errorMessage))); } @Test void testGenerateHqmfReturnsHqmf() throws Exception { - MeasureExport measureExport = MeasureExport.builder() - .measure(measure) - .build(); + MeasureExport measureExport = MeasureExport.builder().measure(measure).build(); HQMFGenerator generator = mock(HQMFGenerator.class); when(factory.getHQMFGenerator()).thenReturn(generator); - when(generator.generate(any(MeasureExport.class))).thenReturn("<QualityMeasureDocument></QualityMeasureDocument>"); + when(generator.generate(any(MeasureExport.class))) + .thenReturn("<QualityMeasureDocument></QualityMeasureDocument>"); String hqmf = packageController.generateHqmf(measureExport); assertThat(hqmf, is(equalTo("<QualityMeasureDocument></QualityMeasureDocument>"))); }