KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > teamkonzept > lib > templates > TKTemplateSyntax


1 package com.teamkonzept.lib.templates;
2
3 import java.io.*;
4 import java.util.*;
5 import com.oroinc.text.regex.*;
6
7 import com.teamkonzept.lib.*;
8
9 /**
10  * Der Syntaxbaum eines Templates
11  * @author $Author: alex $
12  * @version $Revision: 1.19 $
13  */

14 public class TKTemplateSyntax {
15
16     static protected String JavaDoc patListMarker = "LIST";
17     static protected String JavaDoc patTagDefinitionMarker = "TAGDEF";
18     static protected String JavaDoc patAtomTagMarker = "ATAG";
19     static protected String JavaDoc patTagMarker = "TAG";
20     static protected String JavaDoc patNoExpandMarker = "NOEXPAND";
21     static protected String JavaDoc patTrimMarker = "TRIM";
22     static protected String JavaDoc patCaseMarker = "CASE";
23     static protected String JavaDoc patNotMarker = "NOT";
24     static protected String JavaDoc patIfMarker = "IF";
25     static protected String JavaDoc patElseMarker = "ELSE";
26     static protected String JavaDoc patElsIfMarker = "ELSIF";
27     static protected String JavaDoc patIncludeMarker = "INCLUDE";
28     static protected String JavaDoc patSwitchMarker = "SWITCH";
29     static protected String JavaDoc patScopeMarker = "SCOPE";
30     static protected String JavaDoc patIgnoreMarker = "IGNORE";
31     static protected String JavaDoc patSetMarker = "SET";
32     static protected String JavaDoc patSetLocalMarker = "SETLOCAL";
33     static protected String JavaDoc patLocalMarker = "LOCAL";
34     static protected String JavaDoc patEvalMarker = "EVAL";
35     static protected String JavaDoc patExpressionMarker = "EXPRESSION";
36     static protected String JavaDoc patWhileMarker = "WHILE";
37     static protected String JavaDoc patExistsMarker = "EXISTS";
38     static protected String JavaDoc patDateMarker = "DATE";
39     static protected String JavaDoc patLanguageMarker = "LANG";
40     
41     static public final int MAX_TAG_TYPE = 100;
42     
43     public boolean applyConverter = false;
44     public boolean isSubSyntax = false;
45
46     // public static final String CURR_YEAR = Integer.toString( (new java.util.Date()).getYear()+1900 );
47

48     private static final int VECTOR_SIZE = 100;
49     
50     /** die einzelnen Textabschnitte im Template */
51     protected TKVector textChunks = new TKVector( VECTOR_SIZE, VECTOR_SIZE );
52     
53     /** die Tags eines Templates */
54     public TKVector tags = new TKVector( VECTOR_SIZE, VECTOR_SIZE ); // REDESIGN: Wird von anderen Klassen gebraucht
55

56     /** Die Quelle aus der das Template stammt - URL Format ? */
57     protected String JavaDoc source = "";
58     
59     private Pattern patTKTag = TKTemplate.patTKTag;
60     
61     public Pattern getTKTag()
62     {
63         return patTKTag;
64     }
65     
66     protected void setTKTag(Pattern pat)
67     {
68         patTKTag = pat;
69     }
70     
71     public final String JavaDoc getSource()
72     {
73         return source;
74     }
75     
76     public TKTemplate getNewTemplate()
77     {
78         return new TKTemplate( this );
79     }
80     
81     public TKTemplateData getNewTemplateData()
82     {
83         return new TKTemplateData();
84     }
85     
86     public String JavaDoc getDefaultEncoding()
87     {
88         return TKAnsiConverter.CONV_ID;
89     }
90     
91     public String JavaDoc getDefaultEncoding (TKTemplateData td)
92     {
93         String JavaDoc encoding = td == null ? null :
94             (String JavaDoc) td.getVariable("TEMPLATE_SYNTAX_DEFAULT_ENCODING");
95             
96         return encoding == null ? getDefaultEncoding() : encoding;
97     }
98     
99         
100     /**
101     */

102     public TKTemplateSyntax()
103     {
104     }
105     
106     /**
107     */

108     public TKTemplateSyntax(Pattern patTKTag)
109     {
110         if (patTKTag != null) this.patTKTag = patTKTag;
111     }
112     
113     /**
114      * Konstruktor1
115      * Konstrukror2 wird aufgerufen
116      *
117      * @param String text, das vollstaendige Template als String
118      */

119     public TKTemplateSyntax( String JavaDoc text, String JavaDoc source ) throws TKTemplateSyntaxException
120     {
121         init( text, source );
122     }
123     
124     public TKTemplateSyntax( String JavaDoc text, String JavaDoc source, Pattern patTKTag ) throws TKTemplateSyntaxException
125     {
126         this.patTKTag = patTKTag;
127         init( text, source );
128     }
129     
130     public TKTemplateSyntax( String JavaDoc text, String JavaDoc source, boolean applyConverter ) throws TKTemplateSyntaxException
131     {
132         this.applyConverter = applyConverter;
133         init( text, source );
134     }
135     
136     /**
137         erzeugt neues TKTemplateSyntax Objekt und läßt es gleich parsen
138         @param text der zu parsende Text
139         @param source Quelle des textes
140         @return ein neues TKTemplateSyntax Objekt
141     */

142     public TKTemplateSyntax newChild( String JavaDoc text, String JavaDoc source) throws TKTemplateSyntaxException
143     {
144         TKTemplateSyntax result = newChild();
145         result.init( text, source );
146         return result;
147     }
148     
149     /**
150         erzeugt eine neues TKTemplateSyntaxObjekt (entsprechend der Hierarchie)
151         und kopiert die entsprechenden Member
152         @return ein neues TKTemplateSyntax Objekt
153     */

154     public TKTemplateSyntax newChild()
155     {
156         try {
157             TKTemplateSyntax syntax = (TKTemplateSyntax) getClass().newInstance();
158             syntax.applyConverter = this.applyConverter;
159             syntax.isSubSyntax = this.isSubSyntax;
160             syntax.setTKTag(patTKTag);
161             return syntax;
162         }
163         catch( InstantiationException JavaDoc e ) {
164             throw new InstantiationError JavaDoc( e.getMessage() );
165         }
166         catch( IllegalAccessException JavaDoc e ) {
167             throw new IllegalAccessError JavaDoc( e.getMessage() );
168         }
169     }
170     
171     /**
172         erzeugt neues TKTemplateSyntax Objekt und läßt es gleich parsen
173         @param text der zu parsende Text
174         @param source Quelle des textes
175         @param hasSubTags
176         @return ein neues TKTemplateSyntax Objekt
177     */

178     public TKTemplateSyntax newChild( String JavaDoc text, String JavaDoc source, boolean hasSubTags) throws TKTemplateSyntaxException
179     {
180         TKTemplateSyntax result = newChild();
181         result.isSubSyntax = hasSubTags;
182         result.init( text, source );
183         return result;
184     }
185     
186         public TKTemplateSyntax newChild( PatternMatcherInput matcherInput, String JavaDoc source ) throws TKTemplateSyntaxException
187     {
188         TKTemplateSyntax result = newChild();
189         result.init( matcherInput, source );
190         return result;
191     }
192
193     /**
194      * Konstruktor2
195      * Der uebergebene String wird Tag fuer Tag bearbeitet. Wird ein Tag gefunden,
196      * so wird das entsprechende Tag-Objekt erzeugt. Dieses Tag kann wiederum Syntaxobjekte
197      * beinhalten, so das auch dieses Syntaxobjekte erzeugen muessen, die dann
198      * die Kinder des zuvorigen Syntaxobjektes bilden. Zu jedem Syntaxobjekt werden
199      * der zugehoerige Text gespeichert.
200      * Hierdurch wird eine rekursive Datenstruktur aufgebaut, welche es ermoeglicht,
201      * ein Template exakt in einer Objekthierachie wiederzuspiegeln.
202      *
203      * DIE PATTERN:
204      * patPreTag = "TK_";
205      * String patRefTag = "(SRC|HREF|ACTION|BACKGROUND)";
206      * patCopyRight = compiler.compile( "<HTML>", Perl5Compiler.CASE_INSENSITIVE_MASK );
207      * patBaseURL = compiler.compile(" "+patRefTag+"\\s*\\=\\s*\"(?!(/|#|\\w+?(:|&#58)))", Perl5Compiler.CASE_INSENSITIVE_MASK);
208      * patTKTag = compiler.compile("</?"+patPreTag, Perl5Compiler.CASE_INSENSITIVE_MASK);
209      * patCleanEmpty = compiler.compile("\n\\s*\n");
210      *
211      *
212      * @param PatternMatcherInput matcherInput, ist der umgewandelte
213      * String des Templates als Text
214      */

215     public TKTemplateSyntax( PatternMatcherInput matcherInput, String JavaDoc source ) throws TKTemplateSyntaxException
216     {
217         init( matcherInput, source );
218     }
219         
220     /**
221         Hier werden ggf. Escape-Zeichen aus Tag-Parametern abgefiltert (im SubSyntax-Context)
222     */

223     public String JavaDoc checkForSubSyntaxChunk (String JavaDoc chunk) {
224     
225         if (!isSubSyntax || (chunk == null)) return chunk;
226
227         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
228         
229         int pos = 0;
230         while (pos < chunk.length()) {
231         
232             char chr = chunk.charAt (pos++);
233
234             if (chr == '\\') {
235
236                 if (pos+1 < chunk.length()) buf.append (chunk.charAt (pos++));
237                 else buf.append (chr);
238
239             } else buf.append (chr);
240         }
241
242         return buf.toString();
243     }
244     
245     public void init( String JavaDoc _text, String JavaDoc source ) throws TKTemplateSyntaxException
246     {
247         init( new PatternMatcherInput( _text ), source );
248     }
249
250     /**
251         Parsiert Datenquelle und erzeugt Syntaxbaum
252         @param matcherInput Datenquelle für den Pattern Matcher
253         @param source Name der Datenquelle (URL?)
254     */

255     private void init ( PatternMatcherInput matcherInput, String JavaDoc source ) throws TKTemplateSyntaxException
256     {
257         this.source = source;
258         
259         PatternMatcher matcher = TKReg.getMatcher();
260         
261         int lastPos = matcherInput.getCurrentOffset();
262         //---- Solange ein <TK_ oder </TK_ vorhanden ist befindet => weiter ----//
263
while( matcher.contains( matcherInput, patTKTag ) ) {
264
265             //---- match enthaelt den neachsten Pattern: <TK_ oder </TK_ ----//
266
MatchResult match = matcher.getMatch();
267
268             //---- Text zwischen letzter Position und naechstem TK_Tag ----//
269
String JavaDoc newText = matcherInput.substring( lastPos, match.beginOffset(0) );
270
271             //---- Text zwischen den TK-Tags ----//
272
textChunks.addElement( checkForSubSyntaxChunk(newText) );
273
274             //---- EIN aktuelles TK-Tag Objekt wird erzeugt, welches wiederum ----//
275
//---- ein Syntax-Objekt erzeugt ----//
276
TKTag currTag = newTag( matcherInput, match );
277             tags.addElement( currTag );
278             lastPos = matcherInput.getCurrentOffset();
279
280             //---- Abbruchbedingung für rekursive Aufrufe//
281
if( currTag instanceof TKEndTag ) return;
282         }
283         textChunks.addElement( matcherInput.substring( lastPos, matcherInput.getEndOffset() ) );
284     }
285
286     /**
287         codiert Textchunks
288         @param chunk der zu konvertierende Text
289         @param ed hält das Encoding als Template Variable
290     */

291     private String JavaDoc applyConverter (String JavaDoc chunk, TKTemplateData ed) throws TKTemplateSyntaxException {
292
293         if (!applyConverter) return chunk;
294
295         String JavaDoc encoding = getDefaultEncoding(ed);
296
297         TKConverter encoder = TKConverter.getConverter( encoding );
298         if( encoder == null ) {
299                 throw new Error JavaDoc("missing converter for encoding "+encoding);
300         }
301
302         String JavaDoc result = new String JavaDoc (encoder.stringToBytes (chunk),0);
303         
304         return result;
305     }
306
307     /**
308      * 1.Schritt zur TemplateGenerierung
309      *
310      * @param TKTemplateData ed
311      * @return das generierte Template als String
312      */

313     public String JavaDoc apply( TKTemplateData ed ) throws TKTemplateSyntaxException
314     {
315         int nText = textChunks.size();
316         int nTags = tags.size();
317                 
318         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
319         int i=0;
320
321         if(tags != null) {
322             for( ; i < nTags; i++ ) {
323
324                 result.append (applyConverter ((String JavaDoc) textChunks.elementAt (i),ed));
325                 
326                 //---- Die apply-Methode des jeweiligen TKTag-Objekts wird aufgerufen ----//
327
//---- welche wiederum diese apply-Methode aufruft ----//
328

329                 String JavaDoc tagSubst = ((TKTag)tags.elementAt( i )).apply( ed );
330                 if( tagSubst != null ) result.append( tagSubst );
331
332             }
333         }
334
335         if( i < nText ) {
336             result.append(applyConverter ((String JavaDoc) textChunks.elementAt (i),ed));
337         }
338         
339         return result.toString();
340     }
341     
342     /**
343      * Das Template wird generiert.
344      *
345      * @param TKTemplateData ed
346      * @param PrintStream ps
347      */

348      public void apply( TKTemplateData ed, PrintStream ps ) throws TKTemplateSyntaxException, IOException
349     {
350         int nText = textChunks.size();
351         int nTags = tags.size();
352         
353         int i=0;
354         for( ; i < nTags; i++ ) {
355
356             ps.print (applyConverter ((String JavaDoc) textChunks.elementAt (i),ed));
357             ((TKTag)tags.elementAt( i )).apply( ed, ps );
358         }
359         if( i < nText ) {
360             ps.print(applyConverter ((String JavaDoc) textChunks.elementAt (i),ed));
361         }
362     }
363     
364     /**
365      * Das Template wird generiert.
366      *
367      * @param ed TKTemplateData
368      * @param writer Writer to which the result is written
369      */

370      public void apply( TKTemplateData ed, Writer writer)
371         throws TKTemplateSyntaxException, IOException
372     {
373         int nText = textChunks.size();
374         int nTags = tags.size();
375         
376         int i=0;
377         for( ; i < nTags; i++ ) {
378
379             writer.write (applyConverter ((String JavaDoc) textChunks.elementAt (i),ed));
380             ((TKTag)tags.elementAt( i )).apply( ed, writer );
381         }
382         if( i < nText ) {
383             writer.write(applyConverter ((String JavaDoc) textChunks.elementAt (i),ed));
384         }
385     }
386     
387     /**
388      * Wird rekursiv ein Syntaxbaum fuer ein Template aus einem String erzeugt und das Template
389      * enthaelt Tags, so muessen diese als Objekte erzeugt werden. Tags koennen neben
390      * Attribute, die gesetzt werden, wiederum Syntaxobjekte beinhalten,welche erzeugt werden.
391      *
392      * @param PatternMatcherInput matcherInput
393      * @param MatchResult match
394      *
395      * @return ein bearbeitetes TKTag-Objekt
396      */

397     public TKTag newTag( PatternMatcherInput matcherInput, MatchResult match ) throws TKTemplateSyntaxException
398     {
399                 
400         int nameEnd = 0; // Name der Tagklasse (kein Nametag)
401
int firstPos = match.endOffset(0);
402         int currPos = firstPos;
403         int tagsToClose = 1;
404         boolean found = false;
405         boolean hasSubTags = false;
406         char ch;
407         // Wir befinden uns nach </?TK[:_]
408
do {
409             ch = matcherInput.charAt( currPos++ );
410
411             if( (ch == ':') && (!hasSubTags) && (nameEnd == 0) ) {
412
413                 nameEnd = currPos;
414
415             } else if (ch == '\\' ) {
416             
417                 ch = matcherInput.charAt( currPos++ );
418                 continue;
419             
420             } else if( ch == '>' ) {
421
422                 found = ( (--tagsToClose) == 0);
423
424             } else if( ch == '<' ) {
425             
426                 tagsToClose++;
427                 hasSubTags = hasSubTags || matcherInput.substring( currPos, currPos+2 ).equalsIgnoreCase("TK");
428             }
429         } while( !found );
430         
431         matcherInput.setCurrentOffset( currPos );
432         if( nameEnd != 0 ) {
433             String JavaDoc tagType = matcherInput.substring( firstPos, nameEnd-1 ).toUpperCase();
434             String JavaDoc tagData = matcherInput.substring( nameEnd, currPos-1 );
435
436             if( matcherInput.charAt( match.beginOffset(0)+1 ) == '/' )
437                 return new TKEndTag( this, tagType, tagData, hasSubTags );
438             // Starttag
439
return getTag( tagType, tagData, matcherInput, hasSubTags );
440
441         }
442         // z.B. </TK_IF>
443
if( matcherInput.charAt( match.beginOffset(0)+1 ) == '/' )
444             return new TKEndTag( this, matcherInput.substring( firstPos, currPos-1 ), "", hasSubTags );
445             
446         return new TKNameTag( this, matcherInput.substring( firstPos, currPos-1 ), hasSubTags );
447     }
448
449     public TKTag getTag( String JavaDoc tagType, String JavaDoc tagData, PatternMatcherInput matcherInput, boolean hasSubTags )
450         throws TKTemplateSyntaxException
451     {
452         if( tagType.equals(patIfMarker) ) return new TKIfTag( this, tagData, matcherInput, hasSubTags );
453         if( tagType.equals(patElseMarker) ) return new TKEndTag( this, tagType, tagData, hasSubTags );
454         if( tagType.equals(patElsIfMarker) ) return new TKEndTag( this, tagType, tagData, hasSubTags );
455         if( tagType.equals(patListMarker) ) return new TKListTag( this, tagData, matcherInput, hasSubTags );
456         if( tagType.equals(patIncludeMarker) ) return new TKIncludeTag( this, tagData, hasSubTags );
457         if( tagType.equals(patTagDefinitionMarker) ) return new TKTagDefinitionTag( this, tagData, matcherInput, hasSubTags );
458         if( tagType.equals(patAtomTagMarker) ) return new TKAtomTagTag( this, tagData, hasSubTags );
459         if( tagType.equals(patTagMarker) ) return new TKTagTag( this, tagData, matcherInput, hasSubTags );
460         if( tagType.equals(patNoExpandMarker) ) return new TKNoExpandTag( this, tagData, matcherInput, hasSubTags );
461         if( tagType.equals(patTrimMarker) ) return new TKTrimTag( this, tagData, matcherInput, hasSubTags );
462         if( tagType.equals(patCaseMarker) ) return new TKCaseTag( this, tagData, matcherInput, hasSubTags );
463         if( tagType.equals(patNotMarker) ) return new TKNotTag( this, tagData, matcherInput, hasSubTags );
464         if( tagType.equals(patSwitchMarker) ) return new TKSwitchTag( this, tagData, hasSubTags );
465         if( tagType.equals(patScopeMarker) ) return new TKScopeTag( this, tagData, matcherInput, hasSubTags );
466         if( tagType.equals(patIgnoreMarker) ) return new TKIgnoreTag( this, tagData, matcherInput, hasSubTags );
467         if( tagType.equals(patSetMarker) ) return new TKSetTag( this, tagData, hasSubTags );
468         if( tagType.equals(patSetLocalMarker) ) return new TKSetLocalTag( this, tagData, hasSubTags );
469         if( tagType.equals(patLocalMarker) ) return new TKLocalTag( this, tagData, matcherInput, hasSubTags );
470         if( tagType.equals(patEvalMarker) ) return new TKEvalTag( this, tagData, hasSubTags );
471         if( tagType.equals(patExpressionMarker) ) return new TKExpressionTag( this, tagData, hasSubTags );
472         if( tagType.equals(patWhileMarker) ) return new TKWhileTag( this, tagData, matcherInput, hasSubTags );
473         if( tagType.equals(patExistsMarker) ) return new TKExistsTag( this, tagData, hasSubTags );
474         if( tagType.equals(patDateMarker) ) return new TKDateTag( this, tagData, hasSubTags );
475         if( tagType.equals(patLanguageMarker) ) return new TKLanguageTag( this, tagData, hasSubTags );
476         return null;
477     }
478     
479     public final Enumeration getTags()
480     {
481         return tags.elements();
482     }
483     
484     public final Enumeration getTexts()
485     {
486         return textChunks.elements();
487     }
488 }//end class
489

490
491
Popular Tags