/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package Writers;
import Core.Data;
import Core.GraphResultDrawer;
import Core.Result;
import Core.ResultManager;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
import java.awt.Image;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
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.PdfPCell;
import java.awt.Color;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author LauretHa
*/
public class PDFWriter extends FileWriter
{
/**
* Constructor for objects of class PDFWriter
* @param data data to be written to file
* @param result result to be written to file
* @param outputFile destination file
* @param pageSetup whether page setup is needed
* @param coverPage whether cover page is needed
* @param author auther of the project
* @param projectDesc Description of the project
* @throws Exception if an error happens while processing
*/
public PDFWriter(Data data,Result result,File outputFile, boolean pageSetup, boolean coverPage, String author, String projectDesc) throws Exception
{
this.data = data;
this.result = result;
this.outputFile = outputFile;
this.pageSetup = pageSetup;
this.coverPage = coverPage;
this.author = author;
this.projectDesc = projectDesc;
}
@Override
/**
* Generates a PDF file and add contents to the file
* @throws FileNotFoundException
* @throws IOException
*/
public void writeAll() throws FileNotFoundException, IOException{
// Creation of a document object
Document document = new Document();
// Variable declaration and initialization
ResultManager rm = new ResultManager(result);
GraphResultDrawer graphDrawer = rm.getGraphDrawer();
Image[] images = graphDrawer.getGraphImages();
// Add the data into the PDF file based on the page
// layout that the user chosen
if(pageSetup == false) {
// Set the page layout as landscape
document = new Document(PageSize.LETTER.rotate());
addDataLandscape(document, images);
}else if(pageSetup == true) {
addDataPortrait(document, images);
}
}
/**
* Add the data in landscape page layout into the PDF file
* @param doc
* document object
* @param imgs
* Array containing images of the result graphs
*/
public void addDataLandscape(Document doc, Image[] imgs) {
try {
// Create a writer that listens to the document and directs
// a PDF-stream to a file
PdfWriter.getInstance(doc, new FileOutputStream(outputFile));
// Set the header and footer of the file
addHeaderFooter(doc);
// Open the document
doc.open();
// Creates a cover page
if(coverPage == true) {
Paragraph paragraph = new Paragraph();
com.lowagie.text.Image theLogo = com.lowagie.text.Image.getInstance("icons/logo_1.jpg");
theLogo.setAlignment(com.lowagie.text.Image.MIDDLE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(theLogo);
Chunk institution = new Chunk("Swinburne University of Technology", new Font(Font.TIMES_ROMAN, 24, Font.BOLD));
Chunk institution2 = new Chunk("(Sarawak Campus)", new Font(Font.TIMES_ROMAN, 24, Font.BOLD));
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(institution);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(institution2);
Chunk theProjectDesc = new Chunk(projectDesc, new Font(Font.TIMES_ROMAN, 16, Font.BOLD));
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(theProjectDesc);
Chunk theAuthor = new Chunk(author, new Font(Font.TIMES_ROMAN, 16, Font.NORMAL));
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(theAuthor);
String DATE_FORMAT_NOW = "MMMM yyyy";
Calendar c = Calendar.getInstance();
SimpleDateFormat dateFormatted = new SimpleDateFormat(DATE_FORMAT_NOW);
String theDate = dateFormatted.format(c.getTime());
Chunk date = new Chunk(theDate, new Font(Font.TIMES_ROMAN, 14, Font.NORMAL));
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(date);
paragraph.setAlignment(Element.ALIGN_CENTER);
doc.add(paragraph);
doc.newPage();
}
// Add the table into the PDF file
addTables(doc);
doc.newPage();
// Add the result graph into the PDF File
Chunk graphName = new Chunk("The Result Graph", new Font(Font.TIMES_ROMAN, 18, Font.BOLD));
Paragraph pGraph = new Paragraph();
pGraph.add(graphName);
doc.add(pGraph);
doc.add(Chunk.NEWLINE);
for(int i = 0; i <= 4; i+=2)
{
com.lowagie.text.Image img = com.lowagie.text.Image.getInstance(imgs[i], null);
img.setAbsolutePosition(50, 200);
doc.add(img);
com.lowagie.text.Image img1 = com.lowagie.text.Image.getInstance(imgs[i+1], null);
img1.setAbsolutePosition(425, 200);
doc.add(img1);
doc.newPage();
}
int theLast = imgs.length - 1;
com.lowagie.text.Image img = com.lowagie.text.Image.getInstance(imgs[theLast], null);
img.setAbsolutePosition(50, 200);
doc.add(img);
doc.newPage();
// Add user's additional notes into the PDF file
addNotes(doc);
} catch (DocumentException de) {
System.err.println(de.getMessage());
} catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
// Close the document
doc.close();
}
/**
* Add the data in portrait page layout into the PDF file
* @param doc
* document object
* @param imgs
* Array containing images of the result graphs
*/
public void addDataPortrait(Document doc, Image[] imgs) {
try {
// Create a writer that listens to the document and directs
// a PDF-stream to a file
PdfWriter.getInstance(doc, new FileOutputStream(outputFile));
// Set the header and footer of the file
addHeaderFooter(doc);
// Open the document
doc.open();
// Creates a cover page
if(coverPage == true) {
Paragraph paragraph = new Paragraph();
com.lowagie.text.Image theLogo = com.lowagie.text.Image.getInstance("icons/logo_1.jpg");
theLogo.setAlignment(com.lowagie.text.Image.MIDDLE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(theLogo);
Chunk institution = new Chunk("Swinburne University of Technology", new Font(Font.TIMES_ROMAN, 24, Font.BOLD));
Chunk institution2 = new Chunk("(Sarawak Campus)", new Font(Font.TIMES_ROMAN, 24, Font.BOLD));
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(institution);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(institution2);
Chunk theProjectDesc = new Chunk(projectDesc, new Font(Font.TIMES_ROMAN, 16, Font.BOLD));
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(theProjectDesc);
Chunk theAuthor = new Chunk(author, new Font(Font.TIMES_ROMAN, 16, Font.NORMAL));
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(theAuthor);
String DATE_FORMAT_NOW = "MMMM yyyy";
Calendar c = Calendar.getInstance();
SimpleDateFormat dateFormatted = new SimpleDateFormat(DATE_FORMAT_NOW);
String theDate = dateFormatted.format(c.getTime());
Chunk date = new Chunk(theDate, new Font(Font.TIMES_ROMAN, 14, Font.NORMAL));
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(Chunk.NEWLINE);
paragraph.add(date);
paragraph.setAlignment(Element.ALIGN_CENTER);
doc.add(paragraph);
doc.newPage();
}
// Add the table into the PDF file
addTables(doc);
doc.newPage();
// Add the result graph into the PDF File
Chunk graphName = new Chunk("The Result Graph", new Font(Font.TIMES_ROMAN, 18, Font.BOLD));
Paragraph pGraph = new Paragraph(graphName);
doc.add(pGraph);
for(int i = 0; i <= 6; i++)
{
doc.add(Chunk.NEWLINE);
com.lowagie.text.Image img = com.lowagie.text.Image.getInstance(imgs[i], null);
doc.add(img);
doc.add(Chunk.NEWLINE);
}
doc.newPage();
// Add user's additional notes into the PDF file
addNotes(doc);
} catch (DocumentException de) {
System.err.println(de.getMessage());
} catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
// Close the document
doc.close();
}
/**
* Add header and footer into the PDF file
* @param doc
* document object
*/
public void addHeaderFooter(Document doc) {
// Set the author name and project description as the file header
HeaderFooter footer = new HeaderFooter(new Phrase(projectDesc + " - " + author, FontFactory.getFont(FontFactory.TIMES_ROMAN, 10, Font.NORMAL, new Color(64, 62, 62))), false);
// Set page number as the file footer
HeaderFooter header = new HeaderFooter(new Phrase("Page ", FontFactory.getFont(FontFactory.TIMES_ROMAN, 10, Font.NORMAL, new Color(64, 62, 62))), true);
footer.disableBorderSide(Rectangle.TOP);
footer.disableBorderSide(Rectangle.BOTTOM);
// Set the footer alignment to the center
footer.setAlignment(Rectangle.ALIGN_CENTER);
header.disableBorderSide(Rectangle.TOP);
header.disableBorderSide(Rectangle.BOTTOM);
// Set the footer alignment to the right
header.setAlignment(Rectangle.ALIGN_RIGHT);
doc.setHeader(header);
doc.setFooter(footer);
}
/**
* Add the data and result tables into the PDF file
* @param doc
* document object
*/
public void addTables(Document doc) {
try {
// Create the title for the data table
Chunk theDataTable = new Chunk("The Data Table", new Font(Font.TIMES_ROMAN, 18, Font.BOLD));
Paragraph pData = new Paragraph(theDataTable);
pData.setAlignment(Element.ALIGN_CENTER);
doc.add(pData);
doc.add(Chunk.NEWLINE);
// Generates the data table
int rowNo = 5;
PdfPTable dataTableHeader = new PdfPTable(rowNo);
PdfPCell dataTblHeaderCell;
Phrase pTemp = new Phrase("NODE", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
dataTblHeaderCell = new PdfPCell(pTemp);
dataTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
dataTableHeader.addCell(dataTblHeaderCell);
pTemp = new Phrase("DEPTH"+"\n"+"(m)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
dataTblHeaderCell = new PdfPCell(pTemp);
dataTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
dataTableHeader.addCell(dataTblHeaderCell);
pTemp = new Phrase("MODULUS OF SUBGRADE REACTION"+"\n"+"(kN/m)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
dataTblHeaderCell = new PdfPCell(pTemp);
dataTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
dataTableHeader.addCell(dataTblHeaderCell);
pTemp = new Phrase("LATERAL SOIL MOVEMENTS"+"\n"+"(m)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
dataTblHeaderCell = new PdfPCell(pTemp);
dataTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
dataTableHeader.addCell(dataTblHeaderCell);
pTemp = new Phrase("LIMIT SOIL PRESSURE"+"\n"+"(kN/m²)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
dataTblHeaderCell = new PdfPCell(pTemp);
dataTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
dataTableHeader.addCell(dataTblHeaderCell);
PdfPCell dataTblCell;
PdfPTable dataTable = new PdfPTable(rowNo);
for (int i = 0; i <= data.getNumOfElements(); i++) {
Phrase pNode = new Phrase(Integer.toString(i), FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
dataTblCell = new PdfPCell(pNode);
dataTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
dataTable.addCell(dataTblCell);
Phrase pPileNodeCoord = new Phrase(Double.toString(data.getPileNodeCoordinate(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
dataTblCell = new PdfPCell(pPileNodeCoord);
dataTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
dataTable.addCell(dataTblCell);
Phrase pModOfSub = new Phrase(Double.toString(data.getModOfSubgradeReaction(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
dataTblCell = new PdfPCell(pModOfSub);
dataTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
dataTable.addCell(dataTblCell);
Phrase pLateralSoilMov = new Phrase(Double.toString(data.getLateralSoilMovement(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
dataTblCell = new PdfPCell(pLateralSoilMov);
dataTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
dataTable.addCell(dataTblCell);
Phrase pLimitSoilPress = new Phrase(Double.toString(data.getLimitSoilPressure(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
dataTblCell = new PdfPCell(pLimitSoilPress);
dataTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
dataTable.addCell(dataTblCell);
}
doc.add(dataTableHeader);
doc.add(dataTable);
doc.newPage();
// Create the title for the result table
Chunk theResultTable = new Chunk("The Result Table", new Font(Font.TIMES_ROMAN, 18, Font.BOLD));
Paragraph pResult = new Paragraph(theResultTable);
pResult.setAlignment(Element.ALIGN_CENTER);
doc.add(pResult);
doc.add(Chunk.NEWLINE);
// Generates the result table
rowNo = 9;
PdfPTable resultTableHeader = new PdfPTable(rowNo);
PdfPCell resultTblHeaderCell;
pTemp = new Phrase("NODE", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
resultTblHeaderCell = new PdfPCell(pTemp);
resultTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTableHeader.addCell(resultTblHeaderCell);
pTemp = new Phrase("DEPTH"+"\n"+"(m)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
resultTblHeaderCell = new PdfPCell(pTemp);
resultTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTableHeader.addCell(resultTblHeaderCell);
pTemp = new Phrase("SOIL MOVEMENT"+"\n"+"(mm)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
resultTblHeaderCell = new PdfPCell(pTemp);
resultTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTableHeader.addCell(resultTblHeaderCell);
pTemp = new Phrase("SOIL PRESSURE"+"\n"+"(kPa)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
resultTblHeaderCell = new PdfPCell(pTemp);
resultTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTableHeader.addCell(resultTblHeaderCell);
pTemp = new Phrase("ABS"+"\n"+"SOIL PRESSURE"+"\n"+"(kPa)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
resultTblHeaderCell = new PdfPCell(pTemp);
resultTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTableHeader.addCell(resultTblHeaderCell);
pTemp = new Phrase("DISPLACEMENT"+"\n"+"(mm)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
resultTblHeaderCell = new PdfPCell(pTemp);
resultTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTableHeader.addCell(resultTblHeaderCell);
pTemp = new Phrase("ROTATION"+"\n"+"(rad)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 7, Font.BOLD));
resultTblHeaderCell = new PdfPCell(pTemp);
resultTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTableHeader.addCell(resultTblHeaderCell);
pTemp = new Phrase("BENDING MOMENT"+"\n"+"(kNm)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
resultTblHeaderCell = new PdfPCell(pTemp);
resultTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTableHeader.addCell(resultTblHeaderCell);
pTemp = new Phrase("SHEAR FORCE"+"\n"+"(kN)", FontFactory.getFont(FontFactory.TIMES_ROMAN, 8, Font.BOLD));
resultTblHeaderCell = new PdfPCell(pTemp);
resultTblHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTableHeader.addCell(resultTblHeaderCell);
PdfPTable resultTable = new PdfPTable(rowNo);
PdfPCell resultTblCell;
for (int i = 0; i < data.getNumOfElements() + 1; i++) {
Phrase pNodes = new Phrase(Integer.toString(i), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.BOLD));
resultTblCell = new PdfPCell(pNodes);
resultTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTable.addCell(resultTblCell);
Phrase pPileNodeCoord = new Phrase(Double.toString(data.getPileNodeCoordinate(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
resultTblCell = new PdfPCell(pPileNodeCoord);
resultTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTable.addCell(resultTblCell);
Phrase pSoilMov = new Phrase(Double.toString(result.getSoilMovement(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
resultTblCell = new PdfPCell(pSoilMov);
resultTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTable.addCell(resultTblCell);
Phrase pSoilPress = new Phrase(Double.toString(result.getSoilPressure(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
resultTblCell = new PdfPCell(pSoilPress);
resultTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTable.addCell(resultTblCell);
Phrase pLimitPressure = new Phrase(Double.toString(result.getLimitPressure(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
resultTblCell = new PdfPCell(pLimitPressure);
resultTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTable.addCell(resultTblCell);
Phrase pDisplacement = new Phrase(Double.toString(result.getDisplacement(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
resultTblCell = new PdfPCell(pDisplacement);
resultTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTable.addCell(resultTblCell);
Phrase pRotation = new Phrase(Double.toString(result.getRotation(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
resultTblCell = new PdfPCell(pRotation);
resultTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTable.addCell(resultTblCell);
Phrase pBendingMoment = new Phrase(Double.toString(result.getBendingMoment(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
resultTblCell = new PdfPCell(pBendingMoment);
resultTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTable.addCell(resultTblCell);
Phrase pShearForce = new Phrase(Double.toString(result.getShearForce(i)), FontFactory.getFont(FontFactory.TIMES_ROMAN, 9, Font.NORMAL));
resultTblCell = new PdfPCell(pShearForce);
resultTblCell.setHorizontalAlignment(Element.ALIGN_CENTER);
resultTable.addCell(resultTblCell);
}
doc.add(resultTableHeader);
doc.add(resultTable);
} catch (DocumentException ex) {
Logger.getLogger(PDFWriter.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Add additional notes into the PDF file
* @param doc
* document object
* @throws FileNotFoundException
* @throws DocumentException
* @throws IOException
*/
public void addNotes(Document doc) throws FileNotFoundException, DocumentException, IOException {
// Variable declaration and initialization
String line;
Paragraph p;
File f = new File("notes.txt");
boolean exists = f.exists();
// Read the additional notes from a temporary file
BufferedReader reader = new BufferedReader(new FileReader("notes.txt"));
// Add the notes to the PDF file
if (exists) {
doc.newPage();
Chunk theNotes = new Chunk("Notes", new Font(Font.TIMES_ROMAN, 18, Font.BOLD));
doc.add(new Paragraph(theNotes));
}
// Retreive the notes from the txt file and add it into the PDF file
while ((line = reader.readLine()) != null && exists) {
doc.add(Chunk.NEWLINE);
p = new Paragraph(line);
p.setAlignment(Element.ALIGN_JUSTIFIED);
doc.add(p);
}
}
}