package org.vanbest.xmltv;
+import java.net.URL;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
public class Programme {
class Title {
List<String> commentators;
List<String> guests;
}
- public Channel channel; // required
+ class Length {
+ TimeUnit unit;
+ int count;
+ }
+ class Icon {
+ URL url;
+ int width;
+ int height;
+ }
+ class Episode {
+ String episode;
+ String system; // onscreen or xmltv_ns
+ }
+ class Video {
+ boolean present;
+ boolean colour;
+ String aspect; // eg. 16:9, 4:3
+ String quality; // eg. 'HDTV', '800x600'.
+ }
+ class Audio {
+ boolean present;
+ String stereo; // 'mono','stereo','dolby','dolby digital','bilingual' or 'surround'.
+ }
public Date startTime; // required
public Date endTime;
public Date pdcStart;
public Date vpsStart;
public String showview;
public String videoplus;
+ public Channel channel; // required
public String clumpidx;
public List<Title> titles; // at least one
public List<Title> categories;
Title language;
Title origLanguage;
+ Length length;
+ public List<Icon> icons;
+ public List<URL> urls;
+ public List<Title> countries;
+ public List<Episode> episodes;
+ public Video video;
+ public Audio audio;
+ /*
+ previously-shown?, premiere?, last-chance?, new?,
+ subtitles*, rating*, star-rating*, review*
+ */
+ public void addTitle(String title) {
+ addTitle(title, null);
+ }
+ public void addTitle(String title, String lang) {
+ if(titles==null) titles = new ArrayList<Title>();
+ Title t = new Title();
+ t.title = title;
+ t.lang = lang;
+ titles.add(t);
+ }
+ public void addCategory(String category) {
+ addCategory(category, null);
+ }
+ public void addCategory(String category, String lang) {
+ if(categories==null) categories = new ArrayList<Title>();
+ Title t = new Title();
+ t.title = category;
+ t.lang = lang;
+ categories.add(t);
+ }
+
+ public void serialize(XMLStreamWriter writer) throws XMLStreamException {
+ DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss Z");
+
+ writer.writeStartElement("programme");
+ if(startTime != null) writer.writeAttribute("start", df.format(startTime));
+ if(channel != null) writer.writeAttribute("channel", ""+channel.id);
+ if(titles != null) {
+ for(Title title: titles) {
+ writer.writeStartElement("title");
+ if (title.lang != null) writer.writeAttribute("lang", title.lang);
+ if (title.title != null) writer.writeCharacters(title.title);
+ writer.writeEndElement();
+ }
+ }
+ if(categories != null) {
+ for(Title category: categories) {
+ writer.writeStartElement("category");
+ if (category.lang != null) writer.writeAttribute("lang", category.lang);
+ if (category.title != null) writer.writeCharacters(category.title);
+ writer.writeEndElement();
+ }
+ }
+/* for(Icon i: icons) {
+ i.serialize(writer);
+ }
+ for(String url: urls) {
+ writer.writeStartElement("url");
+ writer.writeCharacters(url);
+ writer.writeEndElement();
+ }
+*/
+ writer.writeEndElement();
+ writer.writeCharacters(System.getProperty("line.separator"));
+ }
}
import java.text.ParseException;\r
import java.text.SimpleDateFormat;\r
import java.util.ArrayList;\r
+import java.util.Calendar;\r
import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
import java.util.List;\r
+import java.util.Map;\r
import java.util.Set;\r
\r
import javax.xml.parsers.DocumentBuilderFactory;\r
import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.parsers.SAXParser;\r
+import javax.xml.parsers.SAXParserFactory;\r
import javax.xml.stream.XMLEventFactory;\r
import javax.xml.stream.XMLOutputFactory;\r
import javax.xml.stream.XMLStreamWriter;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
\r
import net.sf.json.JSON;\r
import net.sf.json.JSONArray;\r
import org.vanbest.xmltv.EPGSource.Stats;\r
import org.w3c.dom.Document;\r
import org.w3c.dom.Element;\r
+import org.w3c.dom.Node;\r
+import org.w3c.dom.NodeList;\r
import org.xml.sax.SAXException;\r
\r
public class RTL extends AbstractEPGSource implements EPGSource {\r
\r
- static final String programme_url="http://www.rtl.nl/active/epg_data/dag_data/";\r
- static final String detail_url="http://www.rtl.nl/active/epg_data/uitzending_data/";\r
- static final String icon_url="http://www.rtl.nl/service/gids/components/vaste_componenten/";\r
+ private static final String programme_url="http://www.rtl.nl/active/epg_data/dag_data/";\r
+ private static final String detail_url="http://www.rtl.nl/active/epg_data/uitzending_data/";\r
+ private static final String icon_url="http://www.rtl.nl/service/gids/components/vaste_componenten/";\r
+ private static final String xmltv_channel_suffix = ".rtl.nl";\r
+ private static final int MAX_PROGRAMMES_PER_DAY = 5;\r
+ \r
+ class RTLException extends Exception {\r
+ public RTLException(String s) {\r
+ super(s);\r
+ }\r
+ }\r
\r
- Stats stats = new Stats();\r
-\r
public RTL(Config config) {\r
super(config);\r
}\r
JSONObject o = JSONObject.fromObject( json );\r
for( Object k: o.keySet()) {\r
JSONArray j = (JSONArray) o.get(k);\r
- String id = k.toString().replaceAll("^Z", ""); // remove initial Z\r
+ String id = genericChannelId(k.toString());\r
String name = (String) j.get(0);\r
String icon = icon_url+id+".gif";\r
\r
return result;\r
}\r
\r
- protected void fetchDay(int day) throws Exception {\r
- URL url = new URL(programme_url+day);\r
- String xmltext = fetchURL(url);\r
- System.out.println(xmltext);\r
- Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(url.openStream());\r
- Element root = xml.getDocumentElement();\r
- Date date = new SimpleDateFormat("yyyy-MM-dd").parse(root.getAttribute("date"));\r
- System.out.println("date: " + date);\r
- String json = root.getTextContent();\r
- System.out.println("json: " + json);\r
- JSONObject o = JSONObject.fromObject( json );\r
- for( Object k: o.keySet()) {\r
- JSONArray j = (JSONArray) o.get(k);\r
- System.out.println(k.toString()+": "+j.toString());\r
- System.out.println("Channel name:" + j.get(0));\r
- for (int i=1; i<j.size() && i<3; i++) {\r
- JSONArray p = (JSONArray) j.get(i);\r
- String starttime = p.getString(0);\r
- String title = p.getString(1);\r
- String id = p.getString(2);\r
- String quark1 = p.getString(3);\r
- String quark2 = p.getString(4);\r
- System.out.println(" starttime: " + starttime);\r
- System.out.println(" title: " + title);\r
- System.out.println(" id: " + id);\r
- fetchDetail(id);\r
- }\r
- }\r
+ private String genericChannelId(String jsonid) {\r
+ return jsonid.replaceAll("^Z", "")+xmltv_channel_suffix; // remove initial Z\r
}\r
\r
/*\r
* </uitzending_data>\r
\r
*/\r
- private void fetchDetail(String id) throws Exception {\r
- // TODO Auto-generated method stub\r
- URL url = new URL(detail_url+id);\r
- String xmltext = fetchURL(url);\r
- System.out.println(xmltext);\r
+ private void fetchDetail(Programme prog, String id) throws Exception {\r
+ URL url = detailUrl(id);\r
Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(url.openStream());\r
Element root = xml.getDocumentElement();\r
+ if (root.hasAttributes()) {\r
+ System.out.println("Unknown attributes for RTL detail root node");\r
+ }\r
+ NodeList nodes = root.getChildNodes();\r
+ for( int i=0; i<nodes.getLength(); i++) {\r
+ Node n = nodes.item(i);\r
+ System.out.println(n.getNodeName());\r
+ if (!n.getNodeName().equals("uitzending_data_item")) {\r
+ System.out.println("Ignoring RTL detail, tag " + n.getNodeName() +", full xml:");\r
+ Transformer t = TransformerFactory.newInstance().newTransformer();\r
+ t.transform(new DOMSource(xml),new StreamResult(System.out));\r
+ System.out.println();\r
+ continue;\r
+ }\r
+ // we have a uitzending_data_item node\r
+ NodeList subnodes = n.getChildNodes();\r
+ for( int j=0; j<subnodes.getLength(); j++) {\r
+ try {\r
+ handleNode(prog, subnodes.item(j));\r
+ } catch (RTLException e) {\r
+ System.out.println(e.getMessage());\r
+ Transformer t = TransformerFactory.newInstance().newTransformer();\r
+ t.transform(new DOMSource(xml),new StreamResult(System.out));\r
+ System.out.println();\r
+ continue;\r
+ }\r
+ }\r
+ }\r
}\r
\r
- @Override\r
- public Set<TvGidsProgramme> getProgrammes(List<Channel> channels, int day,\r
+ \r
+ private void handleNode(Programme prog, Node n) throws RTLException {\r
+ if (n.getNodeType() != Node.ELEMENT_NODE) {\r
+ throw new RTLException("Ignoring non-element node " + n.getNodeName());\r
+ }\r
+ Element e = (Element)n;\r
+ switch (e.getTagName()) {\r
+ case "genre":\r
+ prog.addCategory(config.translateCategory(e.getTextContent()));\r
+ break;\r
+ default:\r
+ throw new RTLException("Ignoring unknown tag " + n.getNodeName() + ", content: \"" + e.getTextContent() + "\"");\r
+ }\r
+ //prog.endTime = parseTime(date, root.)\r
+ }\r
+\r
+ public Set<Programme> getProgrammes1(List<Channel> channels, int day,\r
boolean fetchDetails) throws Exception {\r
- // TODO Auto-generated method stub\r
- return null;\r
+ Set<Programme> result = new HashSet<Programme>();\r
+ Map<String,Channel> channelMap = new HashMap<String,Channel>();\r
+ for(Channel c: channels) {\r
+ if (c.enabled) channelMap.put(c.id, c);\r
+ }\r
+ URL url = programmeUrl(day);\r
+ //String xmltext = fetchURL(url);\r
+ //System.out.println(xmltext);\r
+ Thread.sleep(config.niceMilliseconds);\r
+ Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(url.openStream());\r
+ Element root = xml.getDocumentElement();\r
+ Date date = new SimpleDateFormat("yyyy-MM-dd").parse(root.getAttribute("date"));\r
+ System.out.println("date: " + date);\r
+ String json = root.getTextContent();\r
+ System.out.println("json: " + json);\r
+ JSONObject o = JSONObject.fromObject( json );\r
+ for( Object k: o.keySet()) {\r
+ String id = genericChannelId(k.toString());\r
+ if(!channelMap.containsKey(id)) {\r
+ System.out.println("Skipping programmes for channel " + id);\r
+ continue;\r
+ }\r
+ JSONArray j = (JSONArray) o.get(k);\r
+ System.out.println(k.toString()+": "+j.toString());\r
+ //System.out.println("Channel name:" + j.get(0));\r
+ for (int i=1; i<j.size() && i<MAX_PROGRAMMES_PER_DAY; i++) {\r
+ JSONArray p = (JSONArray) j.get(i);\r
+ String starttime = p.getString(0);\r
+ String title = p.getString(1);\r
+ String programme_id = p.getString(2);\r
+ String quark1 = p.getString(3);\r
+ String quark2 = p.getString(4);\r
+ Programme prog = new Programme();\r
+ prog.addTitle(title);\r
+ Date start = parseTime(date, starttime);\r
+ prog.startTime = start;\r
+ prog.channel = channelMap.get(id);\r
+ fetchDetail(prog, programme_id);\r
+ result.add(prog);\r
+ }\r
+ }\r
+ return result;\r
}\r
\r
- @Override\r
- public Stats getStats() {\r
- // TODO Auto-generated method stub\r
- return stats;\r
+ private Date parseTime(Date date, String time) {\r
+ Calendar result = Calendar.getInstance();\r
+ result.setTime(date);\r
+ String[] parts = time.split(":");\r
+ if(parts.length != 2) {\r
+ \r
+ }\r
+ int hour = Integer.parseInt(parts[0]);\r
+ if (hour<4) {\r
+ result.add(Calendar.DAY_OF_MONTH, 1); // early tomorrow morning\r
+ }\r
+ result.set(Calendar.HOUR_OF_DAY, hour);\r
+ result.set(Calendar.MINUTE, Integer.parseInt(parts[1]));\r
+ return result.getTime();\r
+ }\r
+\r
+ private static URL programmeUrl(int day) throws MalformedURLException {\r
+ return new URL(programme_url+day);\r
+ }\r
+ \r
+ private static URL detailUrl(String id) throws Exception {\r
+ return new URL(detail_url+id);\r
}\r
\r
/**\r
* @param args\r
*/\r
public static void main(String[] args) {\r
- RTL rtl = new RTL();\r
+ Config config = Config.getDefaultConfig();\r
+ RTL rtl = new RTL(config);\r
try {\r
- // rtl.fetchDay(1);\r
List<Channel> channels = rtl.getChannels();\r
System.out.println("Channels: " + channels);\r
XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(System.out);\r
writer.writeCharacters("\n");\r
writer.writeStartElement("tv");\r
for(Channel c: channels) {c.serialize(writer);}\r
+ Set<Programme> programmes = rtl.getProgrammes1(channels.subList(0, 3), 0, true);\r
+ for(Programme p: programmes) {p.serialize(writer);}\r
writer.writeEndElement();\r
writer.writeEndDocument();\r
writer.flush();\r
+ rtl.close();\r
} catch (Exception e) {\r
// TODO Auto-generated catch block\r
e.printStackTrace();\r
}\r
}\r
\r
+ @Override\r
+ public Set<TvGidsProgramme> getProgrammes(List<Channel> channels, int day,\r
+ boolean fetchDetails) throws Exception {\r
+ // TODO Refactor EPGSource to return Programme instead of TvGidsProgramme\r
+ return null;\r
+ }\r
+\r
\r
}\r