Άρθρο του Eclipse Corner |
Σύνοψη
Η δημιουργία πρωτογενούς κώδικα μπορεί να σας εξοικονομήσει χρόνο και να μειώσει τον χρόνο κουραστικού και πλεονάζοντος προγραμματισμού. Αν και η δημιουργία πρωτογενούς κώδικα αποτελεί ένα ισχυρό εργαλείο, το πρόγραμμα που συντάσσει τον κώδικα μπορεί γρήγορα να γίνει πολύ σύνθετο και δυσνόητο. Ένας τρόπος για τη μείωση της πολυπλοκότητας και την αύξηση της αξιοπιστίας είναι η χρήση προτύπων.
Το έργο Eclipse Modeling Framework (EMF) περιέχει δύο πανίσχυρα εργαλεία δημιουργίας πρωτογενούς κώδικα: το JET (Java Emitter Templates) και το JMerge (Java Merge). Το JET σας επιτρέπει να χρησιμοποιήσετε σύνταξη όμοια με JSP (συγκεκριμένα ένα υποσύνολο της σύνταξης JSP) για να συντάξετε πρότυπα για τον κώδικα που θέλετε να δημιουργήσετε. Το JET είναι ένας γενικός μηχανισμός προτύπων που μπορεί να χρησιμοποιηθεί για τη δημιουργία κώδικα SQL, XML ή Java καθώς και άλλων μορφών δεδομένων εξόδου από πρότυπα. Βρίσκεται στην πρόσθετη λειτουργία org.eclipse.emf.codegen ως μέρος της μεταφόρτωσης του περιβάλλοντος εκτέλεσης EMF.
Σε αυτό το άρθρο θα μάθετε πώς να δημιουργείτε πρότυπα JET, πώς να χρησιμοποιείτε τη φύση JET και το εργαλείο δόμησης JET για την αυτόματη μετατροπή προτύπων σε κλάσεις Java και πώς να χρησιμοποιήσετε αυτές τις κλάσεις για τη δημιουργία πρωτογενούς κώδικα. Αυτό το άρθρο παρέχει επίσης μια σύντομη περιγραφή της σύνταξης JET.
Συνεισφορά από Remko Popma, Azzurri Ltd., remko.popma at azzurri dot jp, 30 Ιουλίου 2003. Χρησιμοποιείται με άδεια. Τελευταία ενημέρωση: 3 Ιανουαρίου 2007.
Έναρξη εργασιών
Το μοντέλο JET
Οδηγίες
Στοιχεία σεναρίου JET
Πόροι
Πριν τη δημιουργία του πρώτου προτύπου, θα χρειαστεί η πρόσθετη λειτουργία EMF. Αν δεν το έχετε εγκαταστήσει μέχρι τώρα, εγκαταστήστε το προτού συνεχίσετε με αυτό το πρόγραμμα εκμάθησης.
Τα αποτυπώματα οθόνης βασίζονται στην έκδοση 3.1.0 RC2 του Eclipse SDK και στην έκδοση 2.1.0 I200506160200 του EMF. Η ελάχιστη απαίτηση για τη χρήση δομών Java, όπως τα Γενικά είδη, είναι το Eclipse 3.3M4 και EMF 2.3.0M4.
Ένα πρότυπο JET είναι ένα αρχείο κειμένου, το όνομα αρχείου του οποίου τελειώνει με "jet". Θα ακολουθήσουμε τη σύμβαση EMF για την προσάρτηση του "jet" σε οποιαδήποτε επέκταση αρχείου θα είχε ο δημιουργημένος κώδικας. Έτσι, το .javajet υποδηλώνει ότι το πρότυπο δημιουργεί ένα αρχείο .java, τα πρότυπα .xmljet δημιουργούν XML, τα πρότυπα που δημιουργούν SQL έχουν επέκταση .sqljet και ούτω καθεξής.
Θα ξεκινήσουμε με ένα πρότυπο που δημιουργεί το μήνυμα "Hello, world". Θα δημιουργήσουμε το πρώτο μας πρότυπο ακολουθώντας την παρακάτω διαδικασία η οποία χωρίζεται σε τέσσερα βήματα:
Από το μενού του πάγκου εργασίας, επιλέξτε Αρχείο > Δημιουργία > Έργο για να εμφανιστεί ο οδηγός δημιουργίας έργου. Δημιουργήστε ένα έργο Java και προσθέστε του έναν φάκελο πρωτογενούς κώδικα με την ονομασία src.
Μετά την δημιουργία του έργου, πατήστε σε αυτό με το δεξί κουμπί του ποντικιού στην Εξερεύνηση πακέτων ή στην προβολή Ιεραρχία και επιλέξτε Δημιουργία > Άλλο... > Πρότυπα JET> Μετατροπή έργων σε έργα JET.
Αφού πατήσετε το κουμπί Επόμενο, επιλέξτε το έργο που δημιουργήσατε και πατήστε Ολοκλήρωση.
Ο οδηγός προσθέτει στο έργο τη φύση JET δημιουργώντας ένα φάκελο templates στον κεντρικό κατάλογο έργου όπως φαίνεται στην εικόνα παρακάτω. Επίσης, προστίθεται στο έργο ένα εργαλείο δόμησης JET το οποίο θα μετατρέψει αυτόματα όλα τα αρχεία στο φάκελο templates με κατάληξη "jet" σε κλάση Java.
Πριν τη δημιουργία του πρώτου μας προτύπου πρέπει να βεβαιωθούμε ότι ο φάκελος πρωτογενούς κώδικα src του έργου είναι ο φάκελος προορισμού των προτύπων που μετατρέπονται. Πατήστε με το δεξί κουμπί του ποντικιού στο έργο και επιλέξτε "Ιδιότητες" από το αναδυόμενο μενού. Στο πλαίσιο διαλόγου Ιδιότητες έργου, επιλέξτε Ρυθμίσεις JET στο αριστερό μενού και πληκτρολογήστε "src" (το όνομα του φακέλου πρωτογενούς κώδικα) στο πεδίο "Θέση υποδοχής πρωτογενούς κώδικα". Η παρακάτω εικόνα εμφανίζει τη σελίδα ιδιοτήτων Ρυθμίσεις JET στο πλαίσιο διαλόγου Ιδιότητες έργου.
Σημείωση: Μπορείτε
να καθορίσετε πολλαπλούς φακέλους στο πεδίο Θέσεις υποδοχής
προτύπων, διαχωρισμένους με ένα κενό διάστημα ή ελληνικό ερωτηματικό. Ωστόσο, αν
υπάρχουν πρότυπα σε διαφορετικούς φακέλους με το ίδιο όνομα αρχείου, μόνο το
πρότυπο στον πρώτο φάκελο θα μετατραπεί αυτόματα από το Εργαλείο δόμησης JET. Αν θέλετε
να μετατραπούν όλα τα πρότυπα, βεβαιωθείτε ότι έχουν διαφορετικά ονόματα αρχείων.
Το εργαλείο δόμησης JET θα μετατρέψει όλα τα πρότυπα σε αρχεία πρωτογενούς κώδικα στο φάκελο src του έργου.
Πρώτα, προκειμένου να αποφύγετε προβλήματα δόμησης, απενεργοποιήστε τις αυτόματες δομήσεις. Από το μενού Έργο, αποεπιλέξτε το στοιχείο "Αυτόματη δόμηση".
Με την επιλογή "Αυτόματη δόμηση" απενεργοποιημένη, δεν θα λάβετε το το παρακάτω σφάλμα όταν πατήσετε το κουμπί Ολοκλήρωση: "Η οδηγία 'jet' λείπει από το 'helloworld.txtjet', γραμμή 1, στήλη 1".
Αν η αυτόματη δόμηση είναι ενεργοποιημένη, θα λάβετε το παραπάνω μήνυμα σφάλματος. Αυτό δεν σημαίνει ότι υπάρχει πραγματικό πρόβλημα, απλά ότι το εργαλείο δόμησης JET προσπάθησε να μετατρέψει το πρότυπο μόλις το δημιουργήθηκε και διαπίστωσε ότι είναι ακόμα κενό. Πατήστε OK για να κλείσετε το πλαίσιο διαλόγου σφάλματος. Ανοίξτε το αρχείο helloworld.txtjet αν δεν είναι ήδη ανοιχτό και πληκτρολογήστε ή κάντε αποκοπή και επικόλληση των παρακάτω περιεχομένων στη λειτουργία επεξεργασίας.
<%@ jet package="hello" class="HelloWorldTemplate" %>
Hello, world!
Όταν αποθηκεύσετε το αρχείο προτύπου, θα μετατραπεί αυτόματα απο το εργαλείο δόμησης JET αν έχετε ενεργοποιήσει την επιλογή 'Αυτόματη δόμηση'. Σε αντίθετη περίπτωση, επιλέξτε "Δόμηση έργου" από το μενού Έργο.
Επειδή ορίσαμε το πακέτο hello και την κλάση HelloWorldTemplate στη πρώτη γραμμή του προτύπου, το εργαλείο δόμησης δημιουργεί ένα πακέτο hello στον φάκελο src και αποθηκεύει ένα αρχείο Java HelloWorldTemplate.java σε αυτό το πακέτο, όπως απεικονίζεται στην παρακάτω εικόνα.
Αυτή η κλάση Java είναι το αποτέλεσμα της μετατροπής του προτύπου και πλέον ονομάζεται κλάση υλοποίησης προτύπου. Αυτή η κλάση έχει μια μέθοδο με την ονομασία generate. Αυτή είναι η μέθοδος που δημιουργεί τον κώδικα που δηλώνεται στο πρότυπο.
Μπορούμε
να δημιουργήσουμε μια χρήση της κλάσης υλοποίησης προτύπου HelloWorldTemplate
και να καλέσουμε τη μέθοδο generate με αυτόν τον τρόπο:
Για την υλοποίηση του παραπάνω, δημιουργήστε μια νέα κλάση με την ονομασία HelloWorldImpl. Πατήστε με το δεξί κουμπί του ποντικιού στο πακέτο hello στην προβολή Εξερεύνηση πακέτων ή Ιεραρχία και πατήστε Δημιουργία > Κλάση.
Ονομάστε την κλάση "HelloWorldImpl" και βεβαιωθείτε ότι το στέλεχος public static void main(String[] args) είναι επιλεγμένο.
Τώρα αντιγράψτε τον ακόλουθο κώδικα στη μέθοδο main():
HelloWorldTemplate helloworld = new HelloWorldTemplate(); String result = helloworld.generate(null); System.out.println(result);
Για να την εκτελέσετε, επιλέξτε "Εκτέλεση ως/Εφαρμογή Java" από το αναπτυσσόμενο πλαίσιο "Εκτέλεση" της γραμμής εργαλείων. Θα πρέπει να δείτε τις λέξεις "Hello, world!" στην κονσόλα.
Για να ανακεφαλαιώσουμε, μόλις δημιουργήσαμε το πρώτο μας πρότυπο σε συνδυασμό με ένα τμήμα κώδικα. Το αποτέλεσμα μπορεί να μην ήταν τόσο εντυπωσιακό, αλλά είμαστε πλέον έτοιμοι να εξερευνήσουμε τι μπορεί να κάνει το JET για σας. Το επόμενο βήμα είναι να μεταβιβάσουμε ένα όρισμα στο πρότυπο.
Προσθέστε ένα νέο αρχείο προτύπου JET ή αλλάξτε το
υπάρχον με το ακόλουθο περιεχόμενο:
<%@ jet package="hello" class="GreetingTemplate" %> Hello, <%=argument%>!
Το εργαλείο δόμησης JET θα μετατρέψει αυτό το πρότυπο σε μια κλάση GreetingTemplate στο πακέτο hello. Δημιουργούμε ξανά μια χρήση αυτής της κλάσης προτύπου (ή αλλάζουμε το υπάρχον HelloWorldImpl), αλλά αυτή τη φορά μεταβιβάζουμε ένα όρισμα σειράς χαρακτήρων στη μέθοδο generate:
GreetingTemplate sayHello = new GreetingTemplate(); String result = sayHello.generate("Tutorial Reader"); System.out.println(result);
Ο παραπάνω κώδικας θα εκτυπώσει τις λέξεις "Hello, Tutorial Reader!" στην κονσόλα.
Το όρισμα που μεταβιβάζεται στο πρότυπο μπορεί να είναι οποιοδήποτε αντικείμενο. Στο
προηγούμενο παράδειγμα μεταβιβάσαμε μια σειρά χαρακτήρων ως όρισμα στη δημιουργία
μεθόδου, αλλά στην εφαρμογή σας θα θέλετε να μεταβιβάσετε το δικό σας αντικείμενο
μοντέλου. Αν το όρισμα δεν είναι στο πακέτο java.lang, ή αν το
πρότυπό σας χρησιμοποιεί άλλες κλάσεις που δεν βρίσκονται στο πακέτο
java.lang, θα χρειαστεί να εισαγάγετε αυτές τις κλάσεις στην οδηγία
jet του πρότυπου. Μια οδηγία jet με ένα
γνώρισμα imports έχει την ακόλουθη μορφή:
<%@ jet package="hello"imports="java.util.*" class="ImportDemoTemplate" %>
Η ενότητα Πληροφορίες αναφοράς για τη σύνταξη JET αυτού του άρθρου παρέχει περισσότερες πληροφορίες για την οδηγία jet και τα γνωρίσματά της.
Στο επόμενο παράδειγμα θα δημιουργήσουμε ένα πρότυπο που παράγει κώδικα XML. Προκειμένου να ακολουθήσουμε τη σύμβαση EMF για την προσάρτηση του "jet" σε οποιαδήποτε επέκταση αρχείου θα είχε ο δημιουργημένος κώδικας, θα αποθηκεύσουμε το πρότυπο σε ένα αρχείο με την ονομασία importdemo.xmljet. Σημειώστε ότι μεταβιβάζουμε στο πρότυπο ένα αντικείμενο java.util.List που περιέχει τα δεδομένα που θα χρησιμοποιηθούν για τη δημιουργία του XML.
<%@ jet package="hello"imports="java.util.*" class="XMLDemoTemplate" %>
<% List<?> elementList = (List<?>) argument; %> <?xml version="1.0" encoding="UTF-8"?> <demo> <% for (Iterator<?> i = elementList.iterator(); i.hasNext(); ) { %> <element><%=i.next().toString()%></element> <% } %> </demo>
Ο κώδικας που ακολουθεί παρουσιάζει τον τρόπο κλήσης της χρήσης προτύπου. Δημιουργούμε
μια λίστα
και
τη
μεταβιβάζουμε στη μέθοδο generate της κλάσης υλοποίησης προτύπου:
package hello; import java.util.ArrayList; public class XMLDemoImpl { public static void main(String[] args) {List<String> data = new ArrayList<String>(); data.add("first"); data.add("second"); data.add("third"); XMLDemoTemplate generateXml = new XMLDemoTemplate(); String result = generateXml.generate(
data); System.out.println(result); } }
Ο παραπάνω κώδικας εμφανίζει στην κονσόλα το ακόλουθο αποτέλεσμα XML:
<?xml version="1.0" encoding="UTF-8"?> <demo> <element>first</element> <element>second</element> <element>third</element> </demo>
Αυτό είναι ένα πολύ απλό παράδειγμα που δημιουργεί πολύ απλό κώδικα XML. Μπορείτε φυσικά να χρησιμοποιήσετε το JET για να δημιουργήσετε πιο σύνθετο κώδικα XML, χρησιμοποιώντας γνωρίσματα και χώρους ονομάτων. Μπορεί να σας φανεί βολικότερο να δημιουργήσετε μια ειδική κλάση που είναι καλύτερο μοντέλο εγγράφου XML από ένα java.util.ArrayList. Γενικά, όσο πιο σύνθετο γίνεται το πρότυπο JET, τόσο περισσότερο λογικό θα θέλετε να είναι το μοντέλο που θα μεταβιβάσετε στο πρότυπο ώστε να διατηρήσετε τα πρότυπά σας ευανάγνωστα. Θα ασχοληθούμε με το θέμα περισσότερο στο Μέρος 2 του προγράμματος εκμάθησης.
Μια χρήσιμη λειτουργία του JET είναι η δυνατότητα αλλαγής των προσδιοριστικών που επισημαίνουν τα μικροσενάρια στο αρχείο προτύπου. Αυτή λειτουργία είναι ιδιαίτερα χρήσιμη όταν η σύνταξη του κώδικα που δημιουργήσατε είναι παρόμοια με την προεπιλεγμένη σύνταξη JET, για παράδειγμα αν χρησιμοποιείτε το JET για να δημιουργήσετε σελίδες JSP.
Στο επόμενο παράδειγμα θα χρησιμοποιήσουμε το JET για τη δημιουργία μιας απλής σελίδας JSP. Θα αλλάξουμε τα προσδιοριστικά JET προκειμένου να χρησιμοποιούν την ακολουθία χαρακτήρων "<$" για την έναρξη ενός προσδιοριστικού προτύπου και "$>" για τη λήξη ενός προσδιοριστικού προτύπου. Το πρότυπο εξακολουθεί να περιέχει σειρές χαρακτήρων "<%" και "%>", αλλά η μηχανή JET δεν θα τις θεωρεί πλέον ειδικές και θα τις εγγράψει στο αποτέλεσμα όπως κάθε άλλη ακολουθία χαρακτήρων.
Για να αλλάξετε τους δείκτες προσδιοριστικών, προσθέστε ένα γνώρισμα
startTag
και ένα γνώρισμα
endTag στην οδηγία JET στην πρώτη γραμμή του προτύπου, όπως στο παρακάτω παράδειγμα.
<%@ jet package="tags.demo" class="JspTemplate"startTag="<$"
endTag="$>" %> <$ String paramName = (String) argument; /* This is an executed scriptlet */ $> <$ if (paramName != null) { $>
<%= request.getParameter("<$=paramName$>") %> <!-- this is generated JSP --> <$ } $>
Και πάλι καλούμε την κλάση υλοποίησης με ένα όρισμα σειράς χαρακτήρων, όπως παρακάτω:
System.out.println(new tags.demo.JspTemplate().generate("button"));Τα ακόλουθα δεδομένα εξόδου θα εμφανιστούν στην κονσόλα. Σημειώστε ότι τα δεδομένα εξόδου περιέχουν το ανέπαφο προσδιοριστικό JSP: οι σειρές χαρακτήρων "<%" και "%>" δεν ερμηνεύονται ως μικροσενάρια JET αλλά εισάγονται στο δημιουργημένο κώδικα.
<%= request.getParameter("button") %> <!-- this is generated JSP -->
Η προηγούμενη ενότητα παρουσίασε την δημιουργία προτύπων JET, τον τρόπο ορισμού της φύσης JET ώστε να μετατρέπει αυτόματα τα πρότυπα σε κλάσεις υλοποίησης Java και τον τρόπο χρήσης αυτών των κλάσεων υλοποίησης για τη δημιουργία κώδικα.
Σε αυτή την ενότητα θα εξετάσουμε τις κλάσεις υλοποίησης Java που προέρχονται από τη μετατροπή ενός προτύπου. Θα εξετάσουμε γιατί μπορούμε να χρησιμοποιήσουμε τα αντικείμενα έμμεσης δήλωσης argument και stringBuffer σε ένα πρότυπο, ενώ θα ασχοληθούμε με τον τρόπο προσαρμογής των κλάσεων υλοποίησης που έχουν υποστεί μετατροπή, παρέχοντας ένα προσαρμοσμένο "skeleton".
Ένα πρότυπο JET μετατρέπεται σε κλάση υλοποίησης Java. Υπάρχουν ορισμένα αντικείμενα στην κλάση υλοποίησης Java για τα οποία μπορεί να γίνει παραπομπή απευθείας στο πρότυπο JET. Το ακόλουθο παράδειγμα παρουσιάζει τον τρόπο χρήσης των αντικειμένων έμμεσης δήλωσης argument και stringBuffer σε ένα πρότυπο.
<%@ jet package="hello" class="TranslationDemoTemplate" %>Hello, <%=argument%>!
<% stringBuffer.append("Hello again!"); %>
Το παραπάνω πρότυπο μετατρέπεται σε κλάση υλοποίησης Java με τον ακόλουθο τρόπο:
package hello; public class TranslationDemoTemplate { protected static String nl;public static synchronized TranslationDemoTemplate create(String lineSeparator) { nl = lineSeparator; TranslationDemoTemplate result = new TranslationDemoTemplate(); nl = null; return result; } protected final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl; protected final String TEXT_1 = "Hello, "; protected final String TEXT_2 = "!"; public String generate(Object argument) { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(TEXT_1);
stringBuffer.append(argument); stringBuffer.append(TEXT_2);
stringBuffer.append("Hello again!"); return stringBuffer.toString(); } }
Σημειώστε ότι η μέθοδος generate της κλάσης υλοποίησης Java
δέχεται μια παράμετρο Object που ονομάζεται
argument. Αυτό είναι το ίδιο αντικείμενο με το
argument
στη δεύτερη γραμμή του προτύπου. Επίσης, σημειώστε ότι η κλάση υλοποίησης Java
χρησιμοποιεί ένα αντικείμενο StringBuffer για να συλλέξει τον
παραγόμενο κώδικα. Για το αντικείμενο αυτό, μπορεί να γίνει
παραπομπή απευθείας στο πρότυπο μέσω του ονόματός του, stringBuffer.
Η στατική μέθοδος
create
επιτρέπει σε μια εφαρμογή τη δημιουργία χρήσης ενός
TranslationDemoTemplate που χρησιμοποιεί μια συγκεκριμένη σειρά
χαρακτήρων ως διαχωριστικό γραμμής.
Η μέθοδος generate της κλάσης TranslationDemoTemplate που εμφανίζεται παραπάνω είναι μέρος του "σκελετού" της κλάσης υλοποίησης. Ο προεπιλεγμένος σκελετός που χρησιμοποιείται από τη μηχανή JET είναι παρόμοιος με τον παρακάτω:
public class CLASS { public String generate(Object argument) { return ""; } }
Ο ορισμός σκελετού είναι παρόμοιος με μια απλή κλάση Java, εκτός από το όνομα κλάσης. Το όνομα κλάσης (CLASS) θα αντικατασταθεί από την τιμή του γνωρίσματος class στην οδηγία jet. Επιπρόσθετα, ο ορισμός σκελετού έχει την μέθοδο generate που συναντήσαμε νωρίτερα. Αλλάζοντας το σκελετό μπορείτε να προσαρμόσετε μια κλάση υλοποίησης προτύπου, για παράδειγμα να την κάνετε να υλοποιεί μια διεπαφή ή να αλλάξετε οποιαδήποτε άλλη λειτουργία της κλάσης.
Για παράδειγμα, ας υποθέσουμε ότι θέλετε όλες οι κλάσεις υλοποίησης προτύπων
να υλοποιούν μια διεπαφή. Η διεπαφή θα μπορούσε να έχει την παρακάτω εμφάνιση:
public interface IGenerator { String generate(Object argument); }
Μπορούμε να πληροφορήσουμε τη μηχανή JET ότι θέλουμε να χρησιμοποιήσουμε έναν προσαρμοσμένο σκελετό ορίζοντας το γνώρισμα skeleton της οδηγίας jet στην πρώτη γραμμή του αρχείου προτύπου. Η τιμή του γνωρίσματος skeleton είναι ένα URI που παραπέμπει σε ένα αρχείο όπου μπορεί να βρεθεί ο προσαρμοσμένος ορισμός σκελετού.
Για δοκιμή, δημιουργήστε αρχικά ένα νέο αρχείο κειμένου χωρίς τίτλο από την επιλογή μενού Αρχείο > Δημιουργία ή από τη γραμμή εργαλείων.
Πληκτρολογήστε ή επικολλήστε το ακόλουθο περιεχόμενο στο αρχείο:
public class CLASSimplements IGenerator {
/* (non-javadoc) * @see IGenerator#generate(Object) */
public String generate(Object argument) { return ""; } }
Αποθηκεύστε το αρχείο ως generator.skeleton στον κατάλογο templates, με τον τρόπο που απεικονίζεται στην παρακάτω εικόνα.
Αυτό το αρχείο είναι ο προσαρμοσμένος σκελετός μας. Όλα τα πρότυπα που χρησιμοποιούν αυτόν το σκελετό θα μετατραπούν σε κλάσεις που υλοποιούν τη διεπαφή IGenerator. Για να χρησιμοποιήσετε αυτόν το σκελετό, προσθέστε το γνώρισμα skeleton στην οδηγία jet του προτύπου σας με αυτόν τον τρόπο:
<%@ jet package="hello" class="GreetingTemplate" skeleton="generator.skeleton" %> Hello, <%=argument%>! The current time is <%=new java.util.Date()%>.
Όταν το εργαλείο δόμησης JET μετατρέψει το πρότυπο, η κλάση υλοποίησης θα είναι παρόμοια με το παρακάτω:
package hello; public class GreetingTemplateimplements IGenerator { protected final String NL = System.getProperties().getProperty("line.separator"); protected final String TEXT_1 = "Hello, "; protected final String TEXT_2 = "!" + NL + "The current time is "; protected final String TEXT_3 = "."; protected final String TEXT_4 = NL;
/* (non-javadoc) * @see IGenerator#generate(Object) */
public String generate(Object argument) { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(TEXT_1); stringBuffer.append(argument); stringBuffer.append(TEXT_2); stringBuffer.append(new java.util.Date()); stringBuffer.append(TEXT_3); stringBuffer.append(TEXT_4); return stringBuffer.toString(); } }
Σημειώστε ότι το πρότυπο που έχει υποστεί μετατροπή
υλοποιεί πλέον την διεπαφή
IGenerator και η μέθοδος
generate
τώρα έχει
τα σχόλια που ορίσαμε στο αρχείο generator.skeleton. Αυτό είναι ένα
παράδειγμα του τρόπου προσαρμογής με έναν ορισμό σκελετού ενός προτύπου που έχει υποστεί
μετατροπή. Οι
ορισμοί σκελετού μπορεί επίσης να περιέχουν επιπλέον μεθόδους, εσωτερικές κλάσεις,
κ.λπ. Θα χρειαστεί να πειραματιστείτε για να δείτε τι άλλο μπορείτε να κάνετε.
Αν έχετε χρησιμοποιήσει τεχνολογία JSP παλαιότερα, η σύνταξη JET θα σας φανεί οικεία. Η σύνταξη JET είναι ένα υποσύνολο της σύνταξης JSP, επομένως είναι πιθανό να γνωρίζετε αρκετά από όσα αναφέρονται στη συνέχεια.
Αυτή η ενότητα παρέχει μια ημι-επίσημη περιγραφή και παραπομπή στη σύνταξη JET.
Ένα πρότυπο JET μετατρέπεται σε κλάση υλοποίησης Java. Αυτή η κλάση υλοποίησης έχει μια μέθοδο που μπορεί να κληθεί για την ανάκτηση μιας σειράς χαρακτήρων αποτελέσματος. Αυτή η μέθοδος ονομάζεται συνήθως generate (δείτε επίσης το γνώρισμα skeleton της οδηγίας jet).
Αν δεν οριστεί γνώρισμα skeleton στην οδηγία jet, η κλάση υλοποίησης Java έχει τα ακόλουθα αντικείμενα έμμεσης δήλωσης, για τα οποία μπορεί να γίνει παραπομπή στο πρότυπο JET:
Οι οδηγίες είναι μηνύματα προς τη μηχανή JET. Οι οδηγίες έχουν την ακόλουθη σύνταξη:
<%@ directive { attr="value" }* %>
Ενδεχομένως να υπάρχει προαιρετικό κενό διάστημα μετά το "<%@" και πριν το "%>".
Οι οδηγίες επηρεάζουν τον τρόπο μετατροπής του προτύπου, αλλά δεν παράγουν δεδομένα εξόδου στη δημιουργημένη σειρά χαρακτήρων όταν πραγματοποιείται κλήση του προτύπου.
Η οδηγία jet ορίζει έναν αριθμό γνωρισμάτων και τις διαβιβάζει στη μηχανή JET. Ένα αρχείο προτύπου JET πρέπει να περιέχει μια οδηγία jet στην πρώτη γραμμή του αρχείου, αλλιώς το αρχείο προτύπου δεν μπορεί να μετατραπεί. Όλες οι μετέπειτα οδηγίες jet παραβλέπονται. Τα άγνωστα γνωρίσματα έχουν ως αποτέλεσμα ανεπανόρθωτα σφάλματα μετατροπής.
Η ακόλουθη οδηγία υποδεικνύει ότι το πρότυπο πρέπει να μετατραπεί σε κλάση υλοποίησης Java με όνομα HelloWorldTemplate.java στο πακέτο hello. Πρέπει να γίνει εισαγωγή των πακέτων java.io.* και java.util.* από την κλάση υλοποίησης.
<%@ jet package="hello" class="HelloWorldTemplate" imports="java.io.* java.util.*" %>
Οι λεπτομέρειες των γνωρισμάτων της οδηγίας jet είναι οι ακόλουθες:
Γνώρισμα | Τιμή |
---|---|
package | Το όνομα πακέτου της κλάσης υλοποίησης Java στην οποία μετατρέπεται το πρότυπο. Αν αυτό το γνώρισμα δεν υπάρχει, η κλάση υλοποίησης Java θα δημιουργηθεί στο προεπιλεγμένο πακέτο. |
class | Το όνομα της κλάσης υλοποίησης Java στην οποία μετατρέπεται το πρότυπο. Αν δεν υπάρχει, η κλάση υλοποίησης Java ονομάζεται CLASS. |
imports | Μια διαχωρισμένη με διαστήματα λίστα πακέτων ή/και κλάσεων προς εισαγωγή στην κλάση προτύπων Java |
startTag | Η σειρά χαρακτήρων σε ένα πρότυπο JET που σηματοδοτεί την αρχή ενός μικροσεναρίου, μιας έκφρασης ή μιας οδηγίας include. Η προεπιλεγμένη είναι "<%". Αυτό το γνώρισμα, όπως και το συγγενικό του endTag, μπορεί να αποδειχθούν ιδιαίτερα χρήσιμα όταν η σύνταξη του δημιουργημένου κώδικα είναι παρόμοια με την προεπιλεγμένη σύνταξη JET, αν για παράδειγμα χρησιμοποιείτε το JET για τη δημιουργία σελίδων JSP. |
endTag | Η σειρά χαρακτήρων σε ένα πρότυπο JET που σηματοδοτεί το τέλος ενός μικροσεναρίου, μιας έκφρασης ή μιας οδηγίας include. Η προεπιλεγμένη είναι "%>". Δείτε επίσης το startTag. |
skeleton | Το URI ενός αρχείου με ορισμό σκελετού της κλάσης υλοποίησης Java στην οποία μετατρέπεται το πρότυπο. Αυτό το URI θα αναλυθεί με τρόπο παρόμοιο με τον τρόπο ανάλυσης της τιμής του γνωρίσματος file σε μια οδηγία include. Αν δεν έχει διευκρινιστεί αρχείο ορισμού σκελετού, η μηχανή θα χρησιμοποιήσει έναν προεπιλεγμένο σκελετό της μορφής "public class CLASS\n{\n public String generate(Object argument)\n {\n return \"\";\n }\n}\n". Το όνομα κλάσης σε αυτόν τον ορισμό κλάσης σκελετού πρέπει να είναι CLASS. |
nlString | Η σειρά χαρακτήρων νέας γραμμής που θα χρησιμοποιηθεί στην κλάση προτύπου Java. Η προεπιλεγμένη τιμή είναι "System.getProperties().getProperty(\"line.separator\")" |
Η οδηγία include χρησιμοποιείται για να υποκαταστήσει κείμενο ή/και κώδικα κατά τον χρόνο μετατροπής προτύπων. Η οδηγία <%@ include file="urlSpec" %> εισάγει το κείμενο του καθορισμένου πόρου στο αρχείο προτύπου jet. Το συμπεριλαμβανόμενο αρχείο ενδεχομένως να έχει στοιχεία σεναρίου JET τα οποία επίσης θα υποβληθούν σε επεξεργασία.
Αυτή η οδηγία έχει ένα και μοναδικό γνώρισμα, το file. Η τιμή αυτού του γνωρίσματος είναι το URI της θέσης του αρχείου που θα συμπεριληφθεί. Το URI μπορεί να είναι μια απόλυτη ή μια σχετική διαδρομή. Τα σχετικά URI ερμηνεύονται πάντα σε σχέση με το φάκελο του προτύπου που περιέχει την οδηγία include.
Παράδειγμα:
Το ακόλουθο παράδειγμα υποβάλει αίτηση για συμπερίληψη, κατά το χρόνο μετατροπής, ενός αρχείου πνευματικών δικαιωμάτων.
<%@ include file="copyright.jet" %>
Σημείωση: Το JET υποστηρίζει την έννοια της αντικατάστασης διαδρομών
προτύπων. Είναι πιθανό να προσαρμόσετε τη μηχανή JET ώστε να χρησιμοποιεί πολλαπλές
θέσεις υποδοχής προτύπων. Σε αυτήν την περίπτωση, η πρώτη θέση υποδοχής έχει
προτεραιότητα έναντι της δεύτερης, η δεύτερη έναντι της τρίτης, κ.ο.κ. Αυτό σημαίνει ότι
αν υπάρχουν αρχεία προτύπων ή συμπεριλαμβανόμενα αρχεία με το ίδιο όνομα σε πολλαπλές
Θέσεις υποδοχής προτύπων, θα χρησιμοποιηθεί το αρχείο στον πρώτο φάκελο ενώ τα υπόλοιπα
θα αγνοηθούν. Οι πελάτες μιας βασισμένης σε JET εφαρμογής μπορούν να
χρησιμοποιούν αυτόν τον μηχανισμό για να παρέχουν προσαρμοσμένα
συμπεριλαμβανόμενα αρχεία (include files) που αντικαθιστούν τα αρχικά χωρίς να τροποποιούν
τα πρότυπα της
αρχικής εφαρμογής.
Το JET έχει δύο στοιχεία γλώσσας σεναρίου: τα μικροσενάρια και τις εκφράσεις. Το μικροσενάριο είναι ένα τμήμα πρότασης και η έκφραση είναι μια ολοκληρωμένη έκφραση Java.
Κάθε στοιχείο σεναρίου έχει μια σύνταξη βασισμένη σε "<%" όπως παρακάτω:
<% αυτό είναι μικροσενάριο %> <%= αυτό είναι έκφραση %>
Τα κενά διαστήματα είναι προαιρετικά μετά τα "<%" και "<%=", και πριν το "%>".
Αν θέλετε να χρησιμοποιήσετε την ακολουθία χαρακτήρων %> ως πραγματικούς χαρακτήρες σε ένα μικροσενάριο, και όχι ως χαρακτήρες που σηματοδοτούν το κλείσιμό του, μπορείτε να προσθέσετε ένα χαρακτήρα διαφυγής ως εξής: %\>. Παρομοίως, μπορείτε να προσθέσετε χαρακτήρα διαφυγής στη σειρά χαρακτήρων <% πληκτρολογώντας <\%.
Τα μικροσενάρια μπορεί να περιέχουν οποιοδήποτε έγκυρο τμήμα κώδικα Java.
Τα μικροσενάρια εκτελούνται κατά τον χρόνο κλήσης προτύπου. Το αν θα παραγάγουν δεδομένα εξόδου στη σειρά χαρακτήρων αποτελέσματος ή όχι εξαρτάται από τον κώδικα του μικροσενάριου. Τα μικροσενάρια μπορεί να έχουν παρενέργειες, τροποποιώντας τα ορατά αντικείμενα στο εσωτερικό τους.
Όταν όλα τα τμήματα μικροσεναρίου σε μια δεδομένη μονάδα μετατροπής συνδυάζονται με τη σειρά που απεικονίζονται στο πρότυπο JET, θα πρέπει να παρέχουν μια έγκυρη πρόταση ή ακολουθία προτάσεων Java.
Παράδειγμα:<% if (Calendar.getInstance().get(Calendar.AM_PM) == Calendar.AM) {%> Good Morning <% } else { %> Good Afternoon <% } %>
<% scriptlet %>
Μια έκφραση στοιχείου JET είναι μια έκφραση Java που αποτιμάται ενώ το αποτέλεσμα προσαρτάται στο αντικείμενο StringBuffer το οποίο επιστρέφεται από τη μέθοδο generate. Οι εκφράσεις αποτιμώνται κατά τον χρόνο κλήσης του προτύπου.
Αν το αποτέλεσμα της έκφρασης δεν μπορεί να προσαρτηθεί σε ένα StringBuffer, εμφανίζεται σφάλμα χρόνου μετατροπής. Το περιεχόμενο μιας έκφρασης JET πρέπει να είναι μια ολοκληρωμένη έκφραση Java.
Υποστηρίζονται παρενέργειες στις εκφράσεις. Εφαρμόζονται όταν η έκφραση JET αποτιμηθεί. Οι εκφράσεις JET αποτιμώνται από αριστερά προς τα δεξιά στο πρότυπο JET.
Στο επόμενο παράδειγμα, η τρέχουσα ημερομηνία προσαρτάται στο αποτέλεσμα StringBuffer.
<%= (new java.util.Date()).toLocaleString() %>
<%= expression %>
http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-codegen.html