=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramDataEntryService.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramDataEntryService.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/ProgramDataEntryService.java 2011-05-27 01:09:01 +0000 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2009, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.hisp.dhis.program; + +import java.util.Collection; + +import org.hisp.dhis.i18n.I18n; +import org.hisp.dhis.organisationunit.OrganisationUnit; +import org.hisp.dhis.patientdatavalue.PatientDataValue; + +/** + * @author Chau Thu Tran + * @version $ ProgramDataEntryService.java May 26, 2011 3:56:03 PM $ + * + */ +public interface ProgramDataEntryService +{ + String prepareDataEntryFormForEntry( String htmlCode, Collection dataValues, String disabled, + I18n i18n, ProgramStage programStage, ProgramStageInstance programStageInstance, + OrganisationUnit organisationUnit ); +} === added file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramDataEntryService.java' --- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramDataEntryService.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/program/DefaultProgramDataEntryService.java 2011-05-27 01:09:01 +0000 @@ -0,0 +1,1189 @@ +/* + * Copyright (c) 2004-2009, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.hisp.dhis.program; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang.BooleanUtils; +import org.hisp.dhis.dataelement.DataElement; +import org.hisp.dhis.dataelement.DataElementService; +import org.hisp.dhis.i18n.I18n; +import org.hisp.dhis.organisationunit.OrganisationUnit; +import org.hisp.dhis.patientdatavalue.PatientDataValue; +import org.hisp.dhis.patientdatavalue.PatientDataValueService; + +/** + * @author Chau Thu Tran + * @version $ DefaultProgramDataEntryService.java May 26, 2011 3:59:43 PM $ + * + */ +public class DefaultProgramDataEntryService + implements ProgramDataEntryService +{ + private static final String EMPTY = ""; + + private static final String UNKNOW_CLINIC = "unknow_clinic"; + + private static final String NOTAVAILABLE = "not_available"; + + // ------------------------------------------------------------------------- + // Dependencies + // ------------------------------------------------------------------------- + + private PatientDataValueService patientDataValueService; + + public void setPatientDataValueService( PatientDataValueService patientDataValueService ) + { + this.patientDataValueService = patientDataValueService; + } + + private DataElementService dataElementService; + + public void setDataElementService( DataElementService dataElementService ) + { + this.dataElementService = dataElementService; + } + + private ProgramStageInstanceService programStageInstanceService; + + public void setProgramStageInstanceService( ProgramStageInstanceService programStageInstanceService ) + { + this.programStageInstanceService = programStageInstanceService; + } + + private ProgramStageService programStageService; + + public void setProgramStageService( ProgramStageService programStageService ) + { + this.programStageService = programStageService; + } + + private ProgramStageDataElementService programStageDataElementService; + + public void setProgramStageDataElementService( ProgramStageDataElementService programStageDataElementService ) + { + this.programStageDataElementService = programStageDataElementService; + } + + // ------------------------------------------------------------------------- + // Implementation methods + // ------------------------------------------------------------------------- + + @Override + public String prepareDataEntryFormForEntry( String htmlCode, Collection dataValues, + String disabled, I18n i18n, ProgramStage programStage, ProgramStageInstance programStageInstance, + OrganisationUnit organisationUnit ) + { + Map> mapDataValue = new HashMap>(); + + String result = ""; + + result = populateCustomDataEntryForTextBox( htmlCode, dataValues, disabled, i18n, + programStage, programStageInstance, organisationUnit, mapDataValue ); + + result = populateCustomDataEntryForBoolean( result, dataValues, disabled, i18n, + programStage, programStageInstance, organisationUnit, mapDataValue ); + + result = populateCustomDataEntryForMutiDimentionalString( result, dataValues, + disabled, i18n, programStage, programStageInstance, organisationUnit, mapDataValue ); + + result = populateCustomDataEntryForDate( result, dataValues, disabled, i18n, + programStage, programStageInstance, organisationUnit, mapDataValue ); + + result = populateI18nStrings( result, i18n ); + + return result; + } + + // ------------------------------------------------------------------------- + // Supportive methods + // ------------------------------------------------------------------------- + + private String populateCustomDataEntryForTextBox( String dataEntryFormCode, + Collection dataValues, String disabled, I18n i18n, ProgramStage programStage, ProgramStageInstance programStageInstance, + OrganisationUnit organisationUnit, Map> mapDataValue ) + { + // --------------------------------------------------------------------- + // Inline Javascript to add to HTML before outputting + // --------------------------------------------------------------------- + + final String jsCodeForInputs = " $DISABLED onchange=\"saveValueCustom( this )\" data=\"{compulsory:$COMPULSORY, optionComboId:$OPTIONCOMBOID, dataElementId:$DATAELEMENTID, dataElementName:'$DATAELEMENTNAME', dataElementType:'$DATAELEMENTTYPE', programStageId:$PROGRAMSTAGEID, programStageName: '$PROGRAMSTAGENAME', orgUnitName:'$ORGUNITNAME'}\" onkeypress=\"return keyPress(event, this)\" "; + + // --------------------------------------------------------------------- + // Metadata code to add to HTML before outputting + // --------------------------------------------------------------------- + + StringBuffer sb = new StringBuffer(); + + // --------------------------------------------------------------------- + // Pattern to match data elements in the HTML code + // --------------------------------------------------------------------- + + Pattern dataElementPattern = Pattern.compile( "(", Pattern.DOTALL ); + Matcher dataElementMatcher = dataElementPattern.matcher( dataEntryFormCode ); + + // --------------------------------------------------------------------- + // Pattern to extract data element ID from data element field + // --------------------------------------------------------------------- + + Pattern identifierPattern = Pattern + .compile( "\"value\\[([\\p{Digit}.]*)\\].value:value\\[([\\p{Digit}.]*)\\].value:value\\[([\\p{Digit}.]*)\\].value\"" ); + + // --------------------------------------------------------------------- + // Iterate through all matching data element fields + // --------------------------------------------------------------------- + + Map dataElementMap = getDataElementMap( programStage ); + + while ( dataElementMatcher.find() ) + { + // ----------------------------------------------------------------- + // Get HTML input field code + // ----------------------------------------------------------------- + + String compulsory = "null"; + String dataElementCode = dataElementMatcher.group( 1 ); + + Matcher identifierMatcher = identifierPattern.matcher( dataElementCode ); + + if ( identifierMatcher.find() && identifierMatcher.groupCount() > 0 ) + { + // ------------------------------------------------------------- + // Get data element ID of data element + // ------------------------------------------------------------- + + int programStageId = Integer.parseInt( identifierMatcher.group( 1 ) ); + + int dataElementId = Integer.parseInt( identifierMatcher.group( 2 ) ); + + int optionComboId = Integer.parseInt( identifierMatcher.group( 3 ) ); + + DataElement dataElement = null; + + String programStageName = programStage.getName(); + + if ( programStageId != programStage.getId() ) + { + dataElement = dataElementService.getDataElement( dataElementId ); + + ProgramStage otherProgramStage = programStageService.getProgramStage( programStageId ); + programStageName = otherProgramStage != null ? otherProgramStage.getName() : "N/A"; + + } + else + { + dataElement = dataElementMap.get( dataElementId ); + if ( dataElement == null ) + { + return i18n.getString( "program_stage_lack_data_elements" ); + } + + ProgramStageDataElement psde = programStageDataElementService.get( programStage, dataElement ); + + compulsory = BooleanUtils.toStringTrueFalse( psde.isCompulsory() ); + } + + if ( dataElement == null ) + { + continue; + } + if ( !DataElement.VALUE_TYPE_INT.equals( dataElement.getType() ) + && !DataElement.VALUE_TYPE_STRING.equals( dataElement.getType() ) ) + { + continue; + } + // ------------------------------------------------------------- + // Find type of data element + // ------------------------------------------------------------- + + String dataElementType = dataElement.getDetailedNumberType(); + + // ------------------------------------------------------------- + // Find existing value of data element in data set + // ------------------------------------------------------------- + + PatientDataValue patientDataValue = null; + + String dataElementValue = EMPTY; + + if ( programStageId != programStage.getId() ) + { + Collection patientDataValues = mapDataValue.get( programStageId ); + + if ( patientDataValues == null ) + { + ProgramStage otherProgramStage = programStageService.getProgramStage( programStageId ); + ProgramStageInstance otherProgramStageInstance = programStageInstanceService + .getProgramStageInstance( programStageInstance.getProgramInstance(), otherProgramStage ); + patientDataValues = patientDataValueService.getPatientDataValues( otherProgramStageInstance ); + mapDataValue.put( programStageId, patientDataValues ); + } + + patientDataValue = getValue( patientDataValues, dataElementId, optionComboId ); + + dataElementValue = patientDataValue != null ? patientDataValue.getValue() : dataElementValue; + } + else + { + patientDataValue = getValue( dataValues, dataElementId ); + + dataElementValue = patientDataValue != null ? patientDataValue.getValue() : dataElementValue; + } + + // ------------------------------------------------------------- + // Insert value of data element in output code + // ------------------------------------------------------------- + + if ( dataElementCode.contains( "value=\"\"" ) ) + { + dataElementCode = dataElementCode.replace( "value=\"\"", "value=\"" + dataElementValue + "\"" ); + } + else + { + dataElementCode += "value=\"" + dataElementValue + "\""; + } + + // ------------------------------------------------------------- + // Remove placeholder view attribute from input field + // ------------------------------------------------------------- + + dataElementCode = dataElementCode.replaceAll( "view=\".*?\"", "" ); + + // ------------------------------------------------------------- + // Append Javascript code and meta data (type/min/max) for + // persisting to output code, and insert value and type for + // fields + // ------------------------------------------------------------- + + String appendCode = dataElementCode; + + appendCode += jsCodeForInputs; + + appendCode += " />"; + + // ----------------------------------------------------------- + // Check if this dataElement is from another programStage then + // disable + // If programStagsInstance is completed then disabled it + // ----------------------------------------------------------- + + disabled = ""; + if ( programStageId == programStage.getId() && !programStageInstance.isCompleted() ) + { + // ----------------------------------------------------------- + // Add ProvidedByOtherFacility checkbox + // ----------------------------------------------------------- + + appendCode = addProvidedByOtherFacilityCheckbox( appendCode, patientDataValue ); + + } + else + { + disabled = "disabled=\"\""; + } + + // ----------------------------------------------------------- + // + // ----------------------------------------------------------- + + String orgUnitName = i18n.getString( NOTAVAILABLE ); + if ( patientDataValue != null ) + { + if ( patientDataValue.isProvidedByAnotherFacility() ) + { + orgUnitName = i18n.getString( UNKNOW_CLINIC ); + } + else + { + orgUnitName = patientDataValue.getOrganisationUnit().getName(); + } + } + + appendCode = appendCode.replace( "$DATAELEMENTID", String.valueOf( dataElementId ) ); + appendCode = appendCode.replace( "$PROGRAMSTAGEID", String.valueOf( programStageId ) ); + appendCode = appendCode.replace( "$PROGRAMSTAGENAME", programStageName ); + appendCode = appendCode.replace( "$ORGUNITNAME", orgUnitName ); + appendCode = appendCode.replace( "$OPTIONCOMBOID", String.valueOf( optionComboId ) ); + appendCode = appendCode.replace( "$DATAELEMENTNAME", dataElement.getName() ); + appendCode = appendCode.replace( "$DATAELEMENTTYPE", dataElementType ); + appendCode = appendCode.replace( "$DISABLED", disabled ); + appendCode = appendCode.replace( "$COMPULSORY", compulsory ); + appendCode = appendCode.replace( "$SAVEMODE", "false" ); + + dataElementMatcher.appendReplacement( sb, appendCode ); + } + } + + dataElementMatcher.appendTail( sb ); + + return sb.toString(); + } + + private String populateCustomDataEntryForBoolean( String dataEntryFormCode, + Collection dataValues, String disabled, I18n i18n, ProgramStage programStage, + ProgramStageInstance programStageInstance, OrganisationUnit organisationUnit, + Map> mapDataValue ) + { + + // --------------------------------------------------------------------- + // Inline Javascript to add to HTML before outputting + // --------------------------------------------------------------------- + + final String jsCodeForBoolean = " name=\"entryselect\" data=\"{compulsory:$COMPULSORY, dataElementId:$DATAELEMENTID, dataElementName:'$DATAELEMENTNAME', dataElementType:'$DATAELEMENTTYPE', programStageId:$PROGRAMSTAGEID, programStageName: '$PROGRAMSTAGENAME', orgUnitName:'$ORGUNITNAME'}\" $DISABLED onchange=\"saveChoiceCustom( $PROGRAMSTAGEID, $DATAELEMENTID,this)\""; + + // --------------------------------------------------------------------- + // Metadata code to add to HTML before outputting + // --------------------------------------------------------------------- + + final String metaDataCode = "$DATAELEMENTNAME" + + "$DATAELEMENTTYPE"; + StringBuffer sb = new StringBuffer(); + + // --------------------------------------------------------------------- + // Pattern to match data elements in the HTML code + // --------------------------------------------------------------------- + + Pattern dataElementPattern = Pattern.compile( "(", Pattern.DOTALL ); + Matcher dataElementMatcher = dataElementPattern.matcher( dataEntryFormCode ); + + // --------------------------------------------------------------------- + // Pattern to extract data element ID from data element field + // --------------------------------------------------------------------- + + Pattern identifierPattern = Pattern.compile( "value\\[(.*)\\].boolean:value\\[(.*)\\].boolean" ); + + // --------------------------------------------------------------------- + // Iterate through all matching data element fields + // --------------------------------------------------------------------- + + Map dataElementMap = getDataElementMap( programStage ); + + while ( dataElementMatcher.find() ) + { + // ----------------------------------------------------------------- + // Get HTML input field code + // ----------------------------------------------------------------- + + String compulsory = "null"; + String dataElementCode = dataElementMatcher.group( 1 ); + Matcher identifierMatcher = identifierPattern.matcher( dataElementCode ); + if ( identifierMatcher.find() && identifierMatcher.groupCount() > 0 ) + { + // ------------------------------------------------------------- + // Get data element ID of data element + // ------------------------------------------------------------- + + int programStageId = Integer.parseInt( identifierMatcher.group( 1 ) ); + + int dataElementId = Integer.parseInt( identifierMatcher.group( 2 ) ); + + DataElement dataElement = null; + + String programStageName = programStage.getName(); + + if ( programStageId != programStage.getId() ) + { + dataElement = dataElementService.getDataElement( dataElementId ); + + ProgramStage otherProgramStage = programStageService.getProgramStage( programStageId ); + programStageName = otherProgramStage != null ? otherProgramStage.getName() : "N/A"; + } + else + { + dataElement = dataElementMap.get( dataElementId ); + if ( dataElement == null ) + { + return i18n.getString( "program_stage_lack_data_elements" ); + } + + ProgramStageDataElement psde = programStageDataElementService.get( programStage, dataElement ); + + compulsory = BooleanUtils.toStringTrueFalse( psde.isCompulsory() ); + } + + if ( dataElement == null ) + { + continue; + } + + if ( !DataElement.VALUE_TYPE_BOOL.equals( dataElement.getType() ) ) + { + continue; + } + // ------------------------------------------------------------- + // Find type of data element + // ------------------------------------------------------------- + + String dataElementType = dataElement.getType(); + + // ------------------------------------------------------------- + // Find existing value of data element in data set + // ------------------------------------------------------------- + + PatientDataValue patientDataValue = null; + + String dataElementValue = EMPTY; + + if ( programStageId != programStage.getId() ) + { + Collection patientDataValues = mapDataValue.get( programStageId ); + + if ( patientDataValues == null ) + { + ProgramStage otherProgramStage = programStageService.getProgramStage( programStageId ); + ProgramStageInstance otherProgramStageInstance = programStageInstanceService + .getProgramStageInstance( programStageInstance.getProgramInstance(), otherProgramStage ); + patientDataValues = patientDataValueService.getPatientDataValues( otherProgramStageInstance ); + mapDataValue.put( programStageId, patientDataValues ); + } + + patientDataValue = getValue( patientDataValues, dataElementId ); + + dataElementValue = patientDataValue != null ? patientDataValue.getValue() : dataElementValue; + } + else + { + + patientDataValue = getValue( dataValues, dataElementId ); + + if ( patientDataValue != null ) + { + dataElementValue = patientDataValue.getValue(); + } + } + + String appendCode = dataElementCode; + appendCode = appendCode.replace( "name=\"entryselect\"", jsCodeForBoolean ); + + // ------------------------------------------------------------- + // Insert value of data element in output code + // ------------------------------------------------------------- + + if ( patientDataValue != null ) + { + + if ( dataElementValue.equalsIgnoreCase( "true" ) ) + { + appendCode = appendCode.replace( "