← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 10993: merged with psipdfdataentryform, still wip

 

Merge authors:
  James Chang (jamesbchang)
  Morten Olav Hansen (mortenoh)
------------------------------------------------------------
revno: 10993 [merge]
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Sat 2013-05-25 13:19:23 +0700
message:
  merged with psipdfdataentryform, still wip
added:
  dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/
  dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/DefaultPdfDataEntryFormService.java
  dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfDataEntryFormService.java
  dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfDataEntryFormUtil.java
  dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfFieldCell.java
  dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfFormFontSettings.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/PDFFormController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/PdfDataEntryFormImportUtil.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElement.java
  dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetService.java
  dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java
  dhis-2/dhis-dxf2/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-importexport/pom.xml
  dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/util/ImportDataValueTask.java
  dhis-2/dhis-web/dhis-web-importexport/src/main/resources/org/hisp/dhis/importexport/i18n_module.properties
  dhis-2/dhis-web/dhis-web-importexport/src/main/webapp/dhis-web-importexport/index.vm
  dhis-2/dhis-web/dhis-web-importexport/src/main/webapp/dhis-web-importexport/mainMenu.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/dataSetList.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programStage.vm


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElement.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElement.java	2013-04-19 15:02:38 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElement.java	2013-05-25 06:19:23 +0000
@@ -1,7 +1,7 @@
 package org.hisp.dhis.dataelement;
 
 /*
- * Copyright (c) 2004-2012, University of Oslo
+ * Copyright (c) 2004-2013, University of Oslo
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without

=== modified file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetService.java'
--- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetService.java	2012-09-10 08:50:51 +0000
+++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetService.java	2013-05-25 06:19:23 +0000
@@ -27,6 +27,10 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import org.hisp.dhis.dxf2.importsummary.ImportSummary;
+import org.hisp.dhis.dxf2.metadata.ImportOptions;
+import org.hisp.dhis.scheduling.TaskId;
+
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
@@ -34,18 +38,14 @@
 import java.util.Date;
 import java.util.Set;
 
-import org.hisp.dhis.dxf2.importsummary.ImportSummary;
-import org.hisp.dhis.dxf2.metadata.ImportOptions;
-import org.hisp.dhis.scheduling.TaskId;
-
 public interface DataValueSetService
 {
     void writeDataValueSet( String dataSet, String period, String orgUnit, OutputStream out );
-    
+
     void writeDataValueSet( Set<String> dataSets, Date startDate, Date endDate, Set<String> orgUnits, OutputStream out );
-    
+
     void writeDataValueSetCsv( Set<String> dataSets, Date startDate, Date endDate, Set<String> orgUnits, Writer writer );
-    
+
     ImportSummary saveDataValueSet( InputStream in );
 
     ImportSummary saveDataValueSetJson( InputStream in );
@@ -59,4 +59,6 @@
     ImportSummary saveDataValueSetJson( InputStream in, ImportOptions importOptions, TaskId taskId );
 
     ImportSummary saveDataValueSetCsv( Reader reader, ImportOptions importOptions, TaskId id );
+
+    ImportSummary saveDataValueSetPdf( InputStream in, ImportOptions importOptions, TaskId id );
 }

=== modified file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java'
--- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java	2013-04-19 16:05:26 +0000
+++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java	2013-05-25 06:19:23 +0000
@@ -27,25 +27,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static org.hisp.dhis.importexport.ImportStrategy.NEW;
-import static org.hisp.dhis.importexport.ImportStrategy.NEW_AND_UPDATES;
-import static org.hisp.dhis.importexport.ImportStrategy.UPDATES;
-import static org.hisp.dhis.system.notification.NotificationLevel.ERROR;
-import static org.hisp.dhis.system.notification.NotificationLevel.INFO;
-import static org.hisp.dhis.system.util.ConversionUtils.wrap;
-import static org.hisp.dhis.system.util.DateUtils.getDefaultDate;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
+import au.com.bytecode.opencsv.CSVReader;
 import org.amplecode.quick.BatchHandler;
 import org.amplecode.quick.BatchHandlerFactory;
 import org.amplecode.staxwax.factory.XMLFactory;
@@ -66,6 +48,7 @@
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
 import org.hisp.dhis.dxf2.metadata.ImportOptions;
+import org.hisp.dhis.dxf2.pdfform.PdfDataEntryFormUtil;
 import org.hisp.dhis.dxf2.utils.JacksonUtils;
 import org.hisp.dhis.importexport.ImportStrategy;
 import org.hisp.dhis.jdbc.batchhandler.DataValueBatchHandler;
@@ -82,7 +65,22 @@
 import org.hisp.dhis.user.CurrentUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import au.com.bytecode.opencsv.CSVReader;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.hisp.dhis.importexport.ImportStrategy.*;
+import static org.hisp.dhis.system.notification.NotificationLevel.ERROR;
+import static org.hisp.dhis.system.notification.NotificationLevel.INFO;
+import static org.hisp.dhis.system.util.ConversionUtils.wrap;
+import static org.hisp.dhis.system.util.DateUtils.getDefaultDate;
 
 /**
  * @author Lars Helge Overland
@@ -240,6 +238,23 @@
         }
     }
 
+    public ImportSummary saveDataValueSetPdf( InputStream in, ImportOptions importOptions, TaskId id )
+    {
+        try
+        {
+            DataValueSet dataValueSet = PdfDataEntryFormUtil.getDataValueSet( in );
+
+            return saveDataValueSet( importOptions, id, dataValueSet );
+        }
+        catch ( RuntimeException ex )
+        {
+            log.error( DebugUtils.getStackTrace( ex ) );
+            notifier.clear( id ).notify( id, ERROR, "Unfortunately the process failed, check the logs", true );
+            return new ImportSummary( ImportStatus.ERROR, "The import process failed: " + ex.getMessage() );
+        }
+    }
+
+
     private ImportSummary saveDataValueSet( ImportOptions importOptions, TaskId id, DataValueSet dataValueSet )
     {
         notifier.clear( id ).notify( id, "Process started" );
@@ -352,9 +367,9 @@
             {
                 continue;
             }
-            
+
             String valueValid = ValidationUtils.dataValueIsValid( dataValue.getValue(), dataElement );
-            
+
             if ( valueValid != null )
             {
                 summary.getConflicts().add( new ImportConflict( DataValue.class.getSimpleName(), valueValid ) );

=== added directory 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform'
=== added file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/DefaultPdfDataEntryFormService.java'
--- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/DefaultPdfDataEntryFormService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/DefaultPdfDataEntryFormService.java	2013-05-25 06:19:23 +0000
@@ -0,0 +1,848 @@
+package org.hisp.dhis.dxf2.pdfform;
+
+/*
+ * Copyright (c) 2004-2013, 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.
+ */
+
+import com.lowagie.text.Chunk;
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Element;
+import com.lowagie.text.Font;
+import com.lowagie.text.Paragraph;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.CMYKColor;
+import com.lowagie.text.pdf.PdfAnnotation;
+import com.lowagie.text.pdf.PdfAppearance;
+import com.lowagie.text.pdf.PdfBorderDictionary;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfFormField;
+import com.lowagie.text.pdf.PdfPCell;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.PdfWriter;
+import com.lowagie.text.pdf.RadioCheckField;
+import com.lowagie.text.pdf.TextField;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataset.DataSet;
+import org.hisp.dhis.dataset.DataSetService;
+import org.hisp.dhis.dataset.Section;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.option.OptionService;
+import org.hisp.dhis.option.OptionSet;
+import org.hisp.dhis.period.CalendarPeriodType;
+import org.hisp.dhis.period.MonthlyPeriodType;
+import org.hisp.dhis.period.Period;
+import org.hisp.dhis.period.PeriodType;
+import org.hisp.dhis.program.ProgramStage;
+import org.hisp.dhis.program.ProgramStageDataElement;
+import org.hisp.dhis.program.ProgramStageSection;
+import org.hisp.dhis.program.ProgramStageService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.awt.*;
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.List;
+
+public class DefaultPdfDataEntryFormService
+    implements PdfDataEntryFormService
+{
+
+    private static final Color COLOR_BACKGROUDTEXTBOX = Color.LIGHT_GRAY;
+
+    private static final String TEXT_BLANK = " ";
+
+    // --- All the Settings Related
+    private static final int TEXTBOXWIDTH_NUMBERTYPE = 20;
+
+    private static final int TEXTBOXWIDTH = 200;
+
+    private static final int PERIODRANGE_PREVYEARS = 1;
+
+    private static final int PERIODRANGE_FUTUREYEARS = 2;
+
+    private static Integer MAX_OPTIONS_DISPLAYED = 30;
+
+    private static Integer PROGRAM_FORM_ROW_NUMBER = 10;
+
+    // Variables
+
+    private PdfFormFontSettings pdfFormFontSettings;
+
+    private I18nFormat format;
+
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private DataSetService dataSetService;
+
+    @Autowired
+    private ProgramStageService programStageService;
+
+    @Autowired
+    private OptionService optionService;
+
+    // -------------------------------------------------------------------------
+    // METHODS / CLASSES
+    // -------------------------------------------------------------------------
+
+    @Override
+    public void generatePDFDataEntryForm( Document document, PdfWriter writer, String inputUid, int typeId,
+        Rectangle pageSize, PdfFormFontSettings pdfFormFontSettings, I18nFormat format )
+    {
+        try
+        {
+
+            // STEP 1. Assign the parameters to the global variable
+            this.pdfFormFontSettings = pdfFormFontSettings;
+            this.format = format;
+
+            // STEP 2. Set Page Size
+            document.setPageSize( pageSize );
+
+            // STEP 3. PDF Document Open
+            document.open();
+
+            // STEP 3. Generate the PDF Form
+            if ( typeId == PdfDataEntryFormUtil.DATATYPE_DATASET )
+            {
+                setDataSet_DocumentContent( document, writer, inputUid );
+            }
+            else if ( typeId == PdfDataEntryFormUtil.DATATYPE_PROGRAMSTAGE )
+            {
+                setProgramStage_DocumentContent( document, writer, inputUid );
+            }
+
+            // STEP 4. Close the PDF Document
+            document.close();
+
+        }
+        catch ( Exception ex )
+        {
+            ex.printStackTrace();
+        }
+
+    }
+
+    // -----------------------------------------------------------------------------
+    // --- Retrieve Document Content - DataSet [START]
+
+    private void setDataSet_DocumentContent( Document document, PdfWriter writer, String dataSetUid )
+        throws IOException, DocumentException, ParseException, Exception
+    {
+
+        DataSet dataSet = dataSetService.getDataSet( dataSetUid );
+
+        if ( dataSet == null )
+        {
+            throw new Exception( "Error - DataSet not found for UID " + dataSetUid );
+        }
+        else
+        {
+            // Step 1. Set DataSet Name/Description
+            setDataSet_DocumentTopSection( document, dataSet );
+
+            // Add a line space
+            document.add( Chunk.NEWLINE );
+
+            // Step 2. Generate period listings
+            List<Period> periods = getPeriods_DataSet( dataSet.getPeriodType() );
+
+            // Step 3. 'Main Table' Create and Set
+            // The 'Main Table' is used to hold the layout of the page content.
+            PdfPTable mainTable = new PdfPTable( 1 ); // Table with 1 cell.
+            setMainTable( mainTable );
+
+            // Step 4. Add Organisation & Period input textfield
+            insertTable_OrgAndPeriod( mainTable, writer, periods );
+
+            // Step 5. Insert DataSet Info - [The MAIN Section]
+            insertTable_DataSet( mainTable, writer, dataSet );
+
+            // Step 6. Add the mainTable with content in it to the document.
+            document.add( mainTable );
+
+            document.add( Chunk.NEWLINE );
+            document.add( Chunk.NEWLINE );
+
+            // Step. 7 - Add 'Save As' Button
+            insertSaveAsButton( document, writer, PdfDataEntryFormUtil.LABELCODE_BUTTON_SAVEAS );
+        }
+    }
+
+    private void setDataSet_DocumentTopSection( Document document, DataSet dataSet )
+        throws DocumentException
+    {
+        document.add( new Paragraph( dataSet.getDisplayName(), pdfFormFontSettings
+            .getFont( PdfFormFontSettings.FONTTYPE_TITLE ) ) );
+
+        document.add( new Paragraph( dataSet.getDescription(), pdfFormFontSettings
+            .getFont( PdfFormFontSettings.FONTTYPE_DESCRIPTION ) ) );
+    }
+
+    private List<Period> getPeriods_DataSet( PeriodType periodType )
+        throws ParseException
+    {
+        Period period = setPeriodDateRange();
+
+        return ((CalendarPeriodType) periodType).generatePeriods( period.getStartDate(), period.getEndDate() );
+    }
+
+    private void setMainTable( PdfPTable mainTable )
+    {
+        mainTable.setWidthPercentage( 90.0f ); // Use 90% of space for Main
+        // Table Width.
+        mainTable.setHorizontalAlignment( Element.ALIGN_LEFT );
+    }
+
+    private void insertTable_DataSet( PdfPTable mainTable, PdfWriter writer, DataSet dataSet )
+        throws IOException, DocumentException
+    {
+        Rectangle rectangle = new Rectangle( TEXTBOXWIDTH, PdfDataEntryFormUtil.CONTENT_HEIGHT_DEFAULT );
+
+        if ( dataSet.getSections().size() > 0 )
+        {
+            // Sectioned Ones
+            for ( Section section : dataSet.getSections() )
+            {
+                insertTable_DataSetSections( mainTable, writer, rectangle, section.getDataElements(),
+                    section.getDisplayName() );
+            }
+
+        }
+        else
+        {
+            // Default one
+            insertTable_DataSetSections( mainTable, writer, rectangle, dataSet.getDataElements(), "" );
+        }
+
+    }
+
+    private void insertTable_DataSetSections( PdfPTable mainTable, PdfWriter writer, Rectangle rectangle,
+        Collection<DataElement> dataElements, String sectionName )
+        throws IOException, DocumentException
+    {
+
+        // Add Section Name and Section Spacing
+        insertTable_TextRow( writer, mainTable, rectangle, TEXT_BLANK );
+
+        if ( sectionName != "" )
+        {
+            insertTable_TextRow( writer, mainTable, rectangle, sectionName,
+                pdfFormFontSettings.getFont( PdfFormFontSettings.FONTTYPE_SECTIONHEADER ) );
+        }
+
+        // Create A Table To Add For Each Section
+        PdfPTable table = new PdfPTable( 2 ); // Code 1
+
+        for ( DataElement dataElement : dataElements )
+        {
+
+            addCell_Text( table, dataElement.getDisplayName(), Element.ALIGN_RIGHT );
+
+            String strFieldLabel = PdfDataEntryFormUtil.LABELCODE_DATAENTRYTEXTFIELD + dataElement.getUid() + "_"
+                + dataElement.getCategoryCombo().getSortedOptionCombos().get( 0 ).getUid();
+
+            String dataElementTextType = dataElement.getType();
+
+            // Yes Only case - render as Checkbox
+            if ( dataElementTextType.equals( DataElement.VALUE_TYPE_TRUE_ONLY ) )
+            {
+                addCell_WithCheckBox( table, writer, strFieldLabel );
+            }
+            else if ( dataElementTextType.equals( DataElement.VALUE_TYPE_BOOL ) )
+            {
+                // Create Yes - true, No - false, Select..
+                String[] optionList = new String[]{ "[No Value]", "Yes", "No" };
+                String[] valueList = new String[]{ "", "true", "false" };
+
+                // addCell_WithRadioButton(table, writer, strFieldLabel);
+                addCell_WithDropDownListField( table, strFieldLabel, optionList, valueList, rectangle, writer );
+            }
+            else if ( dataElementTextType.equals( DataElement.VALUE_TYPE_NUMBER ) )
+            {
+                rectangle = new Rectangle( TEXTBOXWIDTH_NUMBERTYPE, PdfDataEntryFormUtil.CONTENT_HEIGHT_DEFAULT );
+
+                addCell_WithTextField( table, rectangle, writer, strFieldLabel, PdfFieldCell.TYPE_TEXT_NUMBER );
+            }
+            // if(dataElementTextType.equals(DataElement.VALUE_TYPE_DATE))
+            else
+            {
+                // NOTE: When Rendering for DataSet, DataElement's OptionSet
+                // does not get rendered.
+                // Only for events, it gets rendered as dropdown list.
+                addCell_WithTextField( table, rectangle, writer, strFieldLabel );
+
+            }
+
+        }
+
+        PdfPCell cell_withInnerTable = new PdfPCell( table );
+        cell_withInnerTable.setBorder( Rectangle.NO_BORDER );
+
+        mainTable.addCell( cell_withInnerTable );
+
+    }
+
+    // --- Retrieve Document Content - DataSet [END]
+    // -----------------------------------------------------------------------------
+
+    // -----------------------------------------------------------------------------
+    // --- Retrieve Document Content - ProgramStage [START]
+
+    private void setProgramStage_DocumentContent( Document document, PdfWriter writer, String programStageUid )
+        throws IOException, DocumentException, ParseException, Exception
+    {
+
+        // Get ProgramStage
+        ProgramStage programStage = programStageService.getProgramStage( programStageUid );
+
+        if ( programStage == null )
+        {
+            throw new Exception( "Error - ProgramStage not found for UID " + programStageUid );
+        }
+        else
+        {
+
+            // STEP 1. Get Rectangle with TextBox Width to be used
+            Rectangle rectangle = new Rectangle( 0, 0, TEXTBOXWIDTH, PdfDataEntryFormUtil.CONTENT_HEIGHT_DEFAULT );
+
+            // STEP 2. Create Main Layout table and set the properties
+            PdfPTable mainTable = getProgramStageMainTable();
+
+            // STEP 3. Generate Period List for ProgramStage
+            List<Period> periods = getProgramStagePeriodList();
+
+            // STEP 4. Add Org Unit, Period, Hidden ProgramStageID Field
+            // Add Organisation & Period input textfield
+            insertTable_OrgAndPeriod( mainTable, writer, periods );
+
+            insertTable_TextRow( writer, mainTable, rectangle, TEXT_BLANK );
+
+            // Add ProgramStage Field - programStage.getId();
+            insertTable_HiddenValue( mainTable, rectangle, writer,
+                PdfDataEntryFormUtil.LABELCODE_PROGRAMSTAGEIDTEXTBOX, String.valueOf( programStage.getId() ) );
+
+            // STEP 5. Add ProgramStage Content to PDF - [The Main Section]
+            insertTable_ProgramStage( mainTable, writer, programStage );
+
+            // STEP 6. Add the mainTable to document
+            document.add( mainTable );
+
+        }
+
+    }
+
+    private void insertTable_ProgramStage( PdfPTable mainTable, PdfWriter writer, ProgramStage programStage )
+        throws IOException, DocumentException
+    {
+        Rectangle rectangle = new Rectangle( TEXTBOXWIDTH, PdfDataEntryFormUtil.CONTENT_HEIGHT_DEFAULT );
+
+        // Add Program Stage Sections
+        if ( programStage.getProgramStageSections().size() > 0 )
+        {
+            // Sectioned Ones
+            for ( ProgramStageSection section : programStage.getProgramStageSections() )
+            {
+                insertTable_ProgramStageSections( mainTable, rectangle, writer, section.getProgramStageDataElements() );
+            }
+
+        }
+        else
+        {
+            // Default one
+            insertTable_ProgramStageSections( mainTable, rectangle, writer, programStage.getProgramStageDataElements() );
+        }
+
+    }
+
+    private void insertTable_ProgramStageSections( PdfPTable mainTable, Rectangle rectangle, PdfWriter writer,
+        Collection<ProgramStageDataElement> programStageDataElements )
+        throws IOException, DocumentException
+    {
+
+        // Add one to column count due to date entry + one hidden height set
+        // field.
+        int colCount = programStageDataElements.size() + 1 + 1;
+
+        PdfPTable table = new PdfPTable( colCount ); // Code 1
+
+        float totalWidth = 800f;
+        float firstCellWidth_dateEntry = PdfDataEntryFormUtil.UNITSIZE_DEFAULT * 3;
+        float lastCellWidth_hidden = PdfDataEntryFormUtil.UNITSIZE_DEFAULT;
+        // float dataElementCell_offset = 4f;
+        float dataElementCellWidth = (totalWidth - firstCellWidth_dateEntry - lastCellWidth_hidden)
+            / programStageDataElements.size();
+
+        // Create 2 types of Rectangles, one for Date field, one for data
+        // elements
+        // - to be used when rendering them.
+        Rectangle rectangleDate = new Rectangle( 0, 0, PdfDataEntryFormUtil.UNITSIZE_DEFAULT * 2,
+            PdfDataEntryFormUtil.UNITSIZE_DEFAULT );
+        Rectangle rectangleDataElement = new Rectangle( 0, 0, dataElementCellWidth,
+            PdfDataEntryFormUtil.UNITSIZE_DEFAULT );
+
+        // Cell Width Set
+        float[] cellWidths = new float[colCount];
+
+        // Date Field Settings
+        cellWidths[0] = firstCellWidth_dateEntry;
+
+        for ( int i = 1; i < colCount - 1; i++ )
+        {
+            cellWidths[i] = dataElementCellWidth;
+        }
+
+        cellWidths[colCount - 1] = lastCellWidth_hidden;
+
+        table.setWidths( cellWidths );
+
+        // Create Header
+        table.addCell( new PdfPCell( new Phrase( "Date" ) ) );
+
+        // Add Program Data Elements Columns
+        for ( ProgramStageDataElement programStageDataElement : programStageDataElements )
+        {
+            DataElement dataElement = programStageDataElement.getDataElement();
+
+            table.addCell( new PdfPCell( new Phrase( dataElement.getDisplayFormName() ) ) );
+        }
+
+        table.addCell( new PdfPCell( new Phrase( TEXT_BLANK ) ) );
+
+        // ADD A HIDDEN INFO FOR ProgramStageID
+        // Print rows, having the data elements repeating on each column.
+
+        for ( int rowNo = 1; rowNo <= PROGRAM_FORM_ROW_NUMBER; rowNo++ )
+        {
+
+            // Add Date Column
+            String strFieldDateLabel = PdfDataEntryFormUtil.LABELCODE_DATADATETEXTFIELD + Integer.toString( rowNo );
+
+            addCell_WithTextField( table, rectangleDate, writer, strFieldDateLabel );
+
+            // Add Program Data Elements Columns
+            for ( ProgramStageDataElement programStageDataElement : programStageDataElements )
+            {
+                DataElement dataElement = programStageDataElement.getDataElement();
+
+                OptionSet optionSet = dataElement.getOptionSet();
+                String optionSetName = "";
+
+                // addCell_Text(table, dataElement.getFormName());
+
+                String strFieldLabel = PdfDataEntryFormUtil.LABELCODE_DATAENTRYTEXTFIELD
+                    + Integer.toString( dataElement.getId() )
+                    // + "_" + Integer.toString(programStageId) + "_" +
+                    // Integer.toString(rowNo);
+                    + "_" + Integer.toString( rowNo );
+
+                if ( optionSet != null )
+                {
+                    optionSetName = optionSet.getName();
+
+                    String query = ""; // Get All Option
+
+                    // TODO: This gets repeated <-- Create an array of the
+                    // options. and apply only once.
+                    List<String> options = optionService.getOptions( optionSet.getId(), query, MAX_OPTIONS_DISPLAYED );
+
+                    addCell_WithDropDownListField( table, strFieldLabel, options.toArray( new String[0] ),
+                        options.toArray( new String[0] ), rectangleDataElement, writer );
+                    // (int)(rectangleDataElement.getWidth())
+                }
+                else
+                {
+                    // NOTE: When Rendering for DataSet, DataElement's OptionSet
+                    // does not get rendered.
+                    // Only for events, it gets rendered as dropdown list.
+                    addCell_WithTextField( table, rectangleDataElement, writer, strFieldLabel );
+                }
+            }
+
+            addCell_Text( table, TEXT_BLANK, Element.ALIGN_LEFT );
+
+        }
+
+        PdfPCell cell_withInnerTable = new PdfPCell( table );
+        cell_withInnerTable.setBorder( Rectangle.NO_BORDER );
+
+        mainTable.addCell( cell_withInnerTable );
+
+    }
+
+    private List<Period> getProgramStagePeriodList()
+        throws ParseException
+    {
+        Period period = setPeriodDateRange();
+
+        PeriodType periodType = PeriodType.getPeriodTypeByName( MonthlyPeriodType.NAME );
+
+        return ((CalendarPeriodType) periodType).generatePeriods( period.getStartDate(), period.getEndDate() );
+    }
+
+    private PdfPTable getProgramStageMainTable()
+    {
+        PdfPTable mainTable = new PdfPTable( 1 ); // Code 1
+
+        mainTable.setTotalWidth( 800f );
+        mainTable.setLockedWidth( true );
+        mainTable.setHorizontalAlignment( Element.ALIGN_LEFT );
+
+        return mainTable;
+    }
+
+    // --- Retrieve Document Content - ProgramStage [END]
+    // -----------------------------------------------------------------------------
+
+    // -----------------------------------------------------------------------------
+    // ------------ Insert Section/Item Related Methods [START] ------------
+
+    private void insertTable_OrgAndPeriod( PdfPTable mainTable, PdfWriter writer, List<Period> periods )
+        throws IOException, DocumentException
+    {
+        // Input TextBox size
+        Rectangle rectangle = new Rectangle( TEXTBOXWIDTH, PdfDataEntryFormUtil.CONTENT_HEIGHT_DEFAULT );
+
+        // Add Organization ID/Period textfield
+        // Create A table to add for each group AT HERE
+        PdfPTable table = new PdfPTable( 2 ); // Code 1
+
+        addCell_Text( table, "OrganizationID", Element.ALIGN_LEFT );
+        addCell_WithTextField( table, rectangle, writer, PdfDataEntryFormUtil.LABELCODE_ORGID,
+            PdfFieldCell.TYPE_TEXT_ORGUNIT );
+
+        String[] periodsTitle = getPeriodTitles( periods, format );
+        String[] periodsValue = getPeriodValues( periods );
+
+        addCell_Text( table, "PeriodID", Element.ALIGN_LEFT );
+        addCell_WithDropDownListField( table, PdfDataEntryFormUtil.LABELCODE_PERIODID, periodsTitle, periodsValue,
+            rectangle, writer );
+
+        // Add to the main table
+        PdfPCell cell_withInnerTable = new PdfPCell( table );
+        // cell_withInnerTable.setPadding(0);
+        cell_withInnerTable.setBorder( Rectangle.NO_BORDER );
+
+        cell_withInnerTable.setHorizontalAlignment( Element.ALIGN_LEFT );
+
+        mainTable.addCell( cell_withInnerTable );
+    }
+
+    private void insertTable_HiddenValue( PdfPTable mainTable, Rectangle rectangle, PdfWriter writer, String fieldName,
+        String value )
+        throws IOException, DocumentException
+    {
+
+        // Add Organization ID/Period textfield
+        // Create A table to add for each group AT HERE
+        PdfPTable table = new PdfPTable( 1 ); // Code 1
+
+        addCell_WithTextField( table, rectangle, writer, fieldName, value );
+
+        // Add to the main table
+        PdfPCell cell_withInnerTable = new PdfPCell( table );
+        // cell_withInnerTable.setPadding(0);
+        cell_withInnerTable.setBorder( Rectangle.NO_BORDER );
+        mainTable.addCell( cell_withInnerTable );
+    }
+
+    private void insertTable_TextRow( PdfWriter writer, PdfPTable mainTable, Rectangle rectangle, String text )
+        throws IOException, DocumentException
+    {
+        insertTable_TextRow( writer, mainTable, rectangle, text,
+            pdfFormFontSettings.getFont( PdfFormFontSettings.FONTTYPE_BODY ) );
+    }
+
+    private void insertTable_TextRow( PdfWriter writer, PdfPTable mainTable, Rectangle rectangle, String text, Font font )
+        throws IOException, DocumentException
+    {
+
+        // Add Organization ID/Period textfield
+        // Create A table to add for each group AT HERE
+        PdfPTable table = new PdfPTable( 1 );
+        table.setHorizontalAlignment( Element.ALIGN_LEFT );
+
+        addCell_Text( table, text, Element.ALIGN_LEFT, font );
+
+        // Add to the main table
+        PdfPCell cell_withInnerTable = new PdfPCell( table );
+        cell_withInnerTable.setBorder( Rectangle.NO_BORDER );
+        mainTable.addCell( cell_withInnerTable );
+    }
+
+    // Insert 'Save As' button to document.
+    private void insertSaveAsButton( Document document, PdfWriter writer, String name )
+        throws DocumentException
+    {
+        // Button Table
+        PdfPTable tableButton = new PdfPTable( 1 );
+
+        tableButton.setWidthPercentage( 20.0f );
+        float buttonHeight = PdfDataEntryFormUtil.UNITSIZE_DEFAULT + 5;
+
+        tableButton.setHorizontalAlignment( PdfPTable.ALIGN_CENTER );
+
+        String jsAction = "app.execMenuItem('SaveAs');";
+
+        addCell_WithPushButtonField( tableButton, name, buttonHeight, jsAction, writer );
+
+        document.add( tableButton );
+    }
+
+    // ------------ Insert Section/Item Related Methods [END] ------------
+    // -----------------------------------------------------------------------------
+
+    // -----------------------------------------------------------------------------
+    // ------------ Add Control To Cell Related Methods [START] ------------
+
+    private void addCell_Text( PdfPTable table, String text, int horizontalAlignment )
+    {
+        addCell_Text( table, text, horizontalAlignment, pdfFormFontSettings.getFont( PdfFormFontSettings.FONTTYPE_BODY ) );
+    }
+
+    private void addCell_Text( PdfPTable table, String text, int horizontalAlignment, Font font )
+    {
+        PdfPCell cell = PdfDataEntryFormUtil.getPdfPCell( PdfDataEntryFormUtil.CELL_MIN_HEIGHT_DEFAULT,
+            PdfDataEntryFormUtil.CELL_COLUMN_TYPE_LABEL );
+
+        cell.setHorizontalAlignment( horizontalAlignment );
+
+        cell.setPhrase( new Phrase( text, font ) );
+
+        table.addCell( cell );
+    }
+
+    private void addCell_WithTextField( PdfPTable table, Rectangle rect, PdfWriter writer, String strfldName )
+        throws IOException, DocumentException
+    {
+        addCell_WithTextField( table, rect, writer, strfldName, PdfFieldCell.TYPE_DEFAULT, "" );
+    }
+
+    private void addCell_WithTextField( PdfPTable table, Rectangle rect, PdfWriter writer, String strfldName,
+        int fieldCellType )
+        throws IOException, DocumentException
+    {
+        addCell_WithTextField( table, rect, writer, strfldName, fieldCellType, "" );
+    }
+
+    private void addCell_WithTextField( PdfPTable table, Rectangle rect, PdfWriter writer, String strfldName,
+        String value )
+        throws IOException, DocumentException
+    {
+        addCell_WithTextField( table, rect, writer, strfldName, PdfFieldCell.TYPE_DEFAULT, value );
+    }
+
+    private void addCell_WithTextField( PdfPTable table, Rectangle rect, PdfWriter writer, String strfldName,
+        int fieldCellType, String value )
+        throws IOException, DocumentException
+    {
+        TextField nameField = new TextField( writer, rect, strfldName );
+        // table.getc
+
+        nameField.setBorderWidth( 1 );
+        nameField.setBorderColor( Color.BLACK );
+        nameField.setBorderStyle( PdfBorderDictionary.STYLE_SOLID );
+        nameField.setBackgroundColor( COLOR_BACKGROUDTEXTBOX );
+
+        nameField.setText( value );
+
+        nameField.setAlignment( Element.ALIGN_RIGHT );
+        nameField.setFontSize( PdfDataEntryFormUtil.UNITSIZE_DEFAULT );
+
+        PdfPCell cell = PdfDataEntryFormUtil.getPdfPCell( PdfDataEntryFormUtil.CELL_MIN_HEIGHT_DEFAULT,
+            PdfDataEntryFormUtil.CELL_COLUMN_TYPE_ENTRYFIELD );
+        cell.setCellEvent( new PdfFieldCell( nameField.getTextField(), (int) (rect.getWidth()), fieldCellType, writer ) );
+
+        table.addCell( cell );
+    }
+
+    private void addCell_WithDropDownListField( PdfPTable table, String strfldName, String[] optionList,
+        String[] valueList, Rectangle rect, PdfWriter writer )
+        throws IOException, DocumentException
+    {
+
+        // If there is option, then create name-value set in 2 dimension array
+        // and set it as dropdown option name-value list.
+        String[][] optionValueList = new String[optionList.length][2];
+
+        for ( int i = 0; i < optionList.length; i++ )
+        {
+            optionValueList[i][1] = optionList[i];
+            optionValueList[i][0] = valueList[i];
+        }
+
+        // Code 2 create DROP-DOWN LIST
+        PdfFormField dropDown = PdfFormField.createCombo( writer, true, optionValueList, 0 );
+
+        dropDown.setWidget( rect, PdfAnnotation.HIGHLIGHT_INVERT );
+        dropDown.setFieldName( strfldName );
+
+        dropDown.setMKBorderColor( CMYKColor.BLACK );
+
+        // Combine
+
+        PdfPCell cell = PdfDataEntryFormUtil.getPdfPCell( PdfDataEntryFormUtil.CELL_MIN_HEIGHT_DEFAULT,
+            PdfDataEntryFormUtil.CELL_COLUMN_TYPE_ENTRYFIELD );
+        cell.setCellEvent( new PdfFieldCell( dropDown, (int) (rect.getWidth()), writer ) );
+
+        table.addCell( cell );
+    }
+
+    private void addCell_WithCheckBox( PdfPTable table, PdfWriter writer, String strfldName )
+        throws IOException, DocumentException
+    {
+        float sizeDefault = PdfDataEntryFormUtil.UNITSIZE_DEFAULT;
+
+        PdfContentByte canvas = writer.getDirectContent();
+
+        PdfAppearance[] onOff = new PdfAppearance[2];
+        onOff[0] = canvas.createAppearance( sizeDefault + 2, sizeDefault + 2 );
+        onOff[0].rectangle( 1, 1, sizeDefault, sizeDefault );
+        onOff[0].stroke();
+        onOff[1] = canvas.createAppearance( sizeDefault + 2, sizeDefault + 2 );
+        onOff[1].setRGBColorFill( 255, 128, 128 );
+        onOff[1].rectangle( 1, 1, sizeDefault, sizeDefault );
+        onOff[1].fillStroke();
+        onOff[1].moveTo( 1, 1 );
+        onOff[1].lineTo( sizeDefault + 1, sizeDefault + 1 );
+        onOff[1].moveTo( 1, sizeDefault + 1 );
+        onOff[1].lineTo( sizeDefault + 1, 1 );
+        onOff[1].stroke();
+
+        Rectangle rect = new Rectangle( sizeDefault, sizeDefault );
+
+        RadioCheckField checkbox = new RadioCheckField( writer, rect, "Yes", "on" );
+        checkbox.setBorderWidth( 1 );
+        checkbox.setBorderColor( Color.BLACK );
+
+        PdfFormField checkboxfield = checkbox.getCheckField();
+        checkboxfield.setFieldName( strfldName );
+
+        checkboxfield.setAppearance( PdfAnnotation.APPEARANCE_NORMAL, "", onOff[0] );
+        checkboxfield.setAppearance( PdfAnnotation.APPEARANCE_NORMAL, "true", onOff[1] );
+
+        PdfPCell cell = PdfDataEntryFormUtil.getPdfPCell( PdfDataEntryFormUtil.CELL_MIN_HEIGHT_DEFAULT,
+            PdfDataEntryFormUtil.CELL_COLUMN_TYPE_ENTRYFIELD );
+
+        cell.setCellEvent( new PdfFieldCell( checkboxfield, (int) (rect.getWidth()), writer ) );
+
+        table.addCell( cell );
+    }
+
+    private void addCell_WithRadioButton( PdfPTable table, PdfWriter writer, String strfldName )
+        throws IOException, DocumentException
+    {
+
+        // Add to the main table
+        PdfPCell cell = PdfDataEntryFormUtil.getPdfPCell( PdfDataEntryFormUtil.CELL_MIN_HEIGHT_DEFAULT,
+            PdfDataEntryFormUtil.CELL_COLUMN_TYPE_ENTRYFIELD );
+
+        // RADIO BUTTON FIELD
+        PdfFormField radiogroupField = PdfFormField.createRadioButton( writer, true );
+        radiogroupField.setFieldName( strfldName );
+
+        cell.setCellEvent( new PdfFieldCell( radiogroupField, new String[]{ "Yes", "No", "null" }, new String[]{
+            "true", "false", "" }, "", 30.0f, PdfFieldCell.TYPE_RADIOBUTTON, writer ) );
+
+        table.addCell( cell );
+
+        // Last - Add Annotation
+        writer.addAnnotation( radiogroupField );
+
+    }
+
+    private void addCell_WithPushButtonField( PdfPTable table, String strfldName, float buttonHeight, String jsAction,
+        PdfWriter writer )
+    {
+        PdfPCell cell = PdfDataEntryFormUtil.getPdfPCell( buttonHeight,
+            PdfDataEntryFormUtil.CELL_COLUMN_TYPE_ENTRYFIELD );
+        cell.setCellEvent( new PdfFieldCell( null, jsAction, "BTN_SAVEPDF", "Save PDF", PdfFieldCell.TYPE_BUTTON,
+            writer ) );
+
+        table.addCell( cell );
+    }
+
+    // ------------ Add Control To Cell Related Methods [END] ------------
+    // -----------------------------------------------------------------------------
+
+    // -----------------------------------------------------------------------------
+    // ------------ Period Related Methods [START] ------------
+
+    public String[] getPeriodValues( List<Period> periods )
+    {
+        String[] periodValues = new String[periods.size()];
+
+        for ( int i = 0; i < periods.size(); i++ )
+        {
+            periodValues[i] = periods.get( i ).getExternalId();
+        }
+
+        return periodValues;
+    }
+
+    public String[] getPeriodTitles( List<Period> periods, I18nFormat format )
+    {
+        String[] periodTitles = new String[periods.size()];
+
+        for ( int i = 0; i < periods.size(); i++ )
+        {
+            periodTitles[i] = format.formatPeriod( periods.get( i ) );
+        }
+
+        return periodTitles;
+    }
+
+    private Period setPeriodDateRange()
+        throws ParseException
+    {
+
+        Period period = new Period();
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat( Period.DEFAULT_DATE_FORMAT );
+
+        Calendar currentDate = Calendar.getInstance();
+
+        int currYear = currentDate.get( Calendar.YEAR );
+        int startYear = currYear - PERIODRANGE_PREVYEARS;
+        int endYear = currYear + PERIODRANGE_FUTUREYEARS;
+
+        period.setStartDate( simpleDateFormat.parse( String.valueOf( startYear ) + "-01-01" ) );
+        period.setEndDate( simpleDateFormat.parse( String.valueOf( endYear ) + "-01-01" ) );
+
+        return period;
+    }
+
+    // ------------ Period Related Methods [END] ------------
+    // -----------------------------------------------------------------------------
+
+}

