
<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>ieko artikel</title>
		<link>http://www.ieko.at/artikel/</link>
		

		
		<item>
			<title>dsl mit groovy</title>
			<link>http://www.ieko.at/artikel-groovy-dsl/</link>
			<description>&lt;p&gt;&lt;h4&gt;groovy-dsl-tutorial&lt;/h4&gt;
die script-sprache groovy (&lt;a href=&quot;http://groovy.codehaus.org/&quot;&gt;http://groovy.codehaus.org&lt;/a&gt;) eignet sich gut zur erstellung einer textbasierten dsl (domain specific language).&lt;/p&gt;&lt;p&gt;in diesem artikel soll anhand eines kleinen beispiels eine mgöliche vorgangsweise demonstriert werden.&lt;/p&gt;&lt;p&gt;ziel ist eine einfache dsl zur beschreibung von datenbank-tabellen, um daraus ein sql-statement zur erzeugung der tabelle zu generieren.&lt;br /&gt;(anmerkung: das ist natürlich nur eine demonstration der möglichkeiten, die sinnhaftigkeit des beispiels soll hier nicht zur debatte stehen.)&lt;/p&gt;&lt;p&gt;hier die angestrebte dsl:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;1  table(&quot;test&quot;) {&lt;br /&gt;2      column &quot;id&quot;, datatype: &quot;int&quot;, notnull: true&lt;br /&gt;3      column &quot;name&quot;, datatype: &quot;text&quot;&lt;br /&gt;&lt;/div&gt;
erklärung:&lt;br /&gt;in zeile 1 wird die tabelle &quot;test&quot; definiert, die 2 columns hat:&lt;br /&gt;in zeile 2 wird die column &quot;id&quot; definiert, deren datentyp int ist und die zwingend ausgefüllt sein muss (not null)&lt;br /&gt;in zeile 3 wird die column &quot;name&quot; mit dem datentyp text definiert&lt;/p&gt;&lt;p&gt;das ergebnis soll ein create-statement mit folgendem aussehen sein:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;create table test (&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;id&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;&amp;nbsp;&amp;nbsp;not null,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;name&amp;nbsp;&amp;nbsp;&amp;nbsp;text&lt;br /&gt;);&lt;br /&gt;&lt;/div&gt;

hier nun die schritte im einzelnen:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;vorbemerkung:&lt;/strong&gt;
groovy hat ein &quot;builder&quot;-konzept, das sich hervorragend für diese art der dsl eignet. mit dem groovy-builder können alle hierarchischen sachverhalte verwaltet werden.&lt;br /&gt;es ist in diesem beispiel nicht zwingend nötig, ich empfehle aber trotzdem die verwendung der FactoryBuilderSupport-klasse, die die abarbeitung einzelner tags (wie hier table und column) in eigene factories auslagert. dadurch wird der builder übersichtlicher, leichter erweiterbar und wartbarer.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;model:&lt;/strong&gt;
als erstes sollten wir ein daten-model definieren, in dem wir die informationen über tabellen und columns speichern.&lt;/p&gt;&lt;p&gt;dazu erzeugen wir 2 klassen:&lt;br /&gt;TableModel.groovy:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;class TableModel {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Name der Tabelle&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;String name&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Liste der Columns&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ArrayList&amp;lt;ColumnModel&amp;gt; columns = new ArrayList&amp;lt;ColumnModel&amp;gt;()&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;
und ColumnModel.groovy&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;class ColumnModel {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  * Tabelle, zu der diese Column gehört&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  TableModel table&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  * name der column&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; String name&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  * datentyp&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; String datatype&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * not null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;boolean notnull&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;
die beiden klassen definieren ihre klassen-variablen, die tabelle besitzt noch eine liste der columns, die column eine referenz auf die tabelle (diese referenz ist in unserem beispiel nicht nötig, bei komplexeren anwendungen ist es durchaus sinnvoll, zugriff auf sein master-objekt zu haben).&lt;br /&gt;bei der definition der attribute ohne sichtbarkeits-hinweise (public, protected, private) macht groovy sogenannte properties daraus, die automatisch über zugriffsmethoden getXxx und setXxx verfügen und auch als object.xxx angesprochen werden können.&lt;br /&gt;obwohl es in groovy nicht nötig ist, datentypen anzugeben (wir könnten auch def name schreiben), ist es aus meiner sicht sinnvoll, den datentyp anzugeben, sofern er feststeht und unveränderlich sein soll.&lt;/p&gt;&lt;p&gt;als nächstes erstellen wir die &lt;strong&gt;builder&lt;/strong&gt;-klasse&lt;br /&gt;TableBuilder.groovy:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;class TableBuilder extends FactoryBuilderSupport {&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public TableBuilder() {&lt;br /&gt;        registerTags()&lt;br /&gt;    }&lt;/p&gt;&lt;p&gt;    protected void registerTags() {&lt;br /&gt;        registerFactory(&quot;table&quot;, new TableFactory())&lt;br /&gt;        registerFactory(&quot;column&quot;, new ColumnFactory())&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;
hier wird für jeden verwendeten tag eine factory registriert.&lt;br /&gt;die beiden factory-klassen werden als nächstes implementiert:&lt;br /&gt;TableFactory.groovy:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;class TableFactory extends AbstractFactory {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Erzeugen Class&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;   Object newInstance( FactoryBuilderSupport builder, Object name, Object value, Map attributes )&lt;br /&gt;           throws InstantiationException, IllegalAccessException {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;attributes += [name : value]&lt;br /&gt;    &amp;nbsp;&amp;nbsp;&amp;nbsp;return new TableModel(attributes)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;
ColumnFactory.groovy:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;class ColumnFactory extends AbstractFactory {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Erzeugen Column&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;   Object newInstance( FactoryBuilderSupport builder, Object name, Object value, Map attributes )&lt;br /&gt;           throws InstantiationException, IllegalAccessException {&lt;br /&gt;        attributes += [name : value]&lt;br /&gt;        return new ColumnModel(attributes)&lt;br /&gt;    }&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * add Column to Table&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void setParent( FactoryBuilderSupport builder, Object parent, Object child ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;child.table = parent&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;parent.columns += child&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;
in der methode newInstance wird jeweils eine neue instanz unserer model-klasse erzeugt.&lt;br /&gt;hinweis zur zeile attributes += [name : value]:&lt;br /&gt;mit groovy kann man ein objekt erzeugen, in dem man im konstruktor eine map übergibt. existieren kein konstruktor mit einzigem parameter vom typ map und ein standard-konstruktor ohne parameter, so erzeugt groovy ein objekt mit diesem standard-konstruktor und setzt dann die werte der properties anhand der übergebenen map.&lt;br /&gt;da die factory in unserem beispiel jedoch den namen der tabelle bzw. column nicht in der map sondern im value übergeben bekommt, müssten wir eigene konstruktoren mit map und name erzeugen. um uns das ersparen, erweitern wir einfach die übergebene map um den namen mit dem wert, der in value steht. damit kann der groovy-automatismus verwendet werden.&lt;/p&gt;&lt;p&gt;die methode setParent in der ColumnFactory ermöglicht es uns, die beziehung zwischen tabelle und column zu setzen. in der column (child) wird die refernz auf die tabelle (parent) gesetzt, in der tabelle wird eine column in die liste der columns hinzugefügt.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;anwenden:&lt;/strong&gt;
damit sind wir schon so weit, dass wir mit dem script&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;def builder = new TableBuilder();&lt;/p&gt;&lt;p&gt;def table = builder.table(&quot;test&quot;) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;column &quot;id&quot;, datatype: &quot;int&quot;, notnull: true&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;column &quot;name&quot;, datatype: &quot;text&quot;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;
ein model der tabelle samt columns erzeugen können.&lt;/p&gt;&lt;p&gt;anmerkung: dank groovy können klammern in funktionsaufrufen wegfallen. deshalb ist statt&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;column (&quot;id&quot;, datatype: &quot;int&quot;, notnull: true)&lt;br /&gt;&lt;/div&gt;
auch folgende schreibweise möglich:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;column &quot;id&quot;, datatype: &quot;int&quot;, notnull: true&lt;br /&gt;&lt;/div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;jetzt fehlt nur mehr die &lt;strong&gt;ausgabe&lt;/strong&gt; des create-statements, die dank der kompaktheit von groovy nur wenige zeilen umfasst:&lt;br /&gt;die klasse TableModel wird um die methode create() erweitert:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * erzeugt das create-statement für die tabelle&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;String create() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return &quot;create table ${name} (\n&quot; +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(columns.collect {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;\t&quot; + it.create();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}).join(&quot;,\n&quot;) + &quot;\n);&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/div&gt;
und die klasse ColumnModel ebenfalls:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * erzeugt das create-statement für die column&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;String create() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return name + &quot;\t&quot; + datatype + (notnull?&quot;\tnot null&quot;:&quot;&quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;nun erweitern wir das scipt noch um die ausgabe:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;def builder = new TableBuilder();&lt;/p&gt;&lt;p&gt;def table = builder.table(&quot;test&quot;) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;column &quot;id&quot;, datatype: &quot;int&quot;, notnull: true&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;column &quot;name&quot;, datatype: &quot;text&quot;&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;println table.create()&lt;br /&gt;&lt;/div&gt;
das ergebnis kann natürlich auch gleich in eine sql-datei gespeichert oder über eine jdbc-connection direkt ausgeführt werden.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;fazit:&lt;/strong&gt; mit groovy kann mit wenig code eine dsl definiert werden.&lt;br /&gt;mit dem builder-konzept und der kompakten syntax zeigt groovy hier seine volle stärke.&lt;/p&gt;&lt;p&gt;die source-files zu diesem tutorial können sie &lt;a href=&quot;http://www.ieko.at/assets/downloads/TableBuilder1.zip&quot;&gt;hier downloaden&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;danke für ihre aufmerksamkeit,&lt;br /&gt;ich feue mich über kommentare und anregungen.&lt;br /&gt;&lt;/p&gt;</description>
			<pubDate>Mon, 02 Jun 2008 00:00:00 +0200</pubDate>
			
			
			<guid>http://www.ieko.at/artikel-groovy-dsl/</guid>
		</item>
		
		<item>
			<title>ausdruck von web-seiten mit css optimieren</title>
			<link>http://www.ieko.at/artikel-drucken-mit-css/</link>
			<description>&lt;p&gt;&lt;h3&gt;mehr platz zum drucken mit css&lt;/h3&gt;
beim erstellen des layouts einer web-seite wird vor allem darauf geachtet, dass die bildschirmdarstellung ansprechend ist. leider wird oft vergessen, dass die anwender/innen den inhalt der seite auch ausdrucken wollen. besonders bei längeren artikeln oder wichtigen informationen ist ein ausdruck oft hilfreich.&lt;/p&gt;&lt;p&gt;da aber das layout für den bildschirm und dem interaktiven umgang mit der seite erstellt wurde, muss man für den ausdruck einige anpassungen vornehmen, sonst ist das ergebnis äußerst unzufriedenstellend und auch keine werbung für den betreiber der web-seite. am ausdruck brauche ich keine menü-navigation oder such-felder, und wenn diese links und/oder rechts auch noch platz wegnehmen, bleibt für den eigentlichen inhalt oft nur ein schmaler streifen in der mitte, der sich dafür aber über unzählige seiten hinzieht, bei denen der meiste platz am papier nicht genutzt wird.&lt;/p&gt;&lt;p&gt;im folgenden mache ich ein paar vorschläge, wie mit css (cascading style sheets) bei wenig aufwand ein gutes druckbild erzeugt werden kann.&lt;/p&gt;&lt;p&gt;&lt;h4&gt;keine frames&lt;/h4&gt;
der erste punkt bezieht sich auf die grundlegende architektur der web-seite. dabei sollte die verwendung von frames vermieden werden.&lt;br /&gt;speziell beim drucken führen frames zu problemen: entweder werden alle frames ausgedruckt, was papierverschwendung ist, da navigations-menüs etc. nicht benötigt werden oder die anwender/in muss genau darauf achten, welchen frame sie drucken will.&lt;br /&gt;(zudem sind frames auch in zusammenhang mit suchmaschinen ungeeignet, da oft nur teile einer seite gefunden und angezeigt werden.)&lt;/p&gt;&lt;p&gt;&lt;h4&gt;eigenes css für das drucken&lt;/h4&gt;
nun zu den dingen, die wir mit css erledigen können.&lt;br /&gt;dazu ist es erst einmal nötig, dass wir ein eigenes css-script für den ausdruck erstellen und in die html-seite einbauen. wichtig dabei ist, dass das druck-css &lt;strong&gt;nach&lt;/strong&gt; dem allgemeinen css angegeben wird und für das medium &quot;print&quot; definiert wird:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;css/allgemein.css&quot;&amp;gt;&lt;br /&gt;&amp;lt;link rel=&quot;stylesheet&quot; media=&quot;print&quot; href=&quot;css/druck.css&quot;&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/div&gt;
das druck.css muss nach dem allgemein.css kommen, damit wir dann allgemeine layout-eigenschaften für den ausdruck überschreiben können. eine sauberere aber aufwendigere lösung wäre die aufteilung in 3 css-dateien, eine die die anweisungen für alle medien (&quot;all&quot;) beinhaltet, eine die für das layout am bildschirm zuständig ist (media=&quot;screen&quot;) und eine die den ausdruck definiert.&lt;br /&gt;der einfachheit halber machen wir uns jedoch zu nutze, dass bei mehrmaliger definition einer css-eigenschaft jene verwendet wird, die zuletzt kommt. deshalb kommt druck.css nach allgemein.css und überschreibt nur im falle des druckens die nötigen css-anweisungen.&lt;/p&gt;&lt;p&gt;&lt;h4&gt;alles ausser dem eigentlichen inhalt ausblenden&lt;/h4&gt;
nun zur konkreten arbeit mit css:&lt;br /&gt;als anwender/in möchte ich nur den eigentlichen inhalt der aktuellen web-seite ausdrucken. somit will ich dinge wie navigations-menü, such-felder, news- oder andere hinweise nicht drucken.&lt;br /&gt;das können wir steuern, in dem wir alle bereiche, die nicht zum inhalt gehören, beim drucken nicht anzeigen.&lt;br /&gt;im druck.css definieren wir daher zum beispiel:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;#ContentLeft,&lt;br /&gt;#ContentRight,&lt;br /&gt;.navigatoin,&lt;br /&gt;.news {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;display: none;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;
wobei sie natürlich die ids oder class-names (ContentLeft, ContentRight, navigation, news) an ihre web-seite anpassen müssen.&lt;/p&gt;&lt;p&gt;&lt;h4&gt;content-bereich maximieren&lt;/h4&gt;
oft genügt es noch nicht, alles rundherum ausblenden. durch ein eventuell fixes layout hat der inhalt noch immer nicht mehr platz. dann ist es nötig, die css-eigenschaften für den content-bereich zu überschreiben. in welcher form hängt natürlich von ihrem layout ab, zum besipiel:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;#Content {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;width: 100%;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-left: 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;margin-right: 0;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;

&lt;h4&gt;kopfbereich verkleinern&lt;/h4&gt;
einen kopf (header) sollte die seite natürlich haben. anbieter/innen möchten hier ihr unternehmen präsentieren, anwender/innen möchten wissen, von wem die information stammt.&lt;br /&gt;der kopf muss am papier nicht so aussehen wie am bildschirm und manchmal macht es sinn, wenn wir den kopf-bereich der seite verkleinern, eventuell das logo kleiner ausdrucken, die schriftgröße minimieren.&lt;br /&gt;hier können wir ebenfalls die css-eigenschaften der allgemeinen css-datei überschreiben und so den kopf für den druck anpassen.&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;#Header{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;font-size: 1.5em;&lt;br /&gt;}&lt;br /&gt;#Header img {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;height: 2 em;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;
... und was sonst noch alles nötig ist, eventuell auch das ausblenden von verschiedenen inhalten im kopfbereich.&lt;/p&gt;&lt;p&gt;&lt;h4&gt;keine hintergrundfarbe und -bild&lt;/h4&gt;
ob der hintergrund mit ausgedruckt werden soll oder nicht lässt sich zwar im browser einstellen, aber warum soll sich die anwender/in darum kümmern müssen, wann sie umstellen muss und wann nicht. aus meiner sicht ist es service am kunden, wenn der ausdruck die farbpatronen der tintenstrahldrucker nicht unnötig leert. daher ausschalten von hintergrundfarbe und auch von hintergrundbildern, sofern sie nicht für den inhalt bedeutend sind.&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;body,&lt;br /&gt;#Content {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;background-color: #FFFFFF;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;background-image: none;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;

&lt;h4&gt;links / zitate&lt;/h4&gt;
angeregt durch einen kommentar von &quot;Oliver&quot; hier noch ein paar weitere hinweise:&lt;br /&gt;(an dieser stelle herzlichen dank für das qualifizierte feedback von oliver.)&lt;/p&gt;&lt;p&gt;stellen sie links in der webseite in einer anderen farbe dafür ohne unterstreichung dar, kann man diese bei einem schwaz-weiss-ausdruck nicht mehr erkennen. daher kann es gut sein, diese wieder unterstrichen darzustellen.&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;a {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;color: #000;text-decoration: underline&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;

des weiteren ist es natürlich am papier nicht möglich, den link anzuklicken. und da man nur den Text sieht, weiss man anhand des ausdrucks nicht mehr die adresse, auf die der link verweist. um die link-adresse auszugeben, bedienen wir uns eines css-pseudoelements namens &quot;:after&quot;. damit kann man nach einem html-element automatisch inhalte ausgeben (mit &quot;:before&quot; davor).&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;a {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;content: &quot; [&quot; attr(href) &quot;]&quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;background-color: inherit;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;color: #369;font-style: italic;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;
bewirkt nun, dass die linkadresse (das attribut &quot;href&quot;) nach dem link-text zwischen [ und ] kursiv ausgegeben wird.&lt;/p&gt;&lt;p&gt;für zitate, die sie in dieser form definieren&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;Zitat: &amp;lt;q cite=&quot;urheber des zitats&quot;&amp;gt;Das ist ein Zitat&amp;lt;/q&amp;gt;&lt;br /&gt;&lt;/div&gt;
gibt es die möglichkeit, den urheber bzw. die quelle des zitats auch auszugeben. dazu bedienen wir uns wieder des :after-pseudoelements und schränken den css-selektor auf alle &quot;q&quot; ein, die das attribute &quot;cite&quot; definieren:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;q[cite]:after {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;content:close-quote &quot; (Quelle: &quot; attr(cite) &quot;)&quot;;&lt;br /&gt;}&lt;br /&gt;&lt;/div&gt;

&lt;h4&gt;kommentare&lt;/h4&gt;
ich hoffe, die hinweise waren nützlich für sie, ich freue mich über weitere anregungen und vorschläge, die sie als kommentar hinterlassen können.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 03 Jun 2008 00:00:00 +0200</pubDate>
			
			
			<guid>http://www.ieko.at/artikel-drucken-mit-css/</guid>
		</item>
		
		<item>
			<title>groovy, dsl und templates</title>
			<link>http://www.ieko.at/groovy-dsl-und-templates/</link>
			<description>&lt;p&gt;&lt;h4&gt;groovy-dsl-tutorial&lt;/h4&gt;
im artikel &lt;a href=&quot;http://www.ieko.at/artikel-groovy-dsl/&quot;&gt;dsl mit groovy&lt;/a&gt; gaben wir anhand eines kleinen beispiels eine einführung in groovy-dsl. wir haben eine tabelle mit ihren spalten definiert und dann ein create-table-statement daraus generiert.&lt;/p&gt;&lt;p&gt;da es eine groovy-dsl einführung war, haben wir ein wichtiges prinzip der softwareentwicklung, nämlich die trennung von model und view, vernachlässigt. (zum erzeugen des create-statements hatten wir die create-funktionen im Table- und ColumnModel.) das möchten wir in diesem artikel nachholen.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;unser beispiel:&lt;/p&gt;&lt;p&gt;angenommen sie entwickeln eine datenbankanwendung mit hunderten von tabellen und eine anforderung ist, dass die anwendung mit unterschiedlichen datenbanken läuft. mit unserer bisherigen lösung müssten wir für jeden datenbankdialekt eine eigene create-funktion implementieren. da wir unser model aber nicht mit noch mehr code überfrachten wollen, wählen wir einen anderen weg: groovy-temples. (anmerkung: wir gehen der einfachheit halber davon aus, dass es eine reine sql-anwendung ist und kein orm-framework verwendet wird)&lt;/p&gt;&lt;p&gt;groovy besitzt ein template framework, und mit der SimpleTemplateEngine wird es uns leicht gemacht, vorlagen für die create-statements je datenbank-typ zu erstellen und damit die create-statements zu generieren.&lt;/p&gt;&lt;p&gt;&lt;h4&gt;vorbereitung&lt;/h4&gt;
wir verwenden die groovy-programme aus unserem vorigen artikel (&lt;a href=&quot;http://www.ieko.at/artikel-groovy-dsl/&quot;&gt;dsl mit groovy&lt;/a&gt;).&lt;br /&gt;als erstes bereinigen wir unsere model-klassen und entfernen die create-funktionen.&lt;br /&gt;zur besseren übersicht hier noch einmal die beiden klassen:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;class TableModel {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Name der Tabelle&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;String name&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Liste der Columns&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ArrayList&amp;lt;ColumnModel&amp;gt; columns = new ArrayList&amp;lt;ColumnModel&amp;gt;()&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;class ColumnModel {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  * Tabelle, zu der diese Column gehört&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  TableModel table&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  * name der column&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; String name&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  * datentyp&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; String datatype&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; * not null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;boolean notnull&lt;br /&gt;}&lt;/div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;h4&gt;unsere templates&lt;/h4&gt;
unser erstes template soll ein create-table-statement für eine MySql-datenbank sein, und so aussehen:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;create table test (&lt;br /&gt;    id int not null,&lt;br /&gt;    name text&lt;br /&gt;)&lt;br /&gt;engine = InnoDB;&lt;br /&gt;&lt;/div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;einem groovy-template werden daten übergeben, die innerhalb des templates verwendet werden können.&lt;br /&gt;in unserem fall übergeben wir ein TableModel-objekt mit dem namen &quot;table&quot;. (code siehe weiter unten).&lt;/p&gt;&lt;p&gt;im template selbst können wir groovy-code ausführen:&lt;br /&gt;- ${xxx}: mit dieser syntax wird der wert, den xxx liefert, im template ausgegeben&lt;br /&gt;- &amp;lt;% xxx %&amp;gt;: hiermit wird xxx als groovy-code ins template eingebettet&lt;br /&gt;zum besseren verständnis verwenden wir in unserem ersten template beide varianten.&lt;/p&gt;&lt;p&gt;unser template ist folgendermaßen strukturiert:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;01 create table ${table.name} (&lt;br /&gt;02    &amp;lt;% table.columns.eachWithIndex{ col, i -&amp;gt; %&amp;gt;&lt;br /&gt;03        ${col.name} ${col.datatype} &amp;lt;% if (col.notnull) { %&amp;gt;not null&amp;lt;% } %&amp;gt;&lt;br /&gt;04        &amp;lt;% if (i+1 &amp;lt; table.columns.size()) { %&amp;gt;,&amp;lt;% } %&amp;gt;&lt;br /&gt;05    &amp;lt;% } %&amp;gt;&lt;br /&gt;06  )&lt;br /&gt;07  engine = InnoDB;&lt;br /&gt;&lt;/div&gt;
nun die erklärung zu den einzelnen zeilen:&lt;br /&gt;01: &quot;create table&quot; ist ein fixer text, mit &quot;${table.name}&quot; wird das &quot;name&quot;-property aus unserem table-objekt ausgegeben&lt;br /&gt;02: hier wird mittels der &quot;&amp;lt;% xxx %&amp;gt;&quot;-syntax groovy-code eingebettet: es wird über alle columns im table-objekt iteriert. (mit index)&lt;br /&gt;03: dieser teil wird für jede column ausgeführt und gibt column.name, column.type und &quot;not null&quot; wenn column.notnull == true&lt;br /&gt;04: dieser teil dient nur dazu, um nach jeder außer der letzten column ein komma (&quot;,&quot;) auszugeben&lt;br /&gt;05: das hier ist das ende der &quot;table.columns.eachWithIndex { col, i -&amp;gt; &quot;  anweisung. d.h. der each-loop ist hier beendet&lt;br /&gt;06 und 07: geben nur mehr einen fixen text aus.&lt;/p&gt;&lt;p&gt;das template-code wurde nur zwecks erklärungen in mehrere zeilen aufgeteilt. würden wir das template wie hier verwenden kämen zu viele zeilenumbrüche zustande, da alle zeilenumbrüche auserhalb von groovy-code ausgegeben werden.&lt;/p&gt;&lt;p&gt;daher zusammenfassend unser endgültiges MySql-template (gespeichert in der datei MySql.tpl):&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;create table ${table.name} (&amp;lt;% table.columns.eachWithIndex{ col, i -&amp;gt; %&amp;gt;&lt;br /&gt;    ${col.name} ${col.datatype} &amp;lt;% if (col.notnull) { %&amp;gt;not null&amp;lt;% } %&amp;gt;&amp;lt;% if (i+1 &amp;lt; table.columns.size()) { %&amp;gt;,&amp;lt;% } %&amp;gt;&amp;lt;% } %&amp;gt;&lt;br /&gt;)&lt;br /&gt;engine = InnoDB;&lt;br /&gt;&lt;/div&gt;

analog können wir auch für Oracle ein template schreiben (Oracle.tpl):&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;create table ${table.name} (&amp;lt;% table.columns.eachWithIndex{ col, i -&amp;gt; %&amp;gt;&lt;br /&gt;    ${col.name} ${col.datatype==&quot;text&quot;?&quot;clob&quot;:col.datatype} &amp;lt;% if (col.notnull) { %&amp;gt;not null&amp;lt;% } %&amp;gt;&amp;lt;% if (i+1 &amp;lt; table.columns.size()) { %&amp;gt;,&amp;lt;% } %&amp;gt;&amp;lt;% } %&amp;gt;&lt;br /&gt;);&lt;br /&gt;&lt;/div&gt;
hier ist folgender abschnitt erklärungsbedürftig:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;${col.datatype==&quot;text&quot;?&quot;clob&quot;:col.datatype}&lt;br /&gt;&lt;/div&gt;
da es in Oracle den datentyp &quot;text&quot; nicht gibt, wird statt &quot;text&quot; &quot;clob&quot; (character-large-object) als datentyp ausgegeben.&lt;br /&gt;(anmerkung: in einer realen anwendung würde man den datentyp nicht als text sondern als enum definieren und jeweils den der datenbank entsprechenden datentyp ermitteln.)&lt;/p&gt;&lt;p&gt;&lt;h4&gt;SimpleTemplateEngine&lt;/h4&gt;
wir haben unsere templates definiert, nun wollen wir sie auch verwenden:&lt;/p&gt;&lt;p&gt;dazu bietet uns groovy mit der SimpleTemplateEngine die einfachste möglichkeit.&lt;br /&gt;hier die nötigen schritte:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;import groovy.text.SimpleTemplateEngine&lt;/p&gt;&lt;p&gt;def engine = new SimpleTemplateEngine()&lt;/div&gt;
erzeugen einer engine-instanz&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;def template = engine.createTemplate(template)&lt;br /&gt;&lt;/div&gt;
erzeugen einer template-instanz. template kann dabei ein String, ein File, eine URL oder ein beliebiger Reader sein&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;template = template.build(model)&lt;br /&gt;&lt;/div&gt;
erzeugen anhand der im model übergebenen daten (als Map) das ergebnis&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;def result = template.toString()&lt;br /&gt;&lt;/div&gt;
liest das ergebnis als String aus&lt;/p&gt;&lt;p&gt;anmerkung: der einfachheit halber kann man die createTempate() und build() - schritte zusammenfassen:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;def template = engine.createTemplate(template).build(model)&lt;br /&gt;&lt;/div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;für unser beispiel ergibt sich damit:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;import groovy.text.SimpleTemplateEngine&lt;/p&gt;&lt;p&gt;def builder = new TableBuilder();&lt;/p&gt;&lt;p&gt;def table = builder.table(&quot;test&quot;) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;column &quot;id&quot;, datatype: &quot;int&quot;, notnull: true&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;column &quot;name&quot;, datatype: &quot;text&quot;&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;// Ausgabe&lt;br /&gt;def engine = new SimpleTemplateEngine()&lt;/p&gt;&lt;p&gt;// Ausgabe für MySql&lt;br /&gt;def template = engine.createTemplate(new File('MySql.tpl')).&lt;br /&gt;    make([table: table])&lt;br /&gt;println &quot;MySql-Statement:&quot;&lt;br /&gt;println template.toString()&lt;/p&gt;&lt;p&gt;// Ausgabe für Oracle&lt;br /&gt;template = engine.createTemplate(new File('Oracle.tpl')).&lt;br /&gt;    make([table: table])&lt;br /&gt;println &quot;Oracle-Statement:&quot;&lt;br /&gt;println template.toString()&lt;/div&gt;
zuerst erstellen wir mit der dsl vom vorigen artikel eine tabellen-definition, die in der variablen &quot;table&quot; gespeichert wid.&lt;br /&gt;danach erzeugen wir, wie oben beschrieben eine template-engine, und verwenden einmal das MySql-template und danach das Oracle-template.&lt;br /&gt;als model übergeben wir der build-funktion die Map [table: table] (1. &quot;table&quot; ist die variable, wie sie im template verwendet wird, 2. &quot;table&quot; ist unsere lokale table-variable, die wir am anfang erzeugt haben.)&lt;br /&gt;anstatt das ergebnis mit println an die konsole auszugeben könnten wir natürlich das ergebnis in .sql-dateien schreiben und es dann in der datenbank ausführen.&lt;/p&gt;&lt;p&gt;hier das erzielte ergebnis:&lt;br /&gt;&lt;div class=&quot;codesnippet&quot;&gt;MySql-Statement:&lt;br /&gt;create table test (&lt;br /&gt;    id int not null,&lt;br /&gt;    name text&lt;br /&gt;)&lt;br /&gt;engine = InnoDB;&lt;/p&gt;&lt;p&gt;Oracle-Statement:&lt;br /&gt;create table test (&lt;br /&gt;    id int not null,&lt;br /&gt;    name clob&lt;br /&gt;);&lt;/p&gt;&lt;p&gt;create table test (&lt;br /&gt;    id int not null,&lt;br /&gt;    name text&lt;br /&gt;);&lt;/div&gt;


die source-files zu diesem artikel können sie &lt;a href=&quot;http://www.ieko.at/assets/downloads/TableBuilder2.zip&quot;&gt;hier downloaden&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;danke für ihre aufmerksamkeit,&lt;br /&gt;wir feuen uns über kommentare und anregungen.&lt;/p&gt;</description>
			<pubDate>Tue, 17 Nov 2009 00:00:00 +0100</pubDate>
			
			
			<guid>http://www.ieko.at/groovy-dsl-und-templates/</guid>
		</item>
		

	</channel>
</rss>

