reintroduced StringUtil.regexpReplace
[mir.git] / source / mir / rss / RSS091Reader.java
1 /*
2  * Copyright (C) 2001-2006 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License,
22  * and distribute linked combinations including the two.  You must obey the
23  * GNU General Public License in all respects for all of the code used other than
24  * the above mentioned libraries.  If you modify this file, you may extend this
25  * exception to your version of the file, but you are not obligated to do so.
26  * If you do not wish to do so, delete this exception statement from your version.
27  */
28 package mir.rss;
29
30 import mir.util.HTTPClientHelper;
31 import mir.util.xml.XMLParserEngine;
32 import mir.util.xml.XMLParserExc;
33 import mir.util.xml.XMLParserFailure;
34
35 import java.io.InputStream;
36 import java.util.ArrayList;
37 import java.util.HashMap;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Map;
41
42 /**
43  *
44  * <p>Title: </p>
45  * <p>Description: </p>
46  * <p>Copyright: Copyright (c) 2003</p>
47  * <p>Company: </p>
48  * @author not attributable
49  * @version 1.0
50  */
51
52 public class RSS091Reader {
53   private final static String MAPPED_CHANNEL_PROPERTIES[][]  =
54      {
55        {"link",        "rss:link"        },
56        {"title",       "rss:title"       },
57        {"description", "rss:description" },
58        {"item",        "rss:item" },
59        {"language",    "dc:language" }
60      };
61
62   private final static String MAPPED_ITEM_PROPERTIES[][]  =
63     {
64       {"link",        "rss:link"        },
65       {"title",       "rss:title"       },
66       {"description", "rss:description" },
67       {"author",      "dc:creator" },
68     };
69
70   private Map mappedChannelProperties = new HashMap();
71   private Map mappedItemProperties = new HashMap();
72
73   public RSS091Reader() {
74     int i;
75
76     for (i=0; i<MAPPED_CHANNEL_PROPERTIES.length; i++) {
77       mappedChannelProperties.put(MAPPED_CHANNEL_PROPERTIES[i][0], MAPPED_CHANNEL_PROPERTIES[i][1]);
78     }
79
80     for (i=0; i<MAPPED_ITEM_PROPERTIES.length; i++) {
81       mappedItemProperties.put(MAPPED_ITEM_PROPERTIES[i][0], MAPPED_ITEM_PROPERTIES[i][1]);
82     }
83   }
84
85   public RSSData parseInputStream(InputStream aStream) throws RSSExc, RSSFailure {
86     try {
87       RSSData result = new RSSData();
88       XMLParserEngine.getInstance().parse("html", aStream, new RootSectionHandler(result));
89
90       return result;
91     }
92     catch (Throwable t) {
93       throw new RSSFailure(t);
94     }
95   }
96
97   public RSSData parseInputStream(InputStream aStream, String anEncoding) throws RSSExc, RSSFailure {
98     try {
99       RSSData result = new RSSData();
100       XMLParserEngine.getInstance().parse("html", aStream, anEncoding, new RootSectionHandler(result));
101
102       return result;
103     }
104     catch (Throwable t) {
105       throw new RSSFailure(t);
106     }
107   }
108
109   public RSSData parseUrl(String anUrl) throws RSSExc, RSSFailure {
110     try {
111       HTTPClientHelper httpClientHelper = new HTTPClientHelper();       
112       InputStream inputStream = httpClientHelper.getUrl(anUrl);
113  
114       if (inputStream==null)
115         throw new RSSExc("RSSChannel.parseUrl: Can't get url content");
116
117       RSSData theRSSData =  parseInputStream(inputStream);
118       httpClientHelper.releaseHTTPConnection();
119       return theRSSData;
120
121     }
122     catch (Throwable t) {
123       throw new RSSFailure(t);
124     }
125   }
126
127   public RSSData parseUrl(String anUrl, String anEncoding) throws RSSExc, RSSFailure {
128     try {
129       HTTPClientHelper httpClientHelper = new HTTPClientHelper();       
130       InputStream inputStream = httpClientHelper.getUrl(anUrl);
131
132       if (inputStream==null)
133         throw new RSSExc("RSSChannel.parseUrl: Can't get url content");
134       
135       RSSData theRSSData = parseInputStream(inputStream, anEncoding);
136       httpClientHelper.releaseHTTPConnection();
137       return theRSSData;
138     }
139
140     catch (Throwable t) {
141       throw new RSSFailure(t);
142     }
143   }
144
145   private class RootSectionHandler extends mir.util.xml.AbstractSectionHandler {
146     private RSSData data;
147
148     public RootSectionHandler(RSSData aData) {
149       data = aData;
150     }
151
152     public mir.util.xml.SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc {
153       if (aTag.getLocalName().equals("rss")) {
154         return new RSS091SectionHandler(data);
155       }
156                         throw new XMLParserFailure(new RSSExc("'rss' tag expected"));
157     }
158
159     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
160     }
161
162     public void characters(String aCharacters) throws XMLParserExc {
163       if (aCharacters.trim().length()>0)
164         throw new XMLParserExc("No character data allowed here");
165     }
166
167     public void finishSection() throws XMLParserExc {
168     }
169   }
170
171   private class RSS091SectionHandler extends mir.util.xml.AbstractSectionHandler {
172     private RSSData data;
173
174
175     public RSS091SectionHandler(RSSData aData) {
176       data = aData;
177     }
178
179     public mir.util.xml.SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc {
180       if (aTag.getLocalName().equals("channel"))
181         return new RSS091ChannelSectionHandler(data);
182       else
183         throw new XMLParserExc("channel tag expected, " + aTag.getLocalName() + " found");
184     }
185
186     public void characters(String aCharacters) throws XMLParserExc {
187       if (aCharacters.trim().length()>0)
188         throw new XMLParserExc("No character data allowed here");
189     }
190
191     public void finishSection() throws XMLParserExc {
192     }
193   }
194
195   private class RSS091ChannelSectionHandler extends mir.util.xml.AbstractSectionHandler {
196     private String currentTag;
197
198     private RSSData data;
199     private List items;
200     private RDFResource channel;
201     private Map attributes;
202
203     public RSS091ChannelSectionHandler(RSSData aData) {
204       data = aData;
205       items = new ArrayList();
206       channel = new RDFResource("rss:channel");
207       attributes = new HashMap();
208     }
209
210     public mir.util.xml.SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc {
211       String tag = aTag.getLocalName();
212
213       if (tag.equals("item"))
214         return new RSS091ItemSectionHandler();
215       else if (mappedChannelProperties.containsKey(tag)) {
216         currentTag=(String) mappedChannelProperties.get(tag);
217         return new PCDATASectionHandler();
218       }
219       else
220         return new DiscardingSectionHandler();
221     }
222
223     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
224       if (aHandler instanceof PCDATASectionHandler) {
225         attributes.put(currentTag, (((PCDATASectionHandler) aHandler).getData()));
226       }
227       else if (aHandler instanceof RSS091ItemSectionHandler) {
228         items.add((((RSS091ItemSectionHandler) aHandler).getItem()));
229       }
230     }
231
232     public void characters(String aCharacters) throws XMLParserExc {
233       if (aCharacters.trim().length()>0)
234         throw new XMLParserExc("No character data allowed here");
235     }
236
237     public void finishSection() throws XMLParserExc {
238       Iterator i = items.iterator();
239
240       while (i.hasNext()) {
241         data.addResource((RDFResource) i.next());
242       }
243     }
244   }
245
246   private class RSS091ItemSectionHandler extends mir.util.xml.AbstractSectionHandler {
247     private String currentTag;
248
249     private RDFResource item;
250     private Map attributes;
251
252     public RSS091ItemSectionHandler() {
253       attributes = new HashMap();
254     }
255
256     public mir.util.xml.SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc {
257       String tag = aTag.getLocalName();
258
259       if (mappedItemProperties.containsKey(tag)) {
260         currentTag=(String) mappedItemProperties.get(tag);
261         return new PCDATASectionHandler();
262       }
263                         return new DiscardingSectionHandler();
264     }
265
266     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
267       if (aHandler instanceof PCDATASectionHandler) {
268         attributes.put(currentTag, (((PCDATASectionHandler) aHandler).getData()));
269       }
270     }
271
272     public void characters(String aCharacters) throws XMLParserExc {
273       if (aCharacters.trim().length()>0)
274         throw new XMLParserExc("No character data allowed here");
275     }
276
277     public void finishSection() throws XMLParserExc {
278       item = new RDFResource("rss:item", (String) attributes.get("rss:link"));
279
280       Iterator i = attributes.entrySet().iterator();
281       while (i.hasNext()) {
282         Map.Entry entry = (Map.Entry) i.next();
283
284         item.set((String) entry.getKey(), entry.getValue());
285       }
286     }
287
288     public RDFResource getItem() {
289       return item;
290     }
291   }
292
293
294   private class PCDATASectionHandler extends mir.util.xml.AbstractSectionHandler {
295     private StringBuffer data;
296
297     public PCDATASectionHandler() {
298       data = new StringBuffer();
299     }
300
301     public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
302       throw new XMLParserFailure(new RSSExc("No subtags allowed here"));
303     }
304
305     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
306     }
307
308     public void characters(String aCharacters) throws XMLParserExc {
309       data.append(aCharacters);
310     }
311
312     public void finishSection() throws XMLParserExc {
313     }
314
315     public String getData() {
316       return data.toString();
317     }
318   }
319
320
321   private class RDFSequenceSectionHandler extends mir.util.xml.AbstractSectionHandler {
322     private List items;
323
324     public RDFSequenceSectionHandler() {
325       items = new ArrayList();
326     }
327
328     public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
329       if (aTag.equals("rdf:li")) {
330         String item = (String) anAttributes.get("rdf:resource");
331
332         if (item!=null)
333           items.add(item);
334       }
335
336       return new DiscardingSectionHandler();
337     }
338
339     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
340     }
341
342     public void characters(String aCharacters) throws XMLParserExc {
343     }
344
345     public void finishSection() throws XMLParserExc {
346     }
347
348     public List getItems() {
349       return items;
350     }
351   }
352
353   private class DiscardingSectionHandler extends mir.util.xml.AbstractSectionHandler {
354     public mir.util.xml.SectionHandler startElement(String aTag, Map anAttributes) throws XMLParserExc {
355       return this;
356     }
357
358     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
359     }
360
361     public void characters(String aCharacters) throws XMLParserExc {
362     }
363
364     public void finishSection() throws XMLParserExc {
365     }
366   }
367 }