001: /**
002: * Diese Klasse stellt folgende Funktionalitaeten zur Verfuegung:
003: *
004: * 1. Die in einem Template vorkommenden TKTags werden gestzt
005: *
006: * 2. Der Syntaxbaum eines Templates wird erzeugt
007: *
008: * 3. Der Syntaxbaum eines Templates wird ausgelesen und je nach
009: * gesetzten Tags aus TKTemplateData als String generiert,
010: * Dieser enthaelt eine fertige Seite, die an den Browser geschickt #
011: * werden kann.
012: *
013: * 4. Der Syntaxbaum eines Templates wird in eine Datenbank abgelegt
014: *
015: * 5. Das in der datenbank abgelegte Template wird aus der Datenbank ausgelesen
016: * und ein Syntaxbaum wird generiert
017: */package com.teamkonzept.lib;
018:
019: import java.io.*;
020: import com.oroinc.text.regex.*;
021: import javax.servlet.http.HttpServletRequest;
022: import com.teamkonzept.lib.TKException;
023: import com.teamkonzept.lib.templates.*;
024: import org.apache.log4j.Category;
025:
026: /**
027: * Die Klasse TKTemplate stellt Methoden fuer die Generierung eines Templates
028: * zur Verfuegung
029: * @author $Author: sebastian $
030: * @version $Revision: 1.24 $
031: */
032: public class TKTemplate implements TemplateBasic, TemplateTypes {
033: private static final Category CAT = Category
034: .getInstance(TKTemplate.class);
035:
036: static protected final String PAT_PRETAG = "TK[_:]";
037: static protected final String PAT_REFTAG = "(SRC|HREF|ACTION|BACKGROUND)";
038:
039: static Pattern patCopyRight;
040: static Pattern patCleanEmpty;
041: static Pattern patBaseURL;
042: static public Pattern patTKTag; // REDESIGN: public ist nötig weil TKTemplateSyntax das Pattern braucht
043:
044: static boolean initialized = false;
045:
046: private static String NEW_LINE = System
047: .getProperty("line.separator");
048:
049: private String currAppName = "TKTemplate";
050:
051: /** Syntax des Templates */
052: public TKTemplateSyntax syntax = null;
053:
054: /** Daten für das Template */
055: public TKTemplateData td = null;
056:
057: /** das expandierte Template */
058: public String text;
059:
060: /**
061: Returns a new syntax instance associated to the template.
062: Overwritten by TLKHTMLTemplate.
063: */
064: public TKTemplateSyntax newSyntax() {
065: return new TKTemplateSyntax();
066: }
067:
068: /**
069: Returns a new syntax instance associated to the template.
070: Overwritten by TLKHTMLTemplate.
071: */
072: public TKTemplateSyntax newSyntax(Pattern patTKTag) {
073: return new TKTemplateSyntax(patTKTag);
074: }
075:
076: public String getType() {
077: return TK_TEMPLATE;
078: }
079:
080: /**
081: * Konstruktor1
082: * Ein File-Objekt wird erzeugt und an Konstruktor2 uebergeben
083: *
084: * @param String filename, Pfad und Name des Templates
085: */
086: public TKTemplate(String location)
087: throws TKTemplateSyntaxException, FileNotFoundException {
088: init(location);
089: }
090:
091: /**
092: * Konstruktor3
093: * Durch den Aufruf der statischen Methode init() werden Pattern fuer die
094: * spaetere Patternsuche/ersetzung definiert und global zur Verfuegung gestellt.
095: *
096: *@param ts, Ein TKTemplateSyntax-Objekt
097: *@param filename, das template als File-Objekt
098: */
099: public TKTemplate(TKTemplateSyntax ts/*, File templateFile*/) {
100: init(ts);
101: }
102:
103: public DOMTemplateData getDOMData() {
104: return td.getDOMData();
105: }
106:
107: protected void init(TKTemplateSyntax ts) {
108: if (!initialized)
109: initStatic(); // ???-alex
110: syntax = ts;
111: td = ts.getNewTemplateData();
112: }
113:
114: protected void init(String location)
115: throws TKTemplateSyntaxException, FileNotFoundException {
116: init(TKTemplateCache.getSyntax(location, this ));
117: }
118:
119: /**
120: * Ein TKListIterator wird gesetzt. Das TKListIterator-Objekt wird der
121: * Variablen listIterator der Klasse TKTemplateData zugewiesen.
122: * Aufruf dieser Methode: TemlateObjekt.setListIterator(TKListIteratorObject);
123: *
124: * @param aIterator, Objekt vom typ TKLIstIterator
125: */
126: public void setListIterator(TKListIterator aIterator) {
127: td.setListIterator(aIterator);
128: }
129:
130: /**
131: * Ein TKListIterator-Objekt, welches in der Klasse TKTemplateData existiert,
132: * wird zurueckgegeben.
133: * Aufruf dieser Methode: TemlateObjekt.getListIterator();
134: *
135: * @return ein Objekt vom Typ TKListIterator
136: */
137: public TKListIterator getListIterator() {
138: return td.getListIterator();
139: }
140:
141: // nur fuer jsp wichtig !
142: public void setOriginalRequest(HttpServletRequest request) {
143: }
144:
145: /**
146: in nested lists, there is sometimes the neccessarity to pass some data from
147: the implementation of the outer iterator to the implementation of the inner
148: iterator. this can be done by the enumeration context. the implementation
149: of the list-tags ensures, that the enumerationContext of a call of the
150: apply-method of the outer iterator gets passed to all calls of the
151: corresponding calls of the inner iterator.
152: */
153:
154: public void setEnumerationContext(Object key, Object value) {
155: td.setEnumerationContext(key, value);
156: }
157:
158: /**
159: @see setEnumerationContext
160: */
161:
162: public Object getEnumerationContext(Object key) {
163: return td.getEnumerationContext(key);
164: }
165:
166: /**
167: * Ein Hash fuer die Ersetzung wird der Variable subst der Klasse
168: * TKTemplateData uebergeben.
169: *
170: * @param ein Objekt vom Typ TKHashtable, der die zu ersetzenden
171: * Informationen enthaelt
172: */
173: public void set(TKHashtable aSubst) {
174: td.mergeVariables(aSubst);
175: }
176:
177: /**
178: * Ein Hash fuer die Ersetzung wird fuer die Klasse TKTemplateData
179: * erzeugt und in diesen eingefuegt.
180: *
181: * @param String key, ein Schluessel
182: * @param Object val, die Information zum Schluessel
183: */
184: public void set(String key, Object val) {
185: td.setLocalVariable(key, val);
186: }
187:
188: /**
189: * An einem Hash der Klasse TKTemplateData fuer die Ersetzung in einem
190: * bestimmten Template wird ein weiterer Hash angehaengt.
191: * Die TKTags werden im Template durch die Values ersetzt.
192: *
193: * Aufruf: templateObject.addSubst(TKHashtableObject)
194: *
195: * @param TKHashtable aSubst, der zu konkatinierende Hash
196: */
197: public void add(TKHashtable aSubst) {
198: td.concatVariables(aSubst);
199: }
200:
201: /**
202: * An einem Hash fuer die Ersetzung in einem bestimmten Template wird ein
203: * weitereres Element angehaengt. Die TKTags werden im Template durch die
204: * Values ersetzt.
205: * Aufruf: templateObject.addSubst("Schluessel",Object)
206: *
207: * @param String key, ein Schluessel, z.B. der zu ersetzende TKTag
208: * @param Object val, der Wert zu dem Schuessel, durch den der TKTag
209: ersetzt werden soll
210: */
211: public void add(String key, Object val) {
212: td.extendVariable(key, val);
213: }
214:
215: /**
216: * Das substituierte Template wird als String zuueckgegeben.
217: * Hierfuer muss die Instanzvariable "text" mit dem Text eines Templates
218: * zuvor gefuellt werden. Dies geschieht, indem die Tags im Template zuerst
219: * substituiert werden.
220: *
221: * Bsp. Reihenfolge der Aufrufe:
222: * TKTemplateObject.doTagSubstitution();
223: * TKTemplateObject.doCleanup();
224: * TKTemplateObject.getText();
225: *
226: * @return einen String des substituierten Templates
227: */
228:
229: public String getText() {
230: return text;
231: }
232:
233: /**
234: * Die Instanzvariable ist mit "TKTemplate" initialisiert
235: *
236: * @return einen String der Applikation.
237: */
238: public String setAppName(String appName) {
239: return currAppName = appName;
240: }
241:
242: /**
243: * Das Template wird in den PrintStream geschrieben.
244: * Hierfuer muss die Instanzvariable "text" mit dem Text eines Templates
245: * zuvor gefuellt werden. Dies geschieht, indem die Tags im Template zuerst
246: * substituiert werden.
247: *
248: * Bsp. Reihenfolge der Aufrufe:
249: * TKTemplateObject.doTagSubstitution();
250: * TKTemplateObject.doCleanup();
251: * TKTemplateObject.printTemplate();
252: */
253: public void printTemplate(PrintStream out) {
254: out.print(text);
255: }
256:
257: /**
258: * Das Template wird in den Writer geschrieben.
259: * Hierfuer muss die Instanzvariable "text" mit dem Text eines Templates
260: * zuvor gefuellt werden. Dies geschieht, indem die Tags im Template zuerst
261: * substituiert werden.
262: *
263: * Bsp. Reihenfolge der Aufrufe:
264: * TKTemplateObject.doTagSubstitution();
265: * TKTemplateObject.doCleanup();
266: * TKTemplateObject.printTemplate();
267: */
268: public void printTemplate(Writer writer) throws IOException {
269: writer.write(text);
270: }
271:
272: /**
273: * Das Template wird auf stdout geschrieben.
274: * Hierfuer muss die Instanzvariable "text" mit dem Text eines Templates
275: * zuvor gefuellt werden. Dies geschieht, indem die Tags im Template zuerst
276: * substituiert werden.
277: *
278: * Bsp. Reihenfolge der Aufrufe:
279: * TKTemplateObject.doTagSubstitution();
280: * TKTemplateObject.doCleanup();
281: * TKTemplateObject.printTemplate();
282: */
283: public void printTemplate() {
284: printTemplate(System.out);
285: }
286:
287: /**
288: * Das substituierte Template wird in ein File geschrieben werden.
289: * Hierfuer muss die Instanzvariable "text" mit dem Text eines Templates
290: * zuvor gefuellt werden. Dies geschieht, indem die Tags im Template zuerst
291: * substituiert werden.
292: *
293: * Bsp. Reihenfolge der Aufrufe:
294: * TKTemplateObject.doTagSubstitution();
295: * TKTemplateObject.doCleanup();
296: * TKTemplateObject.printTemplate(String file)
297: *
298: * @param String file, der Filename des zu speichernden templates
299: */
300: public void printTemplate(String file) throws IOException {
301: FileOutputStream f = new FileOutputStream(file);
302: PrintStream out = new PrintStream(f);
303:
304: printTemplate(out);
305: }
306:
307: /**
308: * Durch den Aufruf der Methode doMainSubstitution enthaelt die
309: * Instanzvariable "text" das Template mit den substituierten TKTags.
310: * Die nicht vollstaendigen Pfade werden ersetzt.
311: *
312: * Die URL-Base ist gestzt, wenn Images ausserhalb des CGI-Verzeichnisses
313: * abgelegt sind. Fuer diese Bilder muss der vollstaendige Pfad im
314: * Template gesetzt werden.
315: */
316: public void doTagSubstitution() throws TKTemplateSyntaxException {
317: doMainSubstitutions();
318: }
319:
320: /**
321: * Die Instanzvariable "text" enthaelt das Template mit den
322: * substituierten TKTags
323: *
324: * 1. TKTemplateData-Objekt.prepareApply() => Bearbeitung der Hashes
325: * fuer folgende Tags: if,check,select, case
326: * 2. Die Variable text enthaelt das generierte Template
327: */
328: public void doMainSubstitutions() throws TKTemplateSyntaxException {
329: td.prepareApply();
330:
331: //OLD version using 'String's
332: // text = syntax.apply( td );
333: //OLD
334:
335: //NEW version using Writer
336: try {
337: StringWriter writer = new StringWriter();
338: syntax.apply(td, writer);
339: text = writer.toString();
340: } catch (IOException e) {
341: CAT
342: .error(
343: "Catched IOException in TKTemplate.doMainSubstition() thrown by StringWriter",
344: e);
345: }
346: }
347:
348: /**
349: * Nachdem alle Tags ersetzt worden sind, wird das Template gsaeubert,
350: * so dass nur noch regulaere Tags im Template existieren. Danach kann das
351: * Template ausgegeben werden.
352: *
353: * 1.Template-Objekt.doTagSubstitution()
354: * 2.Template-Objekt.doCleanup()
355: * 3.Template-Objekt.printTemplate()
356: */
357: public void doCleanup() {
358: text = Util.substitute(TKReg.getMatcher(), patCleanEmpty,
359: NEW_LINE, text, Util.SUBSTITUTE_ALL);
360: }
361:
362: /**
363: * Pattern werden fuer die spaetere Patternsuche/ersetzung definiert und
364: * global zur Verfuegung gestellt.
365: */
366: static void initStatic() {
367: if (initialized)
368: return;
369:
370: PatternCompiler compiler = TKReg.getCompiler();
371:
372: try {
373: patCopyRight = compiler.compile("<HTML>",
374: Perl5Compiler.CASE_INSENSITIVE_MASK);
375: patBaseURL = compiler.compile(" " + PAT_REFTAG
376: + "\\s*\\=\\s*\"(?!(/|#|\\w+?(:|:)))",
377: Perl5Compiler.CASE_INSENSITIVE_MASK);
378: patTKTag = compiler.compile("</?" + PAT_PRETAG,
379: Perl5Compiler.CASE_INSENSITIVE_MASK);
380: patCleanEmpty = compiler.compile(NEW_LINE + "\\s*"
381: + NEW_LINE);
382: } catch (MalformedPatternException e) {
383: CAT.error("Bad pattern.", e);
384: }
385:
386: initialized = true;
387: }
388:
389: static {
390: initStatic();
391: }
392: }
|