=== added file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfDataEntryFormService.java'
--- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfDataEntryFormService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfDataEntryFormService.java	2013-05-25 06:19:23 +0000
@@ -0,0 +1,40 @@
+package org.hisp.dhis.dxf2.pdfform;
+
+/*
+ * Copyright (c) 2004-2013, 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.
+ */
+
+import com.lowagie.text.Document;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.PdfWriter;
+import org.hisp.dhis.i18n.I18nFormat;
+
+public interface PdfDataEntryFormService
+{
+    void generatePDFDataEntryForm( Document document, PdfWriter writer, String inputUid, int typeId,
+        Rectangle pageSize, PdfFormFontSettings pdfFormFontSettings, I18nFormat format );
+
+}

=== added file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfDataEntryFormUtil.java'
--- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfDataEntryFormUtil.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfDataEntryFormUtil.java	2013-05-25 06:19:23 +0000
@@ -0,0 +1,277 @@
+package org.hisp.dhis.dxf2.pdfform;
+
+/*
+ * Copyright (c) 2004-2013, 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.
+ */
+
+import com.lowagie.text.Document;
+import com.lowagie.text.Element;
+import com.lowagie.text.Font;
+import com.lowagie.text.HeaderFooter;
+import com.lowagie.text.PageSize;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.AcroFields;
+import com.lowagie.text.pdf.AcroFields.Item;
+import com.lowagie.text.pdf.PdfPCell;
+import com.lowagie.text.pdf.PdfReader;
+import org.hisp.dhis.dxf2.datavalueset.DataValueSet;
+import org.hisp.dhis.period.Period;
+import org.hisp.dhis.period.PeriodType;
+
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+
+
+public class PdfDataEntryFormUtil
+{
+
+    // public Static Values
+    public static final int DATATYPE_DATASET = 0;
+    public static final int DATATYPE_PROGRAMSTAGE = 1;
+
+    public static final float UNITSIZE_DEFAULT = 10;
+
+    // Label Names
+    public static final String LABELCODE_TEXTFIELD = "TXFD_";
+
+    public static final String LABELCODE_BUTTON = "BTNFD_";
+
+    public static final String LABELCODE_ORGID = LABELCODE_TEXTFIELD + "OrgID";
+
+    public static final String LABELCODE_PERIODID = LABELCODE_TEXTFIELD + "PeriodID";
+
+    public static final String LABELCODE_BUTTON_SAVEAS = LABELCODE_BUTTON + "SaveAs";
+
+    public static final String LABELCODE_DATADATETEXTFIELD = "TXFDDT_";
+
+    public static final String LABELCODE_DATAENTRYTEXTFIELD = "TXFDDV_";
+
+    public static final String LABELCODE_PROGRAMSTAGEIDTEXTBOX = "TXPSTGID_";
+
+
+    // Cell Related
+
+    public final static float CELL_MIN_HEIGHT_DEFAULT = 13;
+
+    public final static float CONTENT_HEIGHT_DEFAULT = 11;
+
+    public final static int CELL_COLUMN_TYPE_LABEL = 0;
+
+    public final static int CELL_COLUMN_TYPE_ENTRYFIELD = 1;
+
+
+    // private static values
+    private static final String DATAVALUE_IMPORT_STOREBY = "admin";
+
+    private static final String DATAVALUE_IMPORT_COMMENT = "Imported by PDF Data Entry Form";
+
+    private static final String DATAVALUE_IMPORT_TIMESTAMP_DATEFORMAT = "yyyy-MM-dd";
+
+    private static final String FOOTERTEXT_DEFAULT = "PDF Template generated from DHIS %s on %s";
+
+    private static final String DATEFORMAT_FOOTER_DEFAULT = "MMMM dd, yyyy";
+
+
+    // -------------------------------------------------------------------------
+    // METHODS
+    // -------------------------------------------------------------------------
+
+    // -------------------------------------------------------------------------
+    // --- Document Setting Related [START]
+
+    public static void setFooterOnDocument( Document document, String footerText, Font font )
+    {
+        boolean isNumbered = true;
+
+        HeaderFooter footer = new HeaderFooter( new Phrase( footerText, font ), isNumbered );
+        footer.setBorder( Rectangle.NO_BORDER );
+        footer.setAlignment( Element.ALIGN_RIGHT );
+        document.setFooter( footer );
+
+    }
+
+    // Set DefaultFooter
+    public static void setDefaultFooterOnDocument( Document document, String serverName, Font font )
+    {
+        // Set Footer
+        String strFooterText = String.format( FOOTERTEXT_DEFAULT, serverName, (new SimpleDateFormat(
+            DATEFORMAT_FOOTER_DEFAULT )).format( new Date() ) );
+
+        setFooterOnDocument( document, strFooterText, font );
+
+    }
+
+    public static Rectangle getDefaultPageSize( int typeId )
+    {
+
+        if ( typeId == PdfDataEntryFormUtil.DATATYPE_PROGRAMSTAGE )
+        {
+            return new Rectangle( PageSize.A4.getLeft(),
+                PageSize.A4.getBottom(), PageSize.A4.getTop(), PageSize.A4.getRight() );
+        }
+        else
+        {
+            return PageSize.A4;
+        }
+
+    }
+
+    // --- Document Setting Related [END]
+    // -------------------------------------------------------------------------
+
+    // -------------------------------------------------------------------------
+    // --- PdfPCell Related [START]
+
+    public static PdfPCell getPdfPCell( float minHeight )
+    {
+        return getPdfPCell( minHeight, CELL_COLUMN_TYPE_LABEL );
+    }
+
+    public static PdfPCell getPdfPCell( float minHeight, int cellContentType )
+    {
+        PdfPCell cell = new PdfPCell();
+        cell.setMinimumHeight( minHeight );
+        cell.setBorder( Rectangle.NO_BORDER );
+
+        if ( cellContentType == CELL_COLUMN_TYPE_LABEL )
+        {
+            cell.setHorizontalAlignment( Element.ALIGN_RIGHT );
+            cell.setVerticalAlignment( Element.ALIGN_TOP );
+        }
+        else if ( cellContentType == CELL_COLUMN_TYPE_ENTRYFIELD )
+        {
+            cell.setHorizontalAlignment( Element.ALIGN_CENTER );
+            cell.setVerticalAlignment( Element.ALIGN_MIDDLE );
+        }
+
+        return cell;
+    }
+
+
+    // --- PdfPCell Related [END]
+    // -------------------------------------------------------------------------
+
+
+    // Retreive DataValue Informations from PDF inputStream.
+    public static DataValueSet getDataValueSet( InputStream in )
+        throws RuntimeException
+    {
+        PdfReader reader = null;
+
+        DataValueSet dataValueSet = new DataValueSet();
+
+        List<org.hisp.dhis.dxf2.datavalue.DataValue> dataValueList = new ArrayList<org.hisp.dhis.dxf2.datavalue.DataValue>();
+
+        try
+        {
+
+            reader = new PdfReader( in ); // new PdfReader(in, null);
+
+            AcroFields form = reader.getAcroFields();
+
+            if ( form != null )
+            {
+
+                // TODO: MOVE THESE STATIC NAME VALUES TO inside of service
+                // class or PDFForm Class <-- should be in PDFForm Class.
+                String strOrgUID = form.getField( PdfDataEntryFormUtil.LABELCODE_ORGID );
+                String strPeriodID = form.getField( PdfDataEntryFormUtil.LABELCODE_PERIODID );
+
+                Period period = PeriodType.createPeriodExternalId( strPeriodID );
+
+                // Loop Through the Fields and get data.
+                HashMap<String, AcroFields.Item> fields = form.getFields();
+                Set<Entry<String, Item>> entrySet = fields.entrySet();
+
+                Set<String> fldNames = form.getFields().keySet();
+
+                for ( String fldName : fldNames )
+                {
+
+                    if ( fldName.startsWith( PdfDataEntryFormUtil.LABELCODE_DATAENTRYTEXTFIELD ) )
+                    {
+
+                        String[] strArrFldName = fldName.split( "_" );
+
+                        // Create DataValues to be put in a DataValueSet
+                        org.hisp.dhis.dxf2.datavalue.DataValue dataValue = new org.hisp.dhis.dxf2.datavalue.DataValue();
+
+                        dataValue.setDataElement( strArrFldName[1] );
+                        dataValue.setCategoryOptionCombo( strArrFldName[2] );
+                        dataValue.setOrgUnit( strOrgUID );
+                        dataValue.setPeriod( period.getIsoDate() );
+
+                        dataValue.setValue( form.getField( fldName ) );
+
+                        dataValue.setStoredBy( DATAVALUE_IMPORT_STOREBY );
+                        dataValue.setComment( DATAVALUE_IMPORT_COMMENT );
+                        dataValue.setFollowup( false );
+                        dataValue.setTimestamp( new SimpleDateFormat( DATAVALUE_IMPORT_TIMESTAMP_DATEFORMAT )
+                            .format( new Date() ) );
+
+                        dataValueList.add( dataValue );
+
+                    }
+                }
+
+                dataValueSet.setDataValues( dataValueList );
+
+            }
+            else
+            {
+                throw new RuntimeException( "Could not generate PDF AcroFields form from the file." );
+            }
+
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( e.getMessage() );
+        }
+        finally
+        {
+            reader.close();
+        }
+
+        return dataValueSet;
+    }
+
+
+    // -----------------------------------------------------------------------------
+    // --- For Import - ProgramStage [START]
+
+
+    // --- For Import - ProgramStage [END]
+    // -----------------------------------------------------------------------------
+
+
+}

