KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > tests > jfun > parsec > rfc822 > MessageParser


1 /*
2  * Created on Dec 10, 2004
3  *
4  * Author Ben Yu
5  */

6 package tests.jfun.parsec.rfc822;
7 import jfun.parsec.Map;
8 import jfun.parsec.Map2;
9 import jfun.parsec.Parser;
10 import jfun.parsec.Parsers;
11 import jfun.parsec.Mapn;
12 import jfun.parsec.Map3;
13 import jfun.parsec.Map4;
14 import jfun.parsec.Scanners;
15 import jfun.parsec.pattern.Patterns;
16
17 /**
18  * @author Ben Yu
19  *
20  * Dec 10, 2004
21  */

22 public final class MessageParser {
23   private static Parser keyword(String JavaDoc name){
24     return LexicalRules.keyword(name);
25   }
26   private final AddressParser aparser = new AddressParser();
27   private final DateTimeParser dparser = new DateTimeParser();
28   private final Parser addr_spec = aparser.addr_spec;
29   private final Parser phrase = aparser.phrase;
30   //private final Parser text = LexicalRules.text.many();
31
public final Parser msg_id = Parsers.between(
32       LexicalRules.isChar('<'),
33       LexicalRules.isChar('>'),
34       addr_spec);
35   private static final Parser colon = LexicalRules.isChar(':');
36   private static Parser namedField(String JavaDoc name, Parser p){
37     return LexicalRules.keyword(name).and(p,
38         new Map2(){
39           public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
40             return new NamedObject((String JavaDoc)o1, o2);
41           }
42     });
43   }
44   private static Parser field(String JavaDoc name, Parser p){
45     return namedField(name, colon.seq(p)
46         .followedBy(LexicalRules.crlf));
47   }
48   private static Parser extField(Parser name, Parser p){
49     return name.and(colon.seq(p).followedBy(LexicalRules.crlf),
50         new Map2(){
51       public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
52         return new NamedObject((String JavaDoc)o1, o2);
53       }
54     });
55   }
56   private static Parser foldedText(final Parser p){
57     return LexicalRules.toStringLexer(
58         Parsers.plus(
59             LexicalRules.lwsp, p
60         ).many()
61     );
62   }
63   private final Parser line =foldedText(
64       LexicalRules.crlf.not().seq(LexicalRules.chr)
65   );
66   public final Parser many_phrase_msg_id =
67     Parsers.sum(phrase, msg_id).many(Object JavaDoc.class);
68   public final Parser texts = foldedText(LexicalRules.text);
69   //public final Parser phrase_list = Parsers.sep
70
public final Parser optional_field = Parsers.sum(new Parser[]{
71       field("Message-ID", msg_id),
72       field("Resent-Message-ID", msg_id),
73       field("In-Reply-To",many_phrase_msg_id),
74       field("References", many_phrase_msg_id),
75       field("Keywords",
76           LexicalRules.list(phrase, String JavaDoc[].class)),
77       field("Subject", texts),
78       field("Comments", texts),
79       field("Encrypted",
80           aparser.word.some(String JavaDoc.class, 1,2)),
81       extField(LexicalRules.s_atom, line)
82     }
83   );
84   public final Parser address_list1 =
85     LexicalRules.list1(aparser.address, Address.class);
86   public final Parser address_list =
87     LexicalRules.list(aparser.address, Address.class);
88   public final Parser destination = Parsers.sum(new Parser[]{
89       field("To", address_list1),
90       field("Resent-To", address_list1),
91       field("cc", address_list1),
92       field("Resent-cc", address_list1),
93       field("bcc", address_list),
94       field("Resent-bcc", address_list)
95   });
96   public final Parser resent_date =
97     field("Resent-Date", dparser.pdatetime);
98   public final Parser orig_date =
99     field("Date", dparser.pdatetime);
100   public final Parser dates =
101     orig_date.and(resent_date.option(null), new Map2(){
102     public Object JavaDoc map(Object JavaDoc o1, Object JavaDoc o2){
103       return new Dates((DateTime)getObj((NamedObject)o1),
104           (DateTime)getObj((NamedObject)o2));
105     }
106   });
107   private Parser get_authentic(final String JavaDoc type,
108       final String JavaDoc from, final String JavaDoc sender){
109     return Parsers.plus(
110         field(from, aparser.mailbox).map(new Map(){
111           public Object JavaDoc map(final Object JavaDoc o){
112             final NamedObject no = (NamedObject)o;
113             return new SingleAuthentic(type, (Mailbox)no.getObj());
114           }
115         }).printTrace("authentic.mailbox"),
116         field(sender, aparser.mailbox)
117         .and(field(
118             from,
119             LexicalRules.list1(aparser.mailbox, Mailbox.class)
120             ),
121             new Map2(){
122               public Object JavaDoc map(Object JavaDoc o1, Object JavaDoc o2){
123                 final NamedObject no1 = (NamedObject)o1;
124                 final NamedObject no2 = (NamedObject)o2;
125                 return new MultipleAuthentic(
126                     type, (Mailbox)no1.getObj(), (Mailbox[])no2.getObj()
127                 );
128               }
129             }
130         )
131     );
132   }
133   private Parser get_authenticated_addr(final String JavaDoc type,
134       final String JavaDoc from, final String JavaDoc sender, final String JavaDoc replyto){
135     return get_authentic(type, from, sender).and(
136         field(replyto,
137             LexicalRules.list1(aparser.address, Address.class))
138             .option(null),
139         new Map2(){
140           public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
141             return new AuthenticatedAddress((Authentic)o1,
142                 (Address[])getObj((NamedObject)o2));
143           }
144         });
145   }
146   private static Object JavaDoc getObj(final NamedObject no){
147     return no==null?null:no.getObj();
148   }
149   public final Parser resent_authentic =
150     get_authentic("resent", "Resent-From", "Resent-Sender");
151   public final Parser authentic =
152     get_authentic("original", "From", "Sender");
153   public final Parser resent =
154     get_authenticated_addr("resent", "Resent-From",
155         "Resent-Sender", "Resent-Reply-To");
156   public final Parser originator =
157     get_authenticated_addr("original", "From",
158         "Sender", "Reply-To");
159   public final Parser received =
160     keyword("Received").seq(colon).seq(
161       Parsers.mapn(Object JavaDoc.class, new Parser[]{
162           namedField("from", aparser.domain).option(null),
163           namedField("by", aparser.domain).option(null),
164           namedField("via", aparser.atom).option(null),
165           namedField("with", aparser.atom).many(NamedObject.class),
166           namedField("id", msg_id).option(null),
167           namedField("for", addr_spec).option(null),
168           LexicalRules.isChar(';')
169           .seq(dparser.pdatetime)
170           .followedBy(LexicalRules.crlf)
171       }, new Mapn(){
172           public Object JavaDoc map(final Object JavaDoc[] args){
173             final NamedObject from = (NamedObject)args[0];
174             final NamedObject by = (NamedObject)args[1];
175             final NamedObject via = (NamedObject)args[2];
176             final NamedObject[] withs = (NamedObject[])args[3];
177             final NamedObject id = (NamedObject)args[4];
178             final NamedObject _for = (NamedObject)args[5];
179             final DateTime datetime = (DateTime)args[6];
180             final String JavaDoc[] swith = new String JavaDoc[withs.length];
181             for(int i =0; i<swith.length; i++){
182               swith[i] = (String JavaDoc)getObj(withs[i]);
183             }
184             return new Received((String JavaDoc[])getObj(from),
185                 (String JavaDoc[])getObj(by),
186                 (String JavaDoc)getObj(via),
187                 swith,
188                 (AddrSpec)getObj(id),
189                 (AddrSpec)getObj(_for),
190                 datetime
191                 );
192           }
193         })
194   );
195   public final Parser retn =
196     field("Return-path", aparser.route_addr);
197   public final Parser trace =
198     retn.and(received.many1(Received.class), new Map2(){
199     public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
200       return new Trace(
201           (RouteAddr)getObj((NamedObject)o1), (Received[])o2
202       );
203     }
204   });
205   public final Parser source =
206     Parsers.map3(
207         trace.option(null),
208         originator,
209         resent.option(null),
210     new Map3(){
211       public Object JavaDoc map(final Object JavaDoc o1, Object JavaDoc o2, Object JavaDoc o3){
212         return new Source(
213             (Trace)o1,
214             (AuthenticatedAddress)o2,
215             (AuthenticatedAddress)o3
216         );
217       }
218   });
219   public final Parser fields = Parsers.map4(
220       dates, source,
221       destination.many1(NamedObject.class),
222       optional_field.many(NamedObject.class),
223       new Map4(){
224         public Object JavaDoc map(Object JavaDoc o1, Object JavaDoc o2, Object JavaDoc o3, Object JavaDoc o4){
225           return new Fields(
226               (Dates)o1,
227               (Source)o2,
228               (NamedObject[])o3,
229               (NamedObject[])o4);
230         }
231   });
232   public final Parser body =
233     LexicalRules.toStringLexer(LexicalRules.chr.many());
234   public final Parser message =
235     fields.and(LexicalRules.crlf.seq(body),
236       new Map2(){
237         public Object JavaDoc map(Object JavaDoc o1, Object JavaDoc o2){
238           return new Message((Fields)o1, (String JavaDoc)o2);
239         }
240   });
241   public Object JavaDoc runParser(CharSequence JavaDoc src, final Parser p){
242     return LexicalRules.runParser(src, p);
243   }
244 }
245
Popular Tags