PDF Generator

Allgemeines Schema

Abfrageablauf

Die PDF Erzeugung läuft in einem mehrstufigen Ablauf von Anfragen ab.

  1. Holen verfügbarer Konfigurationen
  2. Auswahl des gewünschten, zu erzeugenden Dokumentes
  3. Abholen der Parameter- und Datenbeschreibung, die Tempest dazu von Nutzer benötigt ()
  4. Eingabe der Daten und Parameter
  5. Aufruf der Datenextraktion mit den eingegbene Parametern.
    1. Erstellung des Datenauszuges
    2. Erzeugung des PDF-Dokumentes
    3. RemoteCopy auf den FrontEnd-Server
    4. Eintragung des Dokumentennames und der URL
  6. Abholen der URL des Dokumentes
  7. Ggf. Download

Datenstruktur

DataRequestConfig

ParameterConfig

PDF-Config

Config Objekt

{
  "doc_cfg":{},
  "data_set":{},
  "head":{},
  "body":{},
  "foot":{},
  "inner_head":{},
  "inner_foot":{}
}

Alle Elemente sind optional. Ist ein Element nicht vorhanden, wird es durch vernünftige Standardwerte ersetzt.

Dokumenten Konfiguration

Mit dem Schlüssel doc_cfg wird die Konfiguration des gesammten Dokumentes eröffnet.

Absolute Größe
"size_x" : <int>
"size_y" : <int>

Größe einer Seite des Dokumentes in Punkten. Falls keine Werte oder falsche Werte angegeben werden, wird x=612 und y=792 angenommen, was in etwa einem DinA4 Dokument entspricht.

Absolute Ränder
"margin_top" : <int>
"margin_bottom" : <int>
"margin_left" : <int>
"margin_right" : <int>

Mit diesen Werten, werden absolute Randbereich festgelegt, von denen aus später Positionen berechnet werden. Dh. insbesondere, daß diese werte zu den absoluten Positionen automatisch addiert werden. (Bitte beachten: Wird ein Textinhalt unter angegebenen Typen und Schriftgrößen zu lang, kann dieser durch aus in den margin Bereich hineinragen.)

Werden keione Werte angegeben, so sind 20 Punkt als Rand an allen Seiten angenommen.

Fuß und Kopfbereiche innerhalb des Dokuments
"inner_head" : <int>
"inner_foot" : <int>

Sollen innerhalb des Dokumentes Kopf und Fussbereiche definiert werden, so muss deren absolute Länge vorab angegeben werden. Das Satzsystem bricht fliessenden Inhalt (im Dokumentenkörper) automatisch um und benötigt diese Angaben zur Freihaltung vorab.

Werden keine werte angegeben, wird 0 Punkte für beide Werte vorausgesetzt.


Datensatz

"data_set" : { ... }

Alle im Dokument verwendeten konstanten Texte und Bilder müssen in einem Datensatz der Konfiguration angegeben und mit einem Schlüssel versehen werden. Dh. jeder verwendete feste Text, bespielsweise die Absenderadresse einer Firma im Fenster eines Briefdokumentes, oder das Wort Seite: vor ein eventuel anzugebenden Pagina in einem Fussteil, müssen als Wert hier mit einem Schlüssel aufgeführt werden. In den body, head oder foot Teilen, wird ihre Position und Darstellung dann anhand der definiert und der Inhalt über den Schlüssel referenziert.

Texte
<key> : <value>

Einfache Texte werden als Schlüssel/Wert Paare aufgeführt.

Beispiel: „companyAdress“ : „Muster GmbH, Teststr.14, 12345 Beispieldorf“

Diese Schlüssel müssen in der späteren Konfiguration so verwendet werden, dass die Erwartung eines auszugebenenden Textes an der entsprechenden Stelle gerechtfertigt ist.

Bilder
<key> : <absolute_path_to_file>

Um Bilder einzubinden existieren in der späteren Dokumentdefinition eigene Befehle. Diese müssen um den absoluten Dateipfad eines auf dem Server hinterlegten Bildes erweitert werden. Derzeit wirde nur das JPG-Format unterstützt.

Beispiel „company_logo“:„/test/name.jpg“


Inhalt

"body":{
  "queue_elements":[
    ]
},

Der eigentliche Dokumenteninhalt ist in der Länge variabel und kann vom Satzsystem umgebrochen werden. Er enthält eine geornete Menge an Elementen. Jedes Element selbst ist abgeschlossen und definiert entweder eine absolute Länge, falls es atomar ist „type“:„elements_fix“ , oder es definiert eine absolute Länge eines Teilelementes, falls es sich selbst um eine Liste handelt „type“:„list_fix“ . (Definition siehe dort.)

Beispiel:

"body":{
"queue_elements":[
	{"type":"elements_fix",
		"length":40,
		"elements_fix":[
			{"type":"text_fix",
				"pos_x":0,
				"pos_y":35,
				"size":20,
				"font":"font_times",
				"text":"bracketopen"},
			]
	}
      ]
 }
Atomare Elemente
{"type":"elements_fix",
  ...
  }