=== added file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfFieldCell.java'
--- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfFieldCell.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfFieldCell.java	2013-05-25 06:19:23 +0000
@@ -0,0 +1,258 @@
+package org.hisp.dhis.dxf2.pdfform;
+
+/*
+ * Copyright (c) 2004-2013, 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.
+ */
+
+import com.lowagie.text.Element;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.ColumnText;
+import com.lowagie.text.pdf.GrayColor;
+import com.lowagie.text.pdf.PdfAction;
+import com.lowagie.text.pdf.PdfAnnotation;
+import com.lowagie.text.pdf.PdfBorderDictionary;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfFormField;
+import com.lowagie.text.pdf.PdfName;
+import com.lowagie.text.pdf.PdfPCell;
+import com.lowagie.text.pdf.PdfPCellEvent;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.PdfWriter;
+import com.lowagie.text.pdf.PushbuttonField;
+import com.lowagie.text.pdf.RadioCheckField;
+
+public class PdfFieldCell
+    implements PdfPCellEvent
+{
+
+    public final static int TYPE_DEFAULT = 0;
+
+    public final static int TYPE_BUTTON = 1;
+
+    public final static int TYPE_TEXT_ORGUNIT = 2;
+
+    public final static int TYPE_TEXT_NUMBER = 3;
+
+    public final static int TYPE_CHECKBOX = 4;
+
+    public final static int TYPE_RADIOBUTTON = 5;
+
+    private final static float RADIOBUTTON_WIDTH = 10.0f;
+
+    private final static float RADIOBUTTON_TEXTOFFSET = 3.0f;
+
+    private PdfFormField parent;
+
+    private PdfFormField formField;
+
+    private PdfWriter writer;
+
+    private float width;
+
+    private int type;
+
+    private String jsAction;
+
+    private String[] values;
+
+    private String[] texts;
+
+    private String checkValue;
+
+    private String text;
+
+    private String name;
+
+    public PdfFieldCell( PdfFormField formField, int width, PdfWriter writer )
+    {
+        this.formField = formField;
+        this.width = width;
+        this.writer = writer;
+        this.type = TYPE_DEFAULT;
+    }
+
+    public PdfFieldCell( PdfFormField formField, int width, int type, PdfWriter writer )
+    {
+        this.formField = formField;
+        this.width = width;
+        this.writer = writer;
+        this.type = type;
+    }
+
+    public PdfFieldCell( PdfFormField formField, String jsAction, String name, String text, int type, PdfWriter writer )
+    {
+        this.formField = formField;
+        this.writer = writer;
+        this.type = type;
+        this.name = name;
+        this.text = text;
+        this.jsAction = jsAction;
+    }
+
+    public PdfFieldCell( PdfFormField parent, String[] texts, String[] values, String checkValue, float width,
+        int type, PdfWriter writer )
+    {
+        this.writer = writer;
+        this.type = type;
+        this.parent = parent;
+        this.texts = texts;
+        this.values = values;
+        this.checkValue = checkValue;
+        this.width = width;
+    }
+
+    public void cellLayout( PdfPCell cell, Rectangle rect, PdfContentByte[] canvas )
+    {
+        try
+        {
+
+            PdfContentByte cb = null;
+
+            if ( type == TYPE_RADIOBUTTON )
+            {
+                cb = canvas[PdfPTable.TEXTCANVAS];
+            }
+            else
+            {
+                cb = canvas[PdfPTable.LINECANVAS];
+            }
+
+            switch ( type )
+            {
+
+                case TYPE_RADIOBUTTON:
+
+                    if ( parent != null )
+                    {
+
+                        float leftLoc = rect.getLeft();
+                        float rightLoc = rect.getLeft() + RADIOBUTTON_WIDTH;
+
+                        try
+                        {
+
+                            String text;
+                            String value;
+
+                            for ( int i = 0; i < texts.length; i++ )
+                            {
+
+                                text = texts[i];
+                                value = values[i];
+
+                                Rectangle radioRec = new Rectangle( leftLoc, rect.getBottom(), rightLoc, rect.getTop() );
+
+                                RadioCheckField rf = new RadioCheckField( writer, radioRec, "RDBtn_" + text, value );
+
+                                if ( value == checkValue )
+                                    rf.setChecked( true );
+
+                                rf.setBorderColor( GrayColor.GRAYBLACK );
+                                rf.setBackgroundColor( GrayColor.GRAYWHITE );
+                                rf.setCheckType( RadioCheckField.TYPE_CIRCLE );
+
+                                parent.addKid( rf.getRadioField() );
+
+                                leftLoc = rightLoc;
+                                rightLoc += width;
+
+                                ColumnText.showTextAligned( cb, Element.ALIGN_LEFT, new Phrase( text ), leftLoc
+                                    + RADIOBUTTON_TEXTOFFSET, (radioRec.getBottom() + radioRec.getTop()) / 2, 0 );
+
+                                leftLoc = rightLoc;
+                                rightLoc += RADIOBUTTON_WIDTH;
+
+                            }
+
+                        }
+                        catch ( Exception ex )
+                        {
+                            throw new RuntimeException( ex.getMessage() );
+                        }
+
+                        writer.addAnnotation( parent );
+
+                    }
+
+                    break;
+
+                case TYPE_BUTTON:
+                    // Add the push button
+                    PushbuttonField button = new PushbuttonField( writer, rect, name );
+                    button.setBackgroundColor( new GrayColor( 0.75f ) );
+                    button.setBorderColor( GrayColor.GRAYBLACK );
+                    button.setBorderWidth( 1 );
+                    button.setBorderStyle( PdfBorderDictionary.STYLE_BEVELED );
+                    button.setTextColor( GrayColor.GRAYBLACK );
+                    button.setFontSize( PdfDataEntryFormUtil.UNITSIZE_DEFAULT );
+                    button.setText( text );
+                    button.setLayout( PushbuttonField.LAYOUT_ICON_LEFT_LABEL_RIGHT );
+                    button.setScaleIcon( PushbuttonField.SCALE_ICON_ALWAYS );
+                    button.setProportionalIcon( true );
+                    button.setIconHorizontalAdjustment( 0 );
+
+                    formField = button.getField();
+                    formField.setAction( PdfAction.javaScript( jsAction, writer ) );
+
+                    break;
+
+                case TYPE_CHECKBOX:
+
+                    // Start from the middle of the cell width.
+                    float startingPoint = rect.getLeft() + ((rect.getWidth() + width) / 2.0f);
+
+                    formField.setWidget(
+                        new Rectangle( startingPoint, rect.getBottom(), startingPoint + width, rect.getTop() ),
+                        PdfAnnotation.HIGHLIGHT_NONE );
+
+                    break;
+
+                case TYPE_TEXT_ORGUNIT:
+                    formField.setAdditionalActions( PdfName.BL, PdfAction.javaScript(
+                        "if(event.value == '') app.alert('Warning! Please Enter The Org ID.');", writer ) );
+
+                case TYPE_TEXT_NUMBER:
+
+                default:
+
+                    formField.setWidget(
+                        new Rectangle( rect.getLeft(), rect.getBottom(), rect.getLeft() + width, rect.getTop() ),
+                        PdfAnnotation.HIGHLIGHT_NONE );
+
+                    break;
+
+            }
+
+            writer.addAnnotation( formField );
+
+        }
+        catch ( Exception ex )
+        {
+            throw new RuntimeException( ex.getMessage() );
+        }
+    }
+}
\ No newline at end of file

