2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
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.
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.
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
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 * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23 * (or with modified versions of the above that use the same license as the above),
24 * and distribute linked combinations including the two. You must obey the
25 * GNU General Public License in all respects for all of the code used other than
26 * the above mentioned libraries. If you modify this file, you may extend this
27 * exception to your version of the file, but you are not obligated to do so.
28 * If you do not wish to do so, delete this exception statement from your version.
32 import java.io.InputStream;
34 import java.util.List;
36 import java.util.Vector;
39 import mir.util.XMLReader;
45 * <p>Description: </p>
46 * <p>Copyright: Copyright (c) 2003</p>
48 * @author not attributable
52 public class RSSReader {
53 private static final String RDF_NAMESPACE_URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
54 private static final String RSS_1_0_NAMESPACE_URI = "http://purl.org/rss/1.0/";
55 private static final String DUBLINCORE_NAMESPACE_URI = "http://purl.org/dc/elements/1.1/";
56 private static final String EVENT_NAMESPACE_URI = "http://purl.org/rss/1.0/modules/event/";
57 private static final String TAXONOMY_NAMESPACE_URI = "http://web.resource.org/rss/1.0/modules/taxonomy/";
59 private static final XMLReader.XMLName RDF_ABOUT_PARAMETER = new XMLReader.XMLName(RDF_NAMESPACE_URI, "about");
60 private static final XMLReader.XMLName RDF_SEQUENCE_TAG = new XMLReader.XMLName(RDF_NAMESPACE_URI, "Seq");
61 private static final XMLReader.XMLName RDF_BAG_PARAMETER = new XMLReader.XMLName(RDF_NAMESPACE_URI, "Bag");
63 private static final XMLReader.XMLName RSS_CHANNEL_TAG = new XMLReader.XMLName(RSS_1_0_NAMESPACE_URI, "channel");
64 private static final XMLReader.XMLName RSS_ITEM_TAG = new XMLReader.XMLName(RSS_1_0_NAMESPACE_URI, "item");
65 private static final XMLReader.XMLName RSS_ITEMS_TAG = new XMLReader.XMLName(RSS_1_0_NAMESPACE_URI, "items");
68 private Map namespaceURItoModule;
69 private Map moduleToPrefix;
70 private RSSModule rdfModule;
73 modules = new Vector();
74 namespaceURItoModule = new HashMap();
75 moduleToPrefix = new HashMap();
77 registerModule(new RSSBasicModule(RDF_NAMESPACE_URI, "RDF module"), "rdf");
78 registerModule(new RSSBasicModule(RSS_1_0_NAMESPACE_URI, "RSS 1.0 module"), "rss");
80 RSSBasicModule dcModule = new RSSBasicModule(DUBLINCORE_NAMESPACE_URI, "Dublin Core RSS module 1.1");
81 dcModule.addProperty("date", RSSBasicModule.W3CDTF_PROPERTY_TYPE);
82 registerModule(dcModule, "dc");
84 registerModule(new RSSBasicModule(EVENT_NAMESPACE_URI, "Event RSS module"), "ev");
85 registerModule(new RSSBasicModule(TAXONOMY_NAMESPACE_URI, "Taxonomy RSS module"), "taxo");
88 public void registerModule(RSSModule aModule, String aPrefix) {
90 namespaceURItoModule.put(aModule.getNamespaceURI(), aModule);
91 moduleToPrefix.put(aModule, aPrefix);
94 public RSSData parseInputStream(InputStream aStream) throws RSSExc, RSSFailure {
96 XMLReader xmlReader = new XMLReader(true);
97 RSSData result = new RSSData();
98 xmlReader.parseInputStream(aStream, new RootSectionHandler(result));
102 catch (Throwable t) {
103 throw new RSSFailure(t);
107 public RSSData parseUrl(String anUrl) throws RSSExc, RSSFailure {
109 InputStream inputStream = (InputStream) new URL(anUrl).getContent(new Class[] {InputStream.class});
111 if (inputStream==null)
112 throw new RSSExc("RSSChannel.parseUrl: Can't get url content");
114 return parseInputStream(inputStream);
116 catch (Throwable t) {
117 throw new RSSFailure(t);
121 private class RootSectionHandler extends XMLReader.AbstractSectionHandler {
122 private RSSData data;
124 public RootSectionHandler(RSSData aData) {
128 public XMLReader.SectionHandler startElement(XMLReader.XMLName aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
129 if (aTag.getLocalName().equals("RDF")) {
130 return new RDFSectionHandler(data);
133 throw new XMLReader.XMLReaderFailure(new RSSExc("'RDF' tag expected"));
136 public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
139 public void characters(String aCharacters) throws XMLReader.XMLReaderExc {
140 if (aCharacters.trim().length()>0)
141 throw new XMLReader.XMLReaderExc("No character data allowed here");
144 public void finishSection() throws XMLReader.XMLReaderExc {
148 private class RDFSectionHandler extends XMLReader.AbstractSectionHandler {
149 private RSSData data;
152 public RDFSectionHandler(RSSData aData) {
156 public XMLReader.SectionHandler startElement(XMLReader.XMLName aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
157 String identifier = (String) anAttributes.get(RDF_ABOUT_PARAMETER);
158 String rdfClass = makeQualifiedName(aTag);
160 return new RDFResourceSectionHandler(rdfClass, identifier);
163 public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
164 if (aHandler instanceof RDFResourceSectionHandler) {
165 data.addResource(((RDFResourceSectionHandler) aHandler).getResource());
169 public void characters(String aCharacters) throws XMLReader.XMLReaderExc {
170 if (aCharacters.trim().length()>0)
171 throw new XMLReader.XMLReaderExc("No character data allowed here");
174 public void finishSection() throws XMLReader.XMLReaderExc {
178 private XMLReader.SectionHandler makePropertyValueSectionHandler(XMLReader.XMLName aTag, Map anAttributes) {
179 RSSModule module = (RSSModule) namespaceURItoModule.get(aTag.getNamespaceURI());
181 if (aTag.getLocalName().equals("date"))
186 RSSModule.RSSModuleProperty property = module.getPropertyForName(aTag.getLocalName());
188 if (property!=null) {
189 switch (property.getType()) {
191 RSSModule.PCDATA_PROPERTY_TYPE:
192 return new PCDATASectionHandler();
194 RSSModule.RDFCOLLECTION_PROPERTY_TYPE:
195 return new RDFCollectionSectionHandler();
197 // RSSModule.RDF_PROPERTY_TYPE:
198 // return new RDFValueSectionHandler();
200 RSSModule.W3CDTF_PROPERTY_TYPE:
201 return new DateSectionHandler();
207 return new FlexiblePropertyValueSectionHandler();
210 private String makeQualifiedName(XMLReader.XMLName aName) {
211 String result=aName.getLocalName();
212 RSSModule module = (RSSModule) namespaceURItoModule.get(aName.getNamespaceURI());
214 String prefix = (String) moduleToPrefix.get(module);
216 if (prefix!=null && prefix.length()>0)
217 result = prefix+":"+result;
223 private class RDFResourceSectionHandler extends XMLReader.AbstractSectionHandler {
224 private String image;
225 private XMLReader.XMLName currentTag;
226 private RDFResource resource;
228 public RDFResourceSectionHandler(String anRDFClass, String anIdentifier) {
229 resource = new RDFResource(anRDFClass, anIdentifier);
232 public XMLReader.SectionHandler startElement(XMLReader.XMLName aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
235 return makePropertyValueSectionHandler(aTag, anAttributes);
238 public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
239 if (aHandler instanceof PropertyValueSectionHandler) {
240 resource.set(makeQualifiedName(currentTag), ( (PropertyValueSectionHandler) aHandler).getValue());
244 public void characters(String aCharacters) throws XMLReader.XMLReaderExc {
245 if (aCharacters.trim().length()>0)
246 throw new XMLReader.XMLReaderExc("No character data allowed here");
249 public void finishSection() throws XMLReader.XMLReaderExc {
252 public RDFResource getResource() {
257 private abstract class PropertyValueSectionHandler extends XMLReader.AbstractSectionHandler {
258 public abstract Object getValue();
261 private class FlexiblePropertyValueSectionHandler extends PropertyValueSectionHandler {
262 private StringBuffer stringData;
263 private Object structuredData;
265 public FlexiblePropertyValueSectionHandler() {
266 stringData = new StringBuffer();
270 public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
271 if (aTag.equals(RDF_SEQUENCE_TAG))
272 return new RDFSequenceSectionHandler();
274 return new DiscardingSectionHandler();
277 public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
278 if (aHandler instanceof RDFSequenceSectionHandler) {
279 structuredData= ((RDFSequenceSectionHandler) aHandler).getItems();
283 public void characters(String aCharacters) throws XMLReader.XMLReaderExc {
284 stringData.append(aCharacters);
287 public void finishSection() throws XMLReader.XMLReaderExc {
290 public String getData() {
291 return stringData.toString();
294 public Object getValue() {
295 if (structuredData==null)
296 return stringData.toString();
298 return structuredData;
302 private class RDFCollectionSectionHandler extends PropertyValueSectionHandler {
305 public RDFCollectionSectionHandler() {
306 items = new Vector();
309 public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
310 if (aTag.equals(RDF_SEQUENCE_TAG))
311 return new RDFSequenceSectionHandler();
313 return new DiscardingSectionHandler();
316 public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
317 if (aHandler instanceof RDFSequenceSectionHandler) {
318 items.addAll(((RDFSequenceSectionHandler) aHandler).getItems());
322 public void characters(String aCharacters) throws XMLReader.XMLReaderExc {
323 if (aCharacters.trim().length()>0)
324 throw new XMLReader.XMLReaderExc("No character data allowed here");
327 public void finishSection() throws XMLReader.XMLReaderExc {
330 public List getItems() {
334 public Object getValue() {
339 private class PCDATASectionHandler extends PropertyValueSectionHandler {
340 private StringBuffer data;
342 public PCDATASectionHandler() {
343 data = new StringBuffer();
346 public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
347 throw new XMLReader.XMLReaderFailure(new RSSExc("No subtags allowed here"));
350 public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
353 public void characters(String aCharacters) throws XMLReader.XMLReaderExc {
354 data.append(aCharacters);
357 public void finishSection() throws XMLReader.XMLReaderExc {
360 public String getData() {
361 return data.toString();
364 public Object getValue() {
365 return data.toString();
369 private class DateSectionHandler extends PropertyValueSectionHandler {
370 private StringBuffer data;
372 public DateSectionHandler() {
373 data = new StringBuffer();
376 public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
377 throw new XMLReader.XMLReaderFailure(new RSSExc("No subtags allowed here"));
380 public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
383 public void characters(String aCharacters) throws XMLReader.XMLReaderExc {
384 data.append(aCharacters);
387 public void finishSection() throws XMLReader.XMLReaderExc {
390 private final static String SPACE = "[\t\n\r ]*";
391 private final static String NUMBER = "[0-9]*";
392 private final static String SIGN = "[-+]";
394 public Object getValue() {
396 String expression = data.toString().trim();
397 SimpleParser parser = new SimpleParser(expression);
405 year = parser.parse(NUMBER);
407 month = parser.parse(NUMBER);
409 day = parser.parse(NUMBER);
411 hour = parser.parse(NUMBER);
413 minutes = parser.parse(NUMBER);
415 SimpleDateFormat d = new SimpleDateFormat("yyyy-MM-dd HH:mm");
417 expression = year + "-" + month + "-" + day + " " + hour + ":" + minutes;
419 System.out.println(expression);
421 Date result = d.parse(expression);
425 catch (Throwable t) {
432 private class RDFSequenceSectionHandler extends XMLReader.AbstractSectionHandler {
435 public RDFSequenceSectionHandler() {
436 items = new Vector();
439 public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
440 if (aTag.equals("rdf:li")) {
441 String item = (String) anAttributes.get("rdf:resource");
447 return new DiscardingSectionHandler();
450 public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
453 public void characters(String aCharacters) throws XMLReader.XMLReaderExc {
456 public void finishSection() throws XMLReader.XMLReaderExc {
459 public List getItems() {
464 private class RDFLiteralSectionHandler extends PropertyValueSectionHandler {
465 private StringBuffer data;
468 public RDFLiteralSectionHandler() {
469 data = new StringBuffer();
472 protected StringBuffer getData() {
476 public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
478 data.append("<"+tag+">");
480 return new RDFLiteralSectionHandler();
483 public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
484 data.append(((RDFLiteralSectionHandler) aHandler).getData());
485 data.append("</"+tag+">");
488 public void characters(String aCharacters) throws XMLReader.XMLReaderExc {
489 data.append(aCharacters);
492 public void finishSection() throws XMLReader.XMLReaderExc {
495 public Object getValue() {
496 return data.toString();
500 private class DiscardingSectionHandler extends XMLReader.AbstractSectionHandler {
501 public XMLReader.SectionHandler startElement(String aTag, Map anAttributes) throws XMLReader.XMLReaderExc {
505 public void endElement(XMLReader.SectionHandler aHandler) throws XMLReader.XMLReaderExc {
508 public void characters(String aCharacters) throws XMLReader.XMLReaderExc {
511 public void finishSection() throws XMLReader.XMLReaderExc {