From 783cc6bc707971292a7a53c65b15160a28f4e52d Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Tue, 28 Feb 2017 23:53:06 -0500 Subject: [PATCH] Add ability to import multiple xmltv.xml files --- rcrdit.cfg.example.xml | 7 +- .../com/moparisthebest/rcrdit/RcrdIt.java | 9 ++- .../com/moparisthebest/rcrdit/xmltv/Tv.java | 75 ++++++++++++------- 3 files changed, 56 insertions(+), 35 deletions(-) diff --git a/rcrdit.cfg.example.xml b/rcrdit.cfg.example.xml index 2cdedba..8b8a1d7 100644 --- a/rcrdit.cfg.example.xml +++ b/rcrdit.cfg.example.xml @@ -22,8 +22,11 @@ jdbc:mysql://localhost:3306/rcrdit?user=rcrdit&password=rcrdit http://localhost:8080/rcrdit/ - - /etc/xmltv.xml + + + /etc/xmltv.xml + /etc/xmltv-other.xml + 2.1 diff --git a/src/main/java/com/moparisthebest/rcrdit/RcrdIt.java b/src/main/java/com/moparisthebest/rcrdit/RcrdIt.java index 2079790..003b905 100644 --- a/src/main/java/com/moparisthebest/rcrdit/RcrdIt.java +++ b/src/main/java/com/moparisthebest/rcrdit/RcrdIt.java @@ -79,7 +79,8 @@ public class RcrdIt extends ResourceConfig implements AutoCloseable { // config items private final Tuners tuners; private final Set allChannels; - private final String databaseUrl, xmltvPath; + private final List xmltvPaths; + private final String databaseUrl; private final TimerTask scheduleTask = new ScheduleTask(); private final Timer timer = new Timer(); @@ -102,7 +103,7 @@ public class RcrdIt extends ResourceConfig implements AutoCloseable { serverUri += "/"; this.serverUri = serverUri; - this.xmltvPath = rcrdit.getChild("xmltvPath").getValue(); + this.xmltvPaths = Arrays.stream(rcrdit.getChild("xmltvPaths").getChildren("xmltvPath")).map(XmlElement::getValue).collect(Collectors.toList()); this.allChannels = Arrays.stream(rcrdit.getChild("channels").getChildren("channel")).map(XmlElement::getValue).collect(Collectors.toSet()); final List tuners = new ArrayList<>(); @@ -370,7 +371,7 @@ public class RcrdIt extends ResourceConfig implements AutoCloseable { @Override public void run() { try { - schedule = Tv.readSchedule(xmltvPath, allChannels); + schedule = Tv.readSchedule(xmltvPaths, allChannels); //System.out.println(schedule); // todo: only re-calcuate if schedule changed reCalculateSchedule(); @@ -412,7 +413,7 @@ public class RcrdIt extends ResourceConfig implements AutoCloseable { "tuners=" + tuners + ", allChannels=" + allChannels + ", databaseUrl='" + databaseUrl + '\'' + - ", xmltvPath='" + xmltvPath + '\'' + + ", xmltvPaths='" + xmltvPaths + '\'' + '}'; } diff --git a/src/main/java/com/moparisthebest/rcrdit/xmltv/Tv.java b/src/main/java/com/moparisthebest/rcrdit/xmltv/Tv.java index 12afc65..55b51bb 100644 --- a/src/main/java/com/moparisthebest/rcrdit/xmltv/Tv.java +++ b/src/main/java/com/moparisthebest/rcrdit/xmltv/Tv.java @@ -76,7 +76,7 @@ public class Tv { '}'; } - public static Tv readSchedule(final String resource, final Set allChannels) throws Exception { + public static Tv readSchedule(final List resources, final Set allChannels) throws Exception { //try /*(InputStream is = new FileInputStream(resource))*/ { /* ObjectMapper mapper = new XmlMapper(new XmlFactory()); // create once, reuse @@ -107,39 +107,56 @@ public class Tv { .withZone(ZoneId.systemDefault()) .withResolverStyle(ResolverStyle.STRICT); - final XmlElement tv = AbstractXmlElement.getFactory().readFromFile(resource); - //System.out.print(tv); - final List channels = new ArrayList<>(); - final Map chanIdToChanName = new HashMap<>(); - for (final XmlElement chan : tv.getChildren("channel")) { - final Channel channel = new Channel(chan.getAttribute("id"), Arrays.stream(chan.getChildren("display-name")).map(XmlElement::getValue).collect(Collectors.toSet())); - for (final String displayName : channel.getDisplayNames()) - if (allChannels == null || allChannels.isEmpty() || allChannels.contains(displayName)) { - chanIdToChanName.put(channel.getId(), displayName); - channels.add(channel); - break; - } - } - final List programs = new ArrayList<>(); - final Instant now = Instant.now().truncatedTo(ChronoUnit.MINUTES); - Instant lastEndTime = now; - for (final XmlElement prog : tv.getChildren("programme")) { - final String chanId = prog.getAttribute("channel"); - final String chanName = chanIdToChanName.get(chanId); - if (chanName != null) { - final Instant stop = INSTANT.parse(prog.getAttribute("stop"), Instant::from); - if (stop.isAfter(now)) { - programs.add(new Program(INSTANT.parse(prog.getAttribute("start"), Instant::from), stop, chanId, chanName, - val(prog.getChild("title")), val(prog.getChild("sub-title")), val(prog.getChild("desc")), val(prog.getChild("episode-num")), - val(prog.getChild("date")), val(prog.getChild("category")), prog.getChild("previously-shown") != null - )); - if (stop.isAfter(lastEndTime)) - lastEndTime = stop; + Instant lastEndTime = Instant.now(); + + for(final String resource : resources) { + final XmlElement tv = AbstractXmlElement.getFactory().readFromFile(resource); + //System.out.print(tv); + + final Map chanIdToChanName = new HashMap<>(); + for (final XmlElement chan : tv.getChildren("channel")) { + final Channel channel = new Channel(chan.getAttribute("id"), Arrays.stream(chan.getChildren("display-name")).map(XmlElement::getValue).collect(Collectors.toSet())); + for (final String displayName : channel.getDisplayNames()) + if (allChannels == null || allChannels.isEmpty() || allChannels.contains(displayName)) { + chanIdToChanName.put(channel.getId(), displayName); + channels.add(channel); + break; + } + } + + final Instant now = Instant.now().truncatedTo(ChronoUnit.MINUTES); + for (final XmlElement prog : tv.getChildren("programme")) { + final String chanId = prog.getAttribute("channel"); + final String chanName = chanIdToChanName.get(chanId); + if (chanName != null) { + final Instant stop = INSTANT.parse(prog.getAttribute("stop"), Instant::from); + if (stop.isAfter(now)) { + programs.add(new Program(INSTANT.parse(prog.getAttribute("start"), Instant::from), stop, chanId, chanName, + val(prog.getChild("title")), val(prog.getChild("sub-title")), val(prog.getChild("desc")), val(prog.getChild("episode-num")), + val(prog.getChild("date")), val(prog.getChild("category")), prog.getChild("previously-shown") != null + )); + if (stop.isAfter(lastEndTime)) + lastEndTime = stop; + } } } } + + // de-duplicate, keep channels in order, programs don't matter since we will sort anyway... + // in theory we should only have to do this if resources.size() > 1, but who knows what kind of crazy xml will appear... + { + final Set dedup = new LinkedHashSet<>(channels); + channels.clear(); + channels.addAll(dedup); + } + { + final Set dedup = new HashSet<>(programs); + programs.clear(); + programs.addAll(dedup); + } + programs.sort(ProgramTimeComparator.instance); return new Tv(channels, programs, lastEndTime); /*