=== added file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfFormFontSettings.java'
--- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfFormFontSettings.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/pdfform/PdfFormFontSettings.java	2013-05-25 06:19:23 +0000
@@ -0,0 +1,164 @@
+package org.hisp.dhis.dxf2.pdfform;
+
+/*
+ * Copyright (c) 2004-2013, 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.
+ */
+
+import com.lowagie.text.Font;
+import java.awt.*;
+
+public class PdfFormFontSettings
+{
+    // Font Types
+    public final static int FONTTYPE_BODY = 0;
+
+    public final static int FONTTYPE_TITLE = 1;
+
+    public final static int FONTTYPE_DESCRIPTION = 2;
+
+    public final static int FONTTYPE_SECTIONHEADER = 3;
+
+    public final static int FONTTYPE_FOOTER = 4;
+
+    // Font Default Sizes
+    private final static float FONTSIZE_BODY = 10;
+
+    private final static float FONTSIZE_TITLE = 16;
+
+    private final static float FONTSIZE_DESCRIPTION = 11;
+
+    private final static float FONTSIZE_SECTIONHEADER = 14;
+
+    private final static float FONTSIZE_FOOTER = 8;
+
+    // Font Family Default
+    private final static String FONTFAMILY = "HELVETICA";
+
+    // private variables
+    private Font fontBody;
+
+    private Font fontTitle;
+
+    private Font fontDescription;
+
+    private Font fontSectionHeader;
+
+    private Font fontFooter;
+
+    public PdfFormFontSettings()
+    {
+        fontBody = createFont( FONTTYPE_BODY );
+        fontTitle = createFont( FONTTYPE_TITLE );
+        fontDescription = createFont( FONTTYPE_DESCRIPTION );
+        fontSectionHeader = createFont( FONTTYPE_SECTIONHEADER );
+        fontFooter = createFont( FONTTYPE_FOOTER );
+    }
+
+    public void setFont( int fontType, Font font )
+    {
+
+        switch ( fontType )
+        {
+            case FONTTYPE_BODY:
+                fontBody = font;
+                break;
+            case FONTTYPE_TITLE:
+                fontTitle = font;
+                break;
+            case FONTTYPE_DESCRIPTION:
+                fontDescription = font;
+                break;
+            case FONTTYPE_SECTIONHEADER:
+                fontSectionHeader = font;
+                break;
+            case FONTTYPE_FOOTER:
+                fontFooter = font;
+                break;
+        }
+
+    }
+
+    public Font getFont( int fontType )
+    {
+        Font font = null;
+
+        switch ( fontType )
+        {
+            case FONTTYPE_BODY:
+                font = fontBody;
+                break;
+            case FONTTYPE_TITLE:
+                font = fontTitle;
+                break;
+            case FONTTYPE_DESCRIPTION:
+                font = fontDescription;
+                break;
+            case FONTTYPE_SECTIONHEADER:
+                font = fontSectionHeader;
+                break;
+            case FONTTYPE_FOOTER:
+                font = fontFooter;
+                break;
+        }
+
+        return font;
+    }
+
+    private Font createFont( int fontType )
+    {
+        Font font = new Font();
+        font.setFamily( FONTFAMILY );
+
+        switch ( fontType )
+        {
+            case FONTTYPE_BODY:
+                font.setSize( FONTSIZE_BODY );
+                break;
+            case FONTTYPE_TITLE:
+                font.setSize( FONTSIZE_TITLE );
+                font.setStyle( java.awt.Font.BOLD );
+                font.setColor( new Color( 0, 0, 128 ) ); // Navy Color
+                break;
+            case FONTTYPE_DESCRIPTION:
+                font.setSize( FONTSIZE_DESCRIPTION );
+                font.setColor( Color.DARK_GRAY );
+                break;
+            case FONTTYPE_SECTIONHEADER:
+                font.setSize( FONTSIZE_SECTIONHEADER );
+                font.setStyle( java.awt.Font.BOLD );
+                font.setColor( new Color( 70, 130, 180 ) ); // Steel Blue Color
+                break;
+            case FONTTYPE_FOOTER:
+                font.setSize( FONTSIZE_FOOTER );
+                break;
+            default:
+                font.setSize( FONTSIZE_BODY );
+                break;
+        }
+
+        return font;
+    }
+}

