import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.html.WebColors;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import com.itextpdf.text.pdf.parser.Vector;
public class PDFNotes
{
private PdfStamper stamper;
private PdfReader reader;
private HashMap<String, String> commentColours;
private String latexSrc;
public static void main(String[] args)
{
PDFNotes note = null;
try
{
note = new PDFNotes();
note.open("C:\\Users\\augustine\\Dropbox\\phd_folders\\research_docs\\latex_docs\\students_project\\students_project.pdf",
"students_projects_commented.pdf",
"C:\\Users\\augustine\\Dropbox\\phd_folders\\research_docs\\latex_docs\\students_project\\students_project.tex");
note.placeComments("%", "\\cmt%");
}
catch(Exception ex)
{
ex.printStackTrace();
System.out.println("Error: " + ex.getMessage());
}
finally
{
if(note != null)
note.cleanup();
}
}
public PDFNotes()
{
// set colours for various comment types
commentColours = new HashMap<String, String>();
commentColours.put("Comment", "#006400");
commentColours.put("Help", "#00008B");
commentColours.put("Note", "#800000");
commentColours.put("Key", "#4B0082");
commentColours.put("NewParagraph", "#006400");
commentColours.put("Paragraph", "#006400");
commentColours.put("Insert", "#006400");
}
public boolean open(String inpSrc, String destSrc, String latexSrc) throws Exception
{
reader = new PdfReader(inpSrc);
stamper = new PdfStamper(reader, new FileOutputStream(destSrc));
this.latexSrc = latexSrc;
return stamper!= null;
}
public Object[] getFirstPositionOfText(String text) throws Exception
{
MyTexExStrat strat = new MyTexExStrat(text);
for(int i=1; i<reader.getNumberOfPages(); i++)
{
PdfTextExtractor.getTextFromPage(reader, i, strat);
if(strat.getRect() != null)
{
System.out.println(strat.getResultantText());
return new Object[]{strat.getRect(), i};
}
}
return new Object[]{new Rectangle(25,25,50,50), 1};
}
public void placeComments(String pdfToken, String latexToken) throws Exception
{
ArrayList<Object[]> pdfComments = parsePDF(pdfToken);
ArrayList<String[]> latexComments = parseLatex(latexSrc, latexToken);
if(pdfComments.size() != latexComments.size())
throw new Exception("Seens there is a problem parsing the input pdf file - might be the use of % (will fix bug later)");
for(int i=0; i<latexComments.size(); i++)
{
addStickyNote(latexComments.get(i)[0], latexComments.get(i)[1], (Rectangle)pdfComments.get(i)[0], (Integer)pdfComments.get(i)[1]);
}
}
public ArrayList<Object[]> parsePDF(String text) throws Exception
{
MyTexExStrat strat = new MyTexExStrat(text);
for(int i=1; i<reader.getNumberOfPages(); i++)
{
PdfTextExtractor.getTextFromPage(reader, i, strat);
strat.setPageNumber(i);
}
return strat.getMatches();
}
public ArrayList<String[]> parseLatex(String src, String token)
{
ArrayList<String[]> comments = new ArrayList<String[]>();
try
{
FileInputStream fstream = new FileInputStream(src);
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
while ((strLine = br.readLine()) != null)
{
if(strLine.length()>4)
if(strLine.substring(0, 5).toLowerCase().trim().equals(token.toLowerCase().trim()))
{
String[] tokens = strLine.replace(token.toLowerCase().trim(), "").split(":");
if(tokens.length>1)
{
String commmentType = tokens[0].trim();
String commentText = tokens[1].trim();
comments.add(new String[] {commmentType, commentText});
}
}
}
in.close();
}
catch (Exception e)
{
System.err.println("Error: " + e.getMessage());
}
return comments;
}
public void addStickyNote(String title, String text, Rectangle rect, int pageNum) throws Exception
{
// create the annotation
// possible icons: "Comment", "Key", "Note", "Help", "NewParagraph", "Paragraph", "Insert"
PdfAnnotation annotation = PdfAnnotation.createText(stamper.getWriter(), rect, title, text, true, title);
// set the colour
annotation.setColor(WebColors.getRGBColor(commentColours.get(title)));
// append to output pdf
stamper.addAnnotation(annotation, pageNum);
}
public void cleanup()
{
try
{
if(stamper != null)
stamper.close();
if(reader != null)
reader.close();
}
catch(Exception ex)
{
ex.printStackTrace();
System.out.println("Error: " + ex.getMessage());
}
}
public class MyTexExStrat implements TextExtractionStrategy
{
private String target = "";
private Rectangle rect = null;
private ArrayList<Object[]> matches;
public MyTexExStrat(String target)
{
this.target = target;
matches = new ArrayList<Object[]>();
}
public void beginTextBlock() {}
public void endTextBlock() {}
public void renderImage(ImageRenderInfo info) {}
public void renderText(TextRenderInfo info)
{
if(info.getText().toLowerCase().trim().equals(target.toLowerCase().trim()))
{
Vector bottomLeft = info.getDescentLine().getStartPoint();
Vector topRight = info.getAscentLine().getEndPoint();
rect = new Rectangle(bottomLeft.get(Vector.I1),
bottomLeft.get(Vector.I2),
topRight.get(Vector.I1),
topRight.get(Vector.I2));
matches.add(new Object[]{rect, null});
}
}
@Override
public String getResultantText()
{
return target;
}
public Rectangle getRect()
{
return rect;
}
public void setPageNumber(int pageNumber)
{
for(Object[] o : matches)
if(o[1] == null)
o[1] = pageNumber;
}
public ArrayList<Object[]> getMatches()
{
return matches;
}
}
}