Bestandteile des Dokumenteninhalts, die in Struktur fest sind. Dh. es werden nur Textinhalte oder Bilder ausgetauscht.

Attribute:

  • „length“ : Absolute Länge des Elements in Punkten.
  • „type“ : Festwert elements_fix. S.o.
  • „elements_fix“ : Liste der Einzelobjekte

Beispiel:

"body":{
"queue_elements":[
	{"type":"elements_fix",
		"length":40,
		"elements_fix":[
			{"type":"text_fix",
				"pos_x":0,
				"pos_y":35,
				"size":20,
				"font":"font_times",
				"text":"bracketopen"},
			]
	}
      ]
 }
Listenelemente
{"type":"list_fix",
  ...
  }

Bestandteile des Dokumenteninhalts, die Ausgaben von Datenlisten spezifizieren. Dh. jede Zeile (Listenelement) enspricht einer Indexposition einer jeweiligen Liste. Ein Zeile einer Tabelle kann als dadurch erzeugt werden, in dem in dem jeweiligen Abschnitt des Dokumentes an verschiedenen x-Positionen, verschiedene Spalten ausgegeben und gestaltet werden.

Einschränkungen sind folgende. Die referenzierten Ausgabeelemente müssen durch Inhaltsschlüssel gefüllt werden, die auf Listendaten zeigen. (Diese können über das eigene oder ein extern hinzugefügtes Datenobjekt definiert werden.) Alle referenzierten Listen sollten die selbe Länge haben. (Falls nicht bleiben die nicht mehr vorhandenen Werte leer.) Und schliesslich muss eine so definierte Zeile einer Tabelle ein vorher bestimmbare Lämge in Punkten haben. Kann diese Länge nicht angegeben werden, ist ein Berechnung des Umbruchpunktes durch das Satzsystem nicht möglich. (Eine Zeile muss deshalb auch einen Punktlänge haben, die kleiner ist als der minimale Raum der für den body in einem Dokument verfügbar ist, sonst würde ein Einfügen einer neuen seite nicht zu ausreichend Platz für das nähste element führen.)

Attribute:

  • „length“ : Absolute Länge des Einzelelements in Punkten.
  • „type“ : Festwert list_fix. S.o.
  • „list_elements“ : Liste der Einzelobjekte

Beispiel:

"body":{
"queue_elements":[
	{"type":"list_fix",
		"length":40,
		"list_elements":[
			{"type":"text_fix",
				"pos_x":0,
					"pos_y":35,
				"size":20,
				"font":"font_times",
				"text": <key_pointing_to_list_data>},
			]
	}
      ]
 }

Fix Element


Standardattribute

Darstellbares Einzelelement innerhalb verschiedener Block-, Fix-, und Listenelemente.

{"type" : <String>,
  "pos_x" : <int>,
  "pos_y" : <int>,
  ... }
  • „type“ : Typ des Darstellungsobjektes
  • „pos_x“ : Absolute X-Position eines Elementes
  • „pos_y“ : Absolute Y-Position eines Elementes

X und Y-Position, relativ zur linken oberen Ecke des betrachteten Bereiches. Der betrachtete Bereich ist zB. in einer Tabelle der rechte obere Punkt in der aktuellen Zeile der Tabelle.

Farbe
  • „red“ : <int>
  • „green“ : <int>
  • „blue“ : <int>

Angabe der Lumineszenz der rot, grün oder blau Werte im Gültigkeitsbereich von 0..255. Standard ist für alle Werte 0, was Schwaz ergibt.

Beispiel Magenta:

{
  "red":255,
  "blue":255,
  ...
}

Weitere Attribute sind abhängig vom konkreten Typ des Objektes.


Bildelement

Typ: „graphix_fix“

Position bezeichnet das linke obere Eck der Graphik. Externe Farbattribute werden nicht interpretiert.

Quellattribut: „source“

Schlüssel der Pfadangaben, die im Datenelement spezifiziert sein muss. Der String, der dort unter dem angegebenen Schlüssel ermittelt wird, wird als komletter Pfad zur Quelle der Bilddatei interpretiert, die dargestellt werden soll.

Implementiert sind derzeit nur JPG-Dateien.

Beispiel: „source“:„logo“


Fester Text

Typ: „text_fix“

Position bezeichnet das linke untere Eck des Schriftzuges. Die Höhe ergibt sich aus der Typengröße. Die Länge ergibt sich aus dem Text, der aus dem Datensatz ermittelt wird. Bitte beachten:Ein zu langer Text kann über das Dokument hinausreichen. Ümbrüche sind nicht möglich.

  • Quellattribut: „text“ : <String>

Schlüssel der Pfadangaben, die im Datenelement spezifiziert sein muss. Der String, der dort unter dem angegebenen Schlüssel ermittelt wird, wird als Text interpretiert, der dargestellt werden soll.

Beispiel: „text“:„address“

  • Quellattribut: „size“ : <int>

Größe der Schrift in Punkt. Ohne diese Angabe wird 10 Punkt angenommen.

Beispiel: „size“ : 14

  • Quellattribut: „font“ : <String>