=== modified file 'dhis-2/dhis-dxf2/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-dxf2/src/main/resources/META-INF/dhis/beans.xml	2013-05-17 10:26:46 +0000
+++ dhis-2/dhis-dxf2/src/main/resources/META-INF/dhis/beans.xml	2013-05-23 04:30:18 +0000
@@ -195,5 +195,8 @@
     class="org.hisp.dhis.dxf2.metadata.importers.DefaultIdentifiableObjectImporter" scope="prototype">
     <constructor-arg name="importerClass" type="java.lang.Class" value="org.hisp.dhis.datadictionary.DataDictionary" />
   </bean>
+  
+  <bean id="pdfDataEntryFormService" class="org.hisp.dhis.dxf2.pdfform.DefaultPdfDataEntryFormService" scope="prototype">
+  </bean>
 
 </beans>

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/PDFFormController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/PDFFormController.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/PDFFormController.java	2013-05-25 06:19:23 +0000
@@ -0,0 +1,246 @@
+package org.hisp.dhis.api.controller;
+
+/*
+ * Copyright (c) 2004-2013, 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.
+ */
+
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.pdf.PdfWriter;
+import org.hisp.dhis.api.utils.ContextUtils;
+import org.hisp.dhis.api.utils.ContextUtils.CacheStrategy;
+import org.hisp.dhis.api.utils.PdfDataEntryFormImportUtil;
+import org.hisp.dhis.common.IdentifiableObject.IdentifiableProperty;
+import org.hisp.dhis.dxf2.datavalueset.DataValueSetService;
+import org.hisp.dhis.dxf2.metadata.ImportOptions;
+import org.hisp.dhis.dxf2.pdfform.PdfDataEntryFormService;
+import org.hisp.dhis.dxf2.pdfform.PdfDataEntryFormUtil;
+import org.hisp.dhis.dxf2.pdfform.PdfFormFontSettings;
+import org.hisp.dhis.i18n.I18nManager;
+import org.hisp.dhis.i18n.I18nManagerException;
+import org.hisp.dhis.importexport.ImportStrategy;
+import org.hisp.dhis.scheduling.TaskCategory;
+import org.hisp.dhis.scheduling.TaskId;
+import org.hisp.dhis.system.notification.Notifier;
+import org.hisp.dhis.system.util.StreamUtils;
+import org.hisp.dhis.user.CurrentUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.ParseException;
+
+/**
+ * @author James Chang <jamesbchang@xxxxxxxxx>
+ */
+
+@Controller
+@RequestMapping(value = "/pdfForm")
+public class PDFFormController
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private CurrentUserService currentUserService;
+
+    @Autowired
+    private Notifier notifier;
+
+    @Autowired
+    private DataValueSetService dataValueSetService;
+
+    @Autowired
+    private I18nManager i18nManager;
+
+    @Autowired
+    private PdfDataEntryFormService pdfDataEntryFormService;
+
+    @Autowired
+    private ContextUtils contextUtils;
+
+    // -------------------------------------------------------------------------
+    // GET / POST
+    // -------------------------------------------------------------------------
+
+    // --------------------- Data Set Related ---------------------
+
+    @RequestMapping(value = "/dataSet/{dataSetUid}", method = RequestMethod.GET)
+    public void getFormPDF_DataSet( HttpServletRequest request, HttpServletResponse response,
+        @PathVariable String dataSetUid )
+        throws Exception
+    {
+        // STEP 1. - Create Document and PdfWriter - with OutputStream and
+        // document tie.
+        Document document = new Document(); // TODO: can specify the size of
+        // document - like letter or A4
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PdfWriter writer = PdfWriter.getInstance( document, baos );
+
+        // STEP 2. Generate PDF Document Contents
+        PdfFormFontSettings pdfFormFontSettings = new PdfFormFontSettings();
+
+        PdfDataEntryFormUtil.setDefaultFooterOnDocument( document, request.getServerName(),
+            pdfFormFontSettings.getFont( PdfFormFontSettings.FONTTYPE_FOOTER ) );
+
+        pdfDataEntryFormService.generatePDFDataEntryForm( document, writer, dataSetUid,
+            PdfDataEntryFormUtil.DATATYPE_DATASET,
+            PdfDataEntryFormUtil.getDefaultPageSize( PdfDataEntryFormUtil.DATATYPE_DATASET ),
+            new PdfFormFontSettings(), i18nManager.getI18nFormat() );
+
+        // STEP 3. - Response Header/Content Type Set
+        contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_PDF, CacheStrategy.NO_CACHE );
+        response.setContentLength( baos.size() );
+
+        // STEP 4. - Output the data into Stream and close the stream.
+        // write ByteArrayOutputStream to the ServletOutputStream
+        writeToOutputStream( baos, response );
+
+    }
+
+    @RequestMapping(value = "/DataSet", method = RequestMethod.POST)
+    // , consumes = MEDIA_TYPE_PDF)
+    public void sendFormPDF_DataSet( HttpServletRequest request, HttpServletResponse response )
+        throws Exception
+    {
+
+        // Step 1. Set up Import Option
+        ImportStrategy strategy = ImportStrategy.NEW_AND_UPDATES;
+        IdentifiableProperty dataElementIdScheme = IdentifiableProperty.UID;
+        IdentifiableProperty orgUnitIdScheme = IdentifiableProperty.UID;
+        boolean dryRun = false;
+        boolean skipExistingCheck = false; // THIS IS THE DEFAULT CHOICE. DO WE
+        // USE THIS?
+
+        ImportOptions options = new ImportOptions( dataElementIdScheme, orgUnitIdScheme, dryRun, strategy,
+            skipExistingCheck );
+
+        // Step 2. Generate Task ID
+        TaskId taskId = new TaskId( TaskCategory.DATAVALUE_IMPORT, currentUserService.getCurrentUser() );
+
+        notifier.clear( taskId );
+
+        // Step 3. Input Stream Check
+        InputStream in = request.getInputStream();
+
+        in = StreamUtils.wrapAndCheckCompressionFormat( in );
+
+        // No logging?
+        // log.info( options );
+
+        // Step 4. Save (Import) the data values.
+        dataValueSetService.saveDataValueSetPdf( in, options, taskId );
+
+        // Step 5. Set the response - just simple OK response.
+        ContextUtils.okResponse( response, "" );
+
+    }
+
+    // --------------------- Program Stage Related ---------------------
+
+    @RequestMapping(value = "/programStage/{programStageUid}", method = RequestMethod.GET)
+    public void getFormPDF_ProgramStage( HttpServletRequest request, HttpServletResponse response, @PathVariable
+    String programStageUid )
+        throws IOException, DocumentException, ParseException, I18nManagerException
+    {
+
+        // STEP 1. - Create Document and PdfWriter - with OutputStream and
+        // document tie.
+        Document document = new Document();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PdfWriter writer = PdfWriter.getInstance( document, baos );
+
+        // STEP 2. Generate PDF Document Contents
+        PdfFormFontSettings pdfFormFontSettings = new PdfFormFontSettings();
+
+        PdfDataEntryFormUtil.setDefaultFooterOnDocument( document, request.getServerName(),
+            pdfFormFontSettings.getFont( PdfFormFontSettings.FONTTYPE_FOOTER ) );
+
+        pdfDataEntryFormService.generatePDFDataEntryForm( document, writer, programStageUid,
+            PdfDataEntryFormUtil.DATATYPE_PROGRAMSTAGE,
+            PdfDataEntryFormUtil.getDefaultPageSize( PdfDataEntryFormUtil.DATATYPE_PROGRAMSTAGE )
+            // , new Rectangle( PageSize.A4.getLeft(),
+            // PageSize.A4.getBottom(), PageSize.A4.getTop(),
+            // PageSize.A4.getRight() )
+            , new PdfFormFontSettings(), i18nManager.getI18nFormat() );
+
+        // STEP 3. - Response Header/Content Type Set
+        contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_PDF, CacheStrategy.NO_CACHE );
+        response.setContentLength( baos.size() );
+
+        // STEP 4. - write ByteArrayOutputStream to the ServletOutputStream
+        writeToOutputStream( baos, response );
+    }
+
+    @RequestMapping(value = "/programStage", method = RequestMethod.POST)
+    // , consumes = MEDIA_TYPE_PDF)
+    public void sendFormPDF_ProgramStage( HttpServletRequest request, HttpServletResponse response )
+        throws IOException, Exception
+    {
+
+        InputStream in = request.getInputStream();
+
+        // Temporarily using Util class from same project.
+        PdfDataEntryFormImportUtil pdfDataEntryFormImportUtil = new PdfDataEntryFormImportUtil();
+
+        pdfDataEntryFormImportUtil.ImportProgramStage( in, i18nManager.getI18nFormat() );
+
+        // Step 5. Set the response - just simple OK response.
+        ContextUtils.okResponse( response, "" );
+
+    }
+
+    // -----------------------------------------------------------------------------
+    // ---------------------- Helper Class Related [START]
+    // ----------------------
+
+    private void writeToOutputStream( ByteArrayOutputStream baos, HttpServletResponse response )
+        throws IOException
+    {
+        OutputStream os = null;
+
+        try
+        {
+            os = response.getOutputStream();
+            baos.writeTo( os );
+        }
+        finally
+        {
+            os.flush();
+            os.close();
+        }
+
+    }
+}
\ No newline at end of file

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/PdfDataEntryFormImportUtil.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/PdfDataEntryFormImportUtil.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/PdfDataEntryFormImportUtil.java	2013-05-25 06:19:23 +0000
@@ -0,0 +1,371 @@
+package org.hisp.dhis.api.utils;
+
+/*
+ * Copyright (c) 2004-2013, 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.
+ */
+
+import com.lowagie.text.pdf.AcroFields;
+import com.lowagie.text.pdf.PdfReader;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.dxf2.pdfform.PdfDataEntryFormUtil;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
+import org.hisp.dhis.patientdatavalue.PatientDataValue;
+import org.hisp.dhis.patientdatavalue.PatientDataValueService;
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramInstance;
+import org.hisp.dhis.program.ProgramInstanceService;
+import org.hisp.dhis.program.ProgramStage;
+import org.hisp.dhis.program.ProgramStageInstance;
+import org.hisp.dhis.program.ProgramStageInstanceService;
+import org.hisp.dhis.program.ProgramStageService;
+import org.hisp.dhis.user.CurrentUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class PdfDataEntryFormImportUtil
+{
+    private static final String DATAVALUE_IMPORT_STOREBY = "admin";
+
+    private static final String DATAVALUE_IMPORT_COMMENT = "Imported by PDF Data Entry Form";
+
+    private static final String DATAVALUE_IMPORT_TIMESTAMP_DATEFORMAT = "yyyy-MM-dd";
+
+    // -------------------------------------------------------------------------
+    // DEPENDENCIES
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private OrganisationUnitService organisationUnitService;
+
+    @Autowired
+    private DataElementService dataElementService;
+
+    @Autowired
+    private CurrentUserService currentUserService;
+
+    @Autowired
+    private ProgramInstanceService programInstanceService;
+
+    @Autowired
+    private ProgramStageService programStageService;
+
+    @Autowired
+    private ProgramStageInstanceService programStageInstanceService;
+
+    @Autowired
+    private PatientDataValueService patientDataValueService;
+
+    // -------------------------------------------------------------------------
+    // METHODS
+    // -------------------------------------------------------------------------
+
+    public void ImportProgramStage( InputStream in, I18nFormat format )
+        throws Exception
+    {
+        int programStageInstanceId;
+        ProgramStageInstance programStageInstance;
+
+        PdfReader reader = new PdfReader( in, null );
+
+        AcroFields form = reader.getAcroFields();
+
+        String strOrgID = form.getField( PdfDataEntryFormUtil.LABELCODE_ORGID );
+        int organisationUnitId = Integer.parseInt( strOrgID );
+
+        String strPeriodID = form.getField( PdfDataEntryFormUtil.LABELCODE_PERIODID );
+        Date executionDateInput = format.parseDate( strPeriodID );
+        Calendar executeDateCal = Calendar.getInstance();
+        executeDateCal.setTime( executionDateInput );
+
+        int programStageId = Integer.valueOf( form.getField( PdfDataEntryFormUtil.LABELCODE_PROGRAMSTAGEIDTEXTBOX ) );
+
+        ProgramStageInstanceDataManager programStageInstanceDataManager = new ProgramStageInstanceDataManager();
+
+        // Loop Through the Fields and get data.
+        Set<String> fldNames = form.getFields().keySet();
+
+        // Create Organized data
+        for ( String fldName : fldNames )
+        {
+            // If the value in the textfield is not empty, proceed to add
+            // it.
+            if ( !form.getField( fldName ).trim().equals( "" ) )
+            {
+                if ( fldName.startsWith( PdfDataEntryFormUtil.LABELCODE_DATADATETEXTFIELD ) )
+                {
+
+                    String[] strArrFldName = fldName.split( "_" );
+                    int rowNumber = Integer.parseInt( strArrFldName[1] );
+
+                    programStageInstanceDataManager.addDateData( Integer.parseInt( form.getField( fldName ) ),
+                        rowNumber );
+                }
+                else if ( fldName.startsWith( PdfDataEntryFormUtil.LABELCODE_DATAENTRYTEXTFIELD ) )
+                {
+
+                    String[] strArrFldName = fldName.split( "_" );
+                    int dataElementId = Integer.parseInt( strArrFldName[1] );
+                    int rowNumber = Integer.parseInt( strArrFldName[2] );
+
+                    programStageInstanceDataManager.addDataElementData( dataElementId, form.getField( fldName ),
+                        rowNumber );
+
+                }
+            }
+        }
+
+        // For each row, add new programStageInstance and add data elements
+        // to it.
+        for ( Map.Entry<Integer, ProgramStageInstanceStoage> entry : programStageInstanceDataManager
+            .getProgramStageInstanceData().entrySet() )
+        {
+            Integer key = entry.getKey(); // rowNumber
+            ProgramStageInstanceStoage programStageInstanceStoage = entry.getValue();
+
+            int date = programStageInstanceStoage.getDate();
+            executeDateCal.set( Calendar.DATE, date );
+            Date executionDate = executeDateCal.getTime();
+
+            // Step 2. Create Program Stage Instance - If does not exists
+            // already.
+            programStageInstanceId = addNewProgramStageInstance( programStageId, organisationUnitId, executionDate );
+
+            programStageInstance = programStageInstanceService.getProgramStageInstance( programStageInstanceId );
+
+            for ( Map.Entry<Integer, String> dataElementsEntry : programStageInstanceStoage.getDataElementsValue()
+                .entrySet() )
+            {
+                Integer dataElementId = dataElementsEntry.getKey();
+                String value = dataElementsEntry.getValue();
+
+                // Step 3. Insert Data
+                insertValue_ProgramStageDataElement( programStageInstance, dataElementId, value );
+            }
+
+        }
+
+        reader.close();
+    }
+
+    private int addNewProgramStageInstance( int programStageId, int organisationUnitId, Date executionDate )
+        throws Exception
+    {
+        OrganisationUnit organisationUnit = organisationUnitService.getOrganisationUnit( organisationUnitId );
+
+        if ( organisationUnit == null )
+        {
+            throw new Exception( "Invalid organisation unit identifier: " + organisationUnitId );
+        }
+
+        ProgramStage programStage = programStageService.getProgramStage( programStageId );
+        Program program = programStage.getProgram();
+
+        ProgramInstance programInstance = programInstanceService.getProgramInstances( program ).iterator().next();
+
+        ProgramStageInstance programStageInstance = new ProgramStageInstance();
+        programStageInstance.setProgramInstance( programInstance );
+        programStageInstance.setProgramStage( programStage );
+        programStageInstance.setDueDate( executionDate );
+        programStageInstance.setExecutionDate( executionDate );
+        programStageInstance.setOrganisationUnit( organisationUnit );
+
+        return programStageInstanceService.addProgramStageInstance( programStageInstance );
+    }
+
+    private void insertValue_ProgramStageDataElement( ProgramStageInstance programStageInstance, int dataElementId,
+        String value )
+        throws IOException, Exception
+    {
+
+        DataElement dataElement = dataElementService.getDataElement( dataElementId );
+
+        PatientDataValue patientDataValue = patientDataValueService.getPatientDataValue( programStageInstance,
+            dataElement );
+
+        if ( value != null && value.trim().length() == 0 )
+        {
+            value = null;
+        }
+
+        // ---------------------------------------------------------------------
+        // Save value
+        // ---------------------------------------------------------------------
+
+        if ( programStageInstance.getExecutionDate() == null )
+        {
+            programStageInstance.setExecutionDate( new Date() );
+            programStageInstanceService.updateProgramStageInstance( programStageInstance );
+        }
+
+        // providedElsewhere = (providedElsewhere == null) ? false :
+        // providedElsewhere;
+        String storedBy = currentUserService.getCurrentUsername();
+
+        if ( patientDataValue == null && value != null )
+        {
+            // LOG.debug( "Adding PatientDataValue, value added" );
+
+            patientDataValue = new PatientDataValue( programStageInstance, dataElement, new Date(), value );
+            patientDataValue.setStoredBy( storedBy );
+            // patientDataValue.setProvidedElsewhere( providedElsewhere );
+
+            patientDataValueService.savePatientDataValue( patientDataValue );
+        }
+
+        if ( patientDataValue != null && value == null )
+        {
+            patientDataValueService.deletePatientDataValue( patientDataValue );
+        }
+        else if ( patientDataValue != null && value != null )
+        {
+            // LOG.debug( "Updating PatientDataValue, value added/changed" );
+
+            patientDataValue.setValue( value );
+            patientDataValue.setTimestamp( new Date() );
+            // patientDataValue.setProvidedElsewhere( providedElsewhere );
+            patientDataValue.setStoredBy( storedBy );
+
+            patientDataValueService.updatePatientDataValue( patientDataValue );
+        }
+
+    }
+
+    // -----------------------------------------------------------------------------
+    // ------------ Helper Classes [START] ------------
+
+    class ProgramStageInstanceDataManager
+    {
+        Map<Integer, ProgramStageInstanceStoage> programStageInstanceData;
+
+        public Map<Integer, ProgramStageInstanceStoage> getProgramStageInstanceData()
+        {
+            return programStageInstanceData;
+        }
+
+        public ProgramStageInstanceDataManager()
+        {
+            programStageInstanceData = new HashMap<Integer, ProgramStageInstanceStoage>();
+        }
+
+        public void addDateData( int date, int rowNumber )
+        {
+            // Obsolete - get Date from strDateData
+
+            // If it already exists, add to existing.
+            // Otherwise, create one and add value in it.
+            if ( programStageInstanceData.containsKey( rowNumber ) )
+            {
+                // add to existing
+                programStageInstanceData.get( rowNumber ).setDate( date );
+            }
+            else
+            {
+                // Create and add
+                ProgramStageInstanceStoage programStageInstanceStoage = new ProgramStageInstanceStoage();
+                programStageInstanceStoage.setDate( date );
+
+                programStageInstanceData.put( rowNumber, programStageInstanceStoage );
+            }
+
+        }
+
+        public void addDataElementData( int dataElementId, String value, int rowNumber )
+        {
+            // If it already exists, add to existing.
+            // Otherwise, create one and add value in it.
+            if ( programStageInstanceData.containsKey( rowNumber ) )
+            {
+                // add to existing
+                programStageInstanceData.get( rowNumber ).addDataElements( dataElementId, value );
+            }
+            else
+            {
+                // Create and add
+                ProgramStageInstanceStoage programStageInstanceStoage = new ProgramStageInstanceStoage();
+                programStageInstanceStoage.addDataElements( dataElementId, value );
+
+                programStageInstanceData.put( rowNumber, programStageInstanceStoage );
+            }
+
+        }
+
+    }
+
+    class ProgramStageInstanceStoage
+    {
+        int date;
+
+        Map<Integer, String> dataElementsValue;
+
+        // -------------------------------------------------------------------------
+        // GET/SET
+        // -------------------------------------------------------------------------
+
+        public int getDate()
+        {
+            return date;
+        }
+
+        public void setDate( int date )
+        {
+            this.date = date;
+        }
+
+        public Map<Integer, String> getDataElementsValue()
+        {
+            return dataElementsValue;
+        }
+
+        // -------------------------------------------------------------------------
+        // CONSTRUCTOR
+        // -------------------------------------------------------------------------
+
+        public ProgramStageInstanceStoage()
+        {
+            dataElementsValue = new HashMap<Integer, String>();
+        }
+
+        // -------------------------------------------------------------------------
+        // METHODS
+        // -------------------------------------------------------------------------
+
+        public void addDataElements( Integer dataElementId, String value )
+        {
+            dataElementsValue.put( dataElementId, value );
+        }
+    }
+
+}

