gt:                 	temp = temp.append("_"+section);
context: 
  /*
   *
   *
   */
  // javac -classpath .;..\lib\itext-1.01.jar -d . FrmPDFServlet.java
  // form/createpdf?__title=British+Columbia+Antenatal+Record+Part+1&__cfgfile=bcar1PrintCfgPg1&__cfgfile=bcar1PrintCfgPg2&__template=bcar1
  package oscar.form.pdfservlet;
  
  import java.io.ByteArrayOutputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.InputStream;
  import java.io.PrintWriter;
  import java.sql.SQLException;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Date;
  import java.util.Enumeration;
  import java.util.List;
  import java.util.Properties;
  
  import javax.servlet.ServletContext;
  import javax.servlet.ServletOutputStream;
  import javax.servlet.http.HttpServlet;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  
  import net.sf.jasperreports.engine.JRException;
  import net.sf.jasperreports.engine.JasperRunManager;
  import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
  
  import org.apache.commons.io.IOUtils;
  import org.apache.log4j.Logger;
  import org.oscarehr.common.printing.FontSettings;
  import org.oscarehr.common.printing.PdfWriterFactory;
  import org.oscarehr.util.LoggedInInfo;
  import org.oscarehr.util.MiscUtils;
  
  import oscar.OscarProperties;
  import oscar.form.FrmRecord;
  import oscar.form.FrmRecordFactory;
  import oscar.form.graphic.FrmGraphicFactory;
  import oscar.form.graphic.FrmPdfGraphic;
  import oscar.log.LogAction;
  import oscar.util.ConcatPDF;
  
  import com.lowagie.text.Document;
  import com.lowagie.text.DocumentException;
  import com.lowagie.text.Element;
  import com.lowagie.text.Font;
  import com.lowagie.text.PageSize;
  import com.lowagie.text.Phrase;
  import com.lowagie.text.Rectangle;
  import com.lowagie.text.pdf.BaseFont;
  import com.lowagie.text.pdf.ColumnText;
  import com.lowagie.text.pdf.PdfContentByte;
  import com.lowagie.text.pdf.PdfImportedPage;
  import com.lowagie.text.pdf.PdfReader;
  import com.lowagie.text.pdf.PdfWriter;
  
  /**
   *
   *
   */
  public class FrmPDFServlet extends HttpServlet {
  
      public static final String HSFO_RX_DATA_KEY = "hsfo.rx.data";
      Logger log = Logger.getLogger(FrmPDFServlet.class);
      /**
       *
       *
       */
      public FrmPDFServlet() {
          super();
      }
  
      public void doGet(HttpServletRequest req, HttpServletResponse res) throws javax.servlet.ServletException,
              java.io.IOException {
          doPost(req, res);
      }
  
      /**
       * @param req HTTP request object
       * @param res HTTP response object
       */
      public void doPost(HttpServletRequest req, HttpServletResponse res) throws javax.servlet.ServletException,
              java.io.IOException {
  
          ByteArrayOutputStream baosPDF = null;
          LoggedInInfo loggedInInfo=LoggedInInfo.getLoggedInInfoFromSession(req);
          
          try {        	
              File tmpFile = null;
              
              if(req.getParameter("multiple")!=null) {
              	ArrayList<Object> files = new ArrayList<Object>();
              	for(int x=0;x<Integer.parseInt(req.getParameter("multiple"));x++) {
              		baosPDF = new ByteArrayOutputStream();
                      baosPDF = generatePDFDocumentBytes(req, this.getServletContext(),baosPDF,x);
              		tmpFile = File.createTempFile("formpdf", String.valueOf((int)Math.random()*10000));
                      baosPDF.writeTo(new FileOutputStream(tmpFile));
                      files.add(tmpFile.getAbsolutePath());
              	}
              	tmpFile = File.createTempFile("formpdf", String.valueOf((int)Math.random()*10000));
              	ConcatPDF.concat(files, tmpFile.getAbsolutePath());
              } else {
              	baosPDF = new ByteArrayOutputStream();
                  baosPDF = generatePDFDocumentBytes(req, this.getServletContext(),baosPDF,0);
              	tmpFile = File.createTempFile("formpdf", String.valueOf((int)Math.random()*10000));
                  baosPDF.writeTo(new FileOutputStream(tmpFile));
              }
              StringBuilder sbFilename = new StringBuilder();
              sbFilename.append("filename_");
              //sbFilename.append(System.currentTimeMillis());
              sbFilename.append(".pdf");
  
              // set the Cache-Control header
              res.setHeader("Cache-Control", "max-age=0");
              //res.setHeader("Cache-Control","no-cache"); //HTTP 1.1
              res.setDateHeader("Expires", 0);
              res.setContentType("application/pdf");
  
              // The Content-disposition value will be inline
  
              StringBuilder sbContentDispValue = new StringBuilder();
              sbContentDispValue.append("inline; filename="); //inline - display
              // the pdf file
              // directly rather
              // than open/save
              // selection
              //sbContentDispValue.append("; filename=");
              sbContentDispValue.append(sbFilename);
  
              res.setHeader("Content-disposition", sbContentDispValue.toString());
  
              
              res.setContentLength((int)tmpFile.length());
              
              
              ServletOutputStream sout = res.getOutputStream();  
              FileInputStream fis = new FileInputStream(tmpFile);
              try {
  	            byte[] buffer = new byte[64000];  
  	            int bytesRead = 0;  
  	                                
  	            while(true)  
                  {  
                         bytesRead = fis.read(buffer);  
                         if (bytesRead == -1)  
                                break;  
                                      
                         sout.write(buffer,0,bytesRead);  
                  }
              }
              finally {
              	fis.close();
              }
              
              LogAction.addLogSynchronous(loggedInInfo,"FrmPDFServlet", "formID=" + req.getParameter("formId") + ",form_class=" + req.getParameter("form_class"));
              
          } catch (DocumentException dex) {
              res.setContentType("text/html");
              PrintWriter writer = res.getWriter();
              writer.println("Exception from: " + this.getClass().getName() + " " + dex.getClass().getName() + "<br>");
              writer.println("<pre>");
              writer.println(dex.getMessage());
              writer.println("</pre>");
          } finally {
              if (baosPDF != null) {
                  baosPDF.reset();
                  //baosPDF.close();
              }
          }
  
      }
  
      // added by vic, hsfo
      private ByteArrayOutputStream generateHsfoRxPDF(HttpServletRequest req){
          HsfoRxDataHolder rx = (HsfoRxDataHolder) req.getSession()
          .getAttribute(HSFO_RX_DATA_KEY);
  
          JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(rx.getOutlines());
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
  
          InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/oscar/form/prop/Hsfo_Rx.jasper");
         
          try {
              JasperRunManager.runReportToPdfStream(is, baos, rx.getParams(), ds);
          } catch (JRException e) {
              throw new RuntimeException(e);
          }
          finally {
          	IOUtils.closeQuietly(is);
          }
          
          return baos;
      }
  
      /**
       * the form txt file has lines in the form:
       *
       * For Checkboxes:
       * ie.  ohip : left, 76, 193, 0, BaseFont.ZAPFDINGBATS, 8, \u2713
       * requestParamName : alignment, Xcoord, Ycoord, 0, font, fontSize, textToPrint[if empty, prints the value of the request param]
       * NOTE: the Xcoord and Ycoord refer to the bottom-left corner of the element
       *
       * For single-line text:
       * ie. patientCity  : left, 242, 261, 0, BaseFont.HELVETICA, 12
       * See checkbox explanation
       *
       * For multi-line text (textarea)
       * ie.  aci : left, 20, 308, 0, BaseFont.HELVETICA, 8, _, 238, 222, 10
       * requestParamName : alignment, bottomLeftXcoord, bottomLeftYcoord, 0, font, fontSize, _, topRightXcoord, topRightYcoord, spacingBtwnLines
       *
       *NOTE: When working on these forms in linux, it helps to load the PDF file into gimp, switch to pt. coordinate system and use the mouse to find the coordinates.
       *Prepare to be bored!
       */
      protected ByteArrayOutputStream generatePDFDocumentBytes(final HttpServletRequest req, final ServletContext ctx, ByteArrayOutputStream baosPDF, int multiple)
      throws DocumentException, java.io.IOException {
  
  		LoggedInInfo loggedInInfo=LoggedInInfo.getLoggedInInfoFromSession(req);
  
      	// added by vic, hsfo
          if (HSFO_RX_DATA_KEY.equals(req.getParameter("__title")))
              return generateHsfoRxPDF(req);
  
          final String PAGESIZE = "printPageSize";
          Document document = new Document();
          //document = new Document(psize, 50, 50, 50, 50);
  
          String suffix = (multiple>0)?String.valueOf(multiple):"";
          
          PdfWriter writer = null;
  
          try {
              writer = PdfWriterFactory.newInstance(document, baosPDF, FontSettings.HELVETICA_6PT); 
  
              String title = req.getParameter("__title"+suffix) != null ? req.getParameter("__title"+suffix) : "Unknown";
              
              String template = req.getParameter("__template"+suffix) != null ? req.getParameter("__template"+suffix) + ".pdf" : "";
                          
              int numPages = 1;
              String pages = req.getParameter("__numPages"+suffix);
              if( pages != null ) {
              	numPages = Integer.parseInt(pages);
              }
                                       
              Properties[] printCfg = null;
              int cfgFileNo;
              String[] cfgFile = req.getParameterValues("__cfgfile"+suffix);
              
              cfgFileNo = cfgFile == null ? 0 : cfgFile.length;
              if( cfgFileNo > 0 ) {
              	printCfg = new Properties[cfgFileNo];
              	for (int idx2 = 0; idx2 < cfgFileNo; ++idx2) {
                      cfgFile[idx2] += ".txt";
                      if (cfgFile[idx2].indexOf("/") > 0) {
                          cfgFile[idx2] = "";
                      }
                      
                      printCfg[idx2] = getCfgProp(cfgFile[idx2]);
                  }
              }
              
                      
              
              Properties[][] graphicCfg = new Properties[numPages][];
              String[] cfgGraphicFile;
              String paramName;
              int cfgGraphicFileNo;            
              for( int idx = 0; idx < numPages; ++idx ) {
              	if( idx == 0 ) {
              		cfgGraphicFile = req.getParameterValues("__cfgGraphicFile"+suffix);            		
              	}
              	else {
              		paramName = "__cfgGraphicFile" + String.valueOf(idx) + suffix;
              		cfgGraphicFile = req.getParameterValues(paramName);
              	}
              	            	
              	cfgGraphicFileNo = cfgGraphicFile == null ? 0: cfgGraphicFile.length;
              	if( cfgGraphicFileNo == 0 ) {
              		graphicCfg[idx] = null;            		
              	}
              	else {
              		graphicCfg[idx] = new Properties[cfgGraphicFileNo];
              		for( int idx2 = 0; idx2 < cfgGraphicFileNo; ++idx2 ) {
              			cfgGraphicFile[idx2] += ".txt";
              			graphicCfg[idx][idx2] = getCfgProp(cfgGraphicFile[idx2]);
              		}
              	}            	
              }
              
              String[] cfgVal = null;
              StringBuilder tempName = null;
              String tempValue = null;
  
              //load from DB
              int demoNo = Integer.parseInt(req.getParameter("demographic_no"));
              String strFormId =req.getParameter("formId");
              int formId = 0;
              try {
              	formId =  Integer.parseInt(strFormId);
              }catch(NumberFormatException e){/*ignore*/}
  
              String formClass=req.getParameter("form_class");
              FrmRecord record = (new FrmRecordFactory()).factory(formClass);
              java.util.Properties props = new Properties();
              if(record != null) {
  	            try {
  	            	props = record.getFormRecord(loggedInInfo, demoNo, formId);
  	            }catch(SQLException e) {
  	            	MiscUtils.getLogger().error("Error",e);
  	            }
              }
              
              // get the print prop values
              //Properties props = new Properties();
              StringBuilder temp = new StringBuilder("");
              for (Enumeration<String> e = req.getParameterNames(); e.hasMoreElements();) {
                  temp = new StringBuilder(e.nextElement().toString());
                  props.setProperty(temp.toString(), req.getParameter(temp.toString()));
              }
              
              if(req.getParameter("postProcessor"+suffix)!=null) {
              	String className = "oscar.form.pdfservlet."+req.getParameter("postProcessor"+suffix);
              	try {
              		FrmPDFPostValueProcessor pp = (FrmPDFPostValueProcessor)Class.forName(className).newInstance();
              		props = pp.process(props);
              	}catch(Exception e) {
              		//ignore
              	}
              }
              
              String currentDate = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
              int totalPages = 1;
              if(req.getParameter("multiple")!=null)
              	totalPages = Integer.parseInt(req.getParameter("multiple"));
              String currentUser = loggedInInfo.getLoggedInProvider().getFormattedName();
              String pg = suffix.length()==0||suffix.equals("0")?"0":suffix;                        
              String currentPage = String.valueOf(Integer.parseInt(pg)+1);
              
              props.setProperty("total_pages",String.valueOf(totalPages));
              props.setProperty("current_page",currentPage);
              props.setProperty("current_user", currentUser);
              props.setProperty("current_date", currentDate);
              
              props.setProperty("printer_info", "Printed on " + currentDate + " by " + currentUser + ": Page " + currentPage + " of " + totalPages );
              
              //initialise measurement collections = a list of pages sections measurements
              List<List<List<String>>>xMeasurementValues = new ArrayList<List<List<String>>>();
              List<List<List<String>>>yMeasurementValues = new ArrayList<List<List<String>>>();
              for( int idx = 0; idx < numPages; ++idx ) {
              	MiscUtils.getLogger().debug("Adding page " + idx);
              	xMeasurementValues.add(new ArrayList<List<String>>());
              	yMeasurementValues.add(new ArrayList<List<String>>());
              }
              
              String elementNum;
              int page;
              int section;
              int index, index2, index3;
              Properties measurements = new Properties();
              
              for (Enumeration<String> e = req.getAttributeNames(); e.hasMoreElements(); ) {
                  temp = new StringBuilder(e.nextElement().toString());                
                  measurements.setProperty(temp.toString(), req.getAttribute(temp.toString()).toString());
                  
                  //for graphing measurements of height and weight
                  //since we don't know how many there could be they cannot be defined in a config file
                  //save them here so they can be added to the graph vectors below    
                  //naming convention of measurements is xVal_num_section_page, yVal_num_section_page
                  //num uniquely identifies value so x num should = y num
                  //section allows graphing of more than one measurement axis e.g. if top of page is different graph than bottom of page see rourke
                  //page is the pdf page it should be plotted on
                  if( temp.toString().startsWith("xVal_") ) {
                  	MiscUtils.getLogger().debug("Processing " + temp.toString());
                  	
                  	index = temp.indexOf("_");
                  	index2 = temp.indexOf("_", index+1);
                  	elementNum = temp.substring(index+1,index2);
                  	
                  	index3 = temp.lastIndexOf("_");
                  	section = Integer.parseInt(temp.substring(index2 + 1, index3));                	
                  	page = Integer.parseInt(temp.substring(index3+1));
                  	
                  	//page is zero based, numPages is not
                  	if( page >= numPages ) {
                  		continue;
                  	}
                  	
                  	//if this is the first measurement of the section init array
                  	while( xMeasurementValues.get(page).size() <= section ) {
                  		MiscUtils.getLogger().debug("Adding section " + section);
                  		List<List<String>> list = xMeasurementValues.get(page);
                  		list.add(new ArrayList<String>());
                  	}
                  	                	
                  	while( yMeasurementValues.get(page).size() <= section ) {
                  		List<List<String>> list = yMeasurementValues.get(page);
                  		list.add(new ArrayList<String>());
                  	}
                  	
                  	xMeasurementValues.get(page).get(section).add((String)req.getAttribute(temp.toString()));
                  	MiscUtils.getLogger().debug("Setting xMeasurementDate to " + (String)req.getAttribute(temp.toString()));
                  	                	
                  	temp = new StringBuilder("yVal_");
                  	temp = temp.append(elementNum);
  