Verfügbare Fonts:

  • „font_helvetica“
  • „font_helvetica_bold“
  • „font_helvetica_bold_italic“
  • „font_helvetica_italic“
  • „font_times“
  • „font_times_bold“
  • „font_times_bold_italic“
  • „font_times_italic“
  • „font_courier“
  • „font_courier_bold“

Schriftart. Ohne diese Angabe wird Helvectica angenommen.

Beispiel: „font“ : „font_times“


Linie

Typ: „line_fix“

Die Attribute „pos_x“ und „pos_y“ werden nicht interpretiert. Stattdessen wird die Definition eines Anfangs und Endpunktes der Linie erwartet.

Quellattribute:

  • „from_x“ : <int>
  • „from_y“ : <int>
  • „to_x“ : <int>
  • „to_y“ : <int>
  • „line_width“ : <int>

Beispiel:

{
  ...
   "from_x" : 10,
   "from_y" : 32,
   "to_x" : 220,
   "to_y" : 32,
   "line_width" : 1.5,
   ...
}

Zieht eines waagrechte, schwarze Linie von x=(10,32) nach y=(220,32) mit einer Strich-Dicke von 1,5 Punkt. (Farbe: siehe allgemeine Parameter)


Text mit Umbruch

Typ: „text_box_fix“

Ermöglicht die Eingrenzung eines Rechteckbereiches zur Textausgabe. Dieser Bereich in in seinen x-Dimensionen festgelegt und in seinen y-Dimensionen dem Satzumbruch überlassen, wodurch er geegnet ist die Struktur der Zeile in einer Tabelle zu spezifizieren. Nur die absolute Höhe des Blockes muss a priori festgelegt werden.

Quellattribute:

  • „length“ : <int>
  • „from_x“ : <int>
  • „to_x“ : <int>
  • „text“ : „String“

Wird „text_box_fix“ innerhalb eines „list_fix“-Elementes verwendet, muss der Wert des Attributes „text“ auf ein Datenelement deuten, das eine Liste von Strings ist.

Wird „text_box_fix“ innerhalb eines „elements_fix“-Elementes verwendet, muss der Wert des Attributes „text“ auf ein Datenelement deuten, das einStrings ist. (Diese Variante ist noch nicht implementiert)

Schlüssel der Pfadangaben, die im Datenelement spezifiziert sein muss. Der String, der dort unter dem angegebenen Schlüssel ermittelt wird, wird als Text interpretiert, der dargestellt werden soll.

Beispiel:

{"type":"list_fix",
  "length":100,
  "list_elements":[
    {"type":"text_box_fix",
      "from_x":0,
      "to_x":100,
      "length":90,
      "font":"font_times_italic",
      "size":10,
      "text":"textitems_1"},

Andere Attribute siehe „text_fix“.


Material

Software

Wir verwenden pdfbox der Apache-Foundation

Ergebnisse der ersten Spielereien

DIN A 4 Dokument wird von links unten her koordiniert.

Positionen in der Graphik im Punkt-Maß. Dh. Die Koordinaten gehen von:

0,0
612,792

API Klassen

PDDocument

Basisklasse eines mehrseitigen Dokumentes.

PDDocument doc=new PDDocument()
...
...
doc.addPage( ... )
...
...
doc.save("...<path>/...<filename>.pdf")
doc.close()

Achtung: Dokument sichern vor dem Schliessen!

PDPage

Einzelseite, die in das Dokument eingefügt wird.

PDPage p1=new PDPage()
<document>.addPage(p1)

Beispiele

Demodokument

Implementierung

InputStream inp = new FileInputStream(new File("/home/barth/Arbeitsfläche/test/5.jpeg"));

String t="Hallo Blasius Anonymusius!!!"
PDDocument doc=new PDDocument()
PDJpeg img = new PDJpeg(doc, inp);

PDPage p1=new PDPage()
doc.addPage(p1)
	
PDPageContentStream content = new PDPageContentStream(doc,p1)

PDFont font = PDType1Font.HELVETICA
int xoffset=80
int yoffset=650
int fsize=36
float w=(font.getStringWidth(t)/1000)*fsize


content.beginText()
content.setFont(font, fsize)
content.moveTextPositionByAmount(xoffset, yoffset)
content.drawString(t)
content.endText()

content.drawLine( xoffset, (yoffset+fsize), (xoffset+w.intValue()), (yoffset+fsize))
content.drawLine( xoffset, (yoffset+fsize),  xoffset, (yoffset-fsize))
content.drawLine( xoffset, (yoffset-fsize), (xoffset+w.intValue()), (yoffset-fsize))
content.drawLine((xoffset+w.intValue()), (yoffset+fsize), (xoffset+w.intValue()), (yoffset-fsize))
content.drawImage(img, 450, 640);

int xmax=612
int ymax=792

content.drawLine( 10,10,600,10)
content.drawLine( 600,10,xmax,ymax)
content.drawLine( 10,10,10,780)
content.drawLine( 10,780,)


content.close()

doc.save("/home/barth/Arbeitsfläche/test/demo.pdf")
doc.close()