=== modified file 'dhis-2/dhis-web/dhis-web-importexport/pom.xml'
--- dhis-2/dhis-web/dhis-web-importexport/pom.xml	2013-03-22 13:47:40 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/pom.xml	2013-05-23 04:30:18 +0000
@@ -47,6 +47,10 @@
     </dependency>
     <dependency>
       <groupId>org.hisp.dhis</groupId>
+      <artifactId>dhis-dxf2</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.hisp.dhis</groupId>
       <artifactId>dhis-web-commons</artifactId>
     </dependency>
     <dependency>

=== modified file 'dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/util/ImportDataValueTask.java'
--- dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/util/ImportDataValueTask.java	2012-04-15 20:21:18 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/util/ImportDataValueTask.java	2013-05-25 06:19:23 +0000
@@ -27,13 +27,13 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.io.InputStream;
-import java.io.Reader;
-
 import org.hisp.dhis.dxf2.datavalueset.DataValueSetService;
 import org.hisp.dhis.dxf2.metadata.ImportOptions;
 import org.hisp.dhis.scheduling.TaskId;
 
+import java.io.InputStream;
+import java.io.Reader;
+
 /**
  * @author Lars Helge Overland
  */
@@ -41,14 +41,16 @@
     implements Runnable
 {
     public static final String FORMAT_CSV = "csv";
-    
+
+    public static final String FORMAT_PDF = "pdf";
+
     private DataValueSetService dataValueSetService;
     private InputStream in;
     private Reader reader;
     private ImportOptions options;
     private TaskId taskId;
     private String format;
-    
+
     public ImportDataValueTask( DataValueSetService dataValueSetService, InputStream in, Reader reader, ImportOptions options, TaskId taskId, String format )
     {
         this.dataValueSetService = dataValueSetService;
@@ -58,7 +60,7 @@
         this.taskId = taskId;
         this.format = format;
     }
-    
+
     @Override
     public void run()
     {
@@ -66,6 +68,10 @@
         {
             dataValueSetService.saveDataValueSetCsv( reader, options, taskId );
         }
+        else if ( FORMAT_PDF.equals( format ) )
+        {
+            dataValueSetService.saveDataValueSetPdf( in, options, taskId );
+        }
         else
         {
             dataValueSetService.saveDataValueSet( in, options, taskId );

=== modified file 'dhis-2/dhis-web/dhis-web-importexport/src/main/resources/org/hisp/dhis/importexport/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-importexport/src/main/resources/org/hisp/dhis/importexport/i18n_module.properties	2013-04-19 07:37:53 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/resources/org/hisp/dhis/importexport/i18n_module.properties	2013-05-23 04:30:18 +0000
@@ -263,6 +263,7 @@
 intro_xls_metadata_export=Excel Spreadsheet (XLS) is a commonly used spreadsheet file format from Microsoft.
 intro_xml_data_import=Import data values on the DXF 2 XML format which is used for data exchange by DHIS 2 and other software.
 intro_csv_data_import=Import data values on the CSV format which is used for data exchange by DHIS 2 and other third-party software.
+intro_pdf_data_import=Import data values on the PDF Data Entry Form.
 intro_dhis14_import=Import data from DHIS 1.4 installations. DHIS 1.4 is the predecessor of DHIS 2.
 intro_data_export=Export data values. This is the regular export function which exports data to the DHIS 2 exchange format called DXF 2.
 intro_metadata_export=Export meta data like data elements and organisation units to the standard DHIS 2 exchange format.
@@ -292,6 +293,7 @@
 xml=XML
 xml_data_import=XML Data Import
 csv_data_import=CSV Data Import
+pdf_data_import=PDF Data Import
 no_data_values_found=No data values found
 create_new_route=Create new route
 integration=Integration

=== modified file 'dhis-2/dhis-web/dhis-web-importexport/src/main/webapp/dhis-web-importexport/index.vm'
--- dhis-2/dhis-web/dhis-web-importexport/src/main/webapp/dhis-web-importexport/index.vm	2013-05-23 09:36:40 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/webapp/dhis-web-importexport/index.vm	2013-05-25 05:54:08 +0000
@@ -11,6 +11,7 @@
     #introListImgItem( "dxf2MetaDataImport.action" "metadata_import" "import" )
     #introListImgItem( "displayImportDataValueForm.action?importFormat=xml" "xml_data_import" "import" )
     #introListImgItem( "displayImportDataValueForm.action?importFormat=csv" "csv_data_import" "import" )
+    #introListImgItem( "displayImportDataValueForm.action?importFormat=pdf" "pdf_data_import" "import" )
     #introListImgItem( "displayExternalImportMenu.action" "dhis14_import" "import" )
     	
     #introListImgItem( "dxf2MetaDataExport.action" "metadata_export" "export" )

=== modified file 'dhis-2/dhis-web/dhis-web-importexport/src/main/webapp/dhis-web-importexport/mainMenu.vm'
--- dhis-2/dhis-web/dhis-web-importexport/src/main/webapp/dhis-web-importexport/mainMenu.vm	2013-04-20 12:35:07 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/webapp/dhis-web-importexport/mainMenu.vm	2013-05-23 04:30:18 +0000
@@ -5,6 +5,7 @@
   <li><a href="dxf2MetaDataImport.action">$i18n.getString( "metadata_import" )&nbsp;</a></li>
   <li><a href="displayImportDataValueForm.action?importFormat=xml">$i18n.getString( "xml_data_import" )&nbsp;</a></li>
   <li><a href="displayImportDataValueForm.action?importFormat=csv">$i18n.getString( "csv_data_import" )&nbsp;</a></li>
+  <li><a href="displayImportDataValueForm.action?importFormat=pdf">$i18n.getString( "pdf_data_import" )&nbsp;</a></li>
   <li><a href="displayExternalImportMenu.action">$i18n.getString( "dhis14_import" )&nbsp;</a></li>
   <li><a href="setImportFormat.action?importFormat=DXF">$i18n.getString( "gml_import" )&nbsp;</a></li>
 </ul>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties	2013-01-23 09:08:59 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties	2013-05-23 04:30:18 +0000
@@ -108,4 +108,5 @@
 object_not_deleted_associated_by_objects=Object not deleted because it is associated by objects of type
 auto_save_data_entry_forms=Auto-save data entry forms
 notify_completing_user=Send notification to completing user
-insert_images=Insert images
\ No newline at end of file
+insert_images=Insert images
+pdf_data_entry_form=Get PDF for Data Entry
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/dataSetList.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/dataSetList.vm	2013-03-13 11:47:27 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/dataSetList.vm	2013-05-23 04:30:18 +0000
@@ -31,7 +31,7 @@
 		</table>
       <table class="listTable" id="listTable">
           <col/>          
-          <col width="230"/>
+          <col width="260"/>
           <thead>
           <tr>
             <th>$i18n.getString( "name" )</th>
@@ -73,6 +73,12 @@
                   <img src="../images/edit_layout-denied.png">
                   #end
 
+                  #if( $security.canUpdate( $dataSet ) )
+                  <a href="../api/pdfForm/DataSet/$dataSet.uid" title="$i18n.getString( 'pdf_data_entry_form' )" target="_blank"><img src="../images/pdf.png" alt="$i18n.getString( 'pdf_data_entry_form' )" width="24" height="24"/></a>
+                  #else
+                  <img src="../images/pdf-denied.png">
+                  #end
+
                   #if( $security.canWrite( $dataSet ) )
                   <a href="javascript:window.location.href='displayCompulsoryDataElementsForm.action?id=${dataSet.id}'" title="$i18n.getString( 'edit_compulsory_data_elements' )"><img src="../images/edit_compulsory_data_elements.png" alt="$i18n.getString( 'edit_compulsory_data_elements' )"/></a>
                   #else

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties	2013-05-24 09:10:42 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/org/hisp/dhis/patient/i18n_module.properties	2013-05-25 05:54:08 +0000
@@ -364,6 +364,7 @@
 capture_coordinates = Capture coordinates
 task_stragely = Task strategy
 last_month = Last month
+pdf_data_entry_form=Get PDF for Data Entry
 last_3_month = Last 3 months
 last_6_month = Last 6 months
 last_12_month = Last 12 months

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programStage.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programStage.vm	2013-03-01 14:09:05 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/webapp/dhis-web-maintenance-patient/programStage.vm	2013-05-23 04:30:18 +0000
@@ -19,7 +19,7 @@
 			<table class="listTable" id="listTable">
 				<col>
 				<col>     
-				<col width="180">	 
+				<col width="210">	 
 				<thead>
 					<tr>            
 						<th>$i18n.getString( "name" )</th>
@@ -41,8 +41,10 @@
 							  #if( $program.type=='1' )
 								<a href="javascript:removeItem( '$association.id', '$encoder.jsEncode( $association.name )', i18n_confirm_delete , 'removeProgramStage.action' )" title="$i18n.getString( 'remove' )"><img src="../images/delete.png" alt="$i18n.getString( 'remove' )"></a>
 							  #end
+							  							  
 							  <a href="javascript:showProgramStageDetails( $association.id )" title="$i18n.getString( "show_details" )"><img src="../images/information.png" alt="$i18n.getString( 'show_details' )"></a>
 							  <a href="programStageSectionList.action?id=$association.id" title="$i18n.getString( 'section_management' )"><img src="images/sections.png" alt="$i18n.getString( 'section_management' )"></a>
+	                  		  <a href="../api/pdfForm/ProgramStage/$association.uid" title="$i18n.getString( 'pdf_data_entry_form' )" target="_blank"><img src="../images/pdf.png" alt="$i18n.getString( 'pdf_data_entry_form' )" width="24" height="24"/></a>	                  
 							  <a href="viewDataEntryForm.action?programStageId=$association.id" title="$i18n.getString( "design_data_entry_form" )"><img src="../images/edit_layout.png" alt="$i18n.getString( 'design_data_entry_form' )"></a>
 							</td>
 						</tr>