rcrdit/src/main/java/com/moparisthebest/rcrdit/xmltv/Tv.java

162 lines
6.3 KiB
Java

/*
* rcrdit records TV programs from TV tuners
* Copyright (C) 2017 Travis Burtrum
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.moparisthebest.rcrdit.xmltv;
import org.moparscape.xml.impl.AbstractXmlElement;
import org.moparscape.xml.impl.XmlElement;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.time.format.SignStyle;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import static java.time.temporal.ChronoField.*;
/**
* Created by mopar on 2/17/17.
*/
//@JacksonXmlRootElement(localName = "tv")
//@JsonIgnoreProperties(ignoreUnknown = true)
public class Tv {
//@JsonProperty("channel")
//@JacksonXmlElementWrapper(localName = "channel", useWrapping = false)
private final List<Channel> channels;
//@JacksonXmlProperty(localName = "programme")
//@JacksonXmlElementWrapper(useWrapping = false)
private final List<Program> programs;
private final Instant lastEndTime;
public Tv(final List<Channel> channels, final List<Program> programs, final Instant lastEndTime) {
this.channels = Collections.unmodifiableList(channels);
this.programs = Collections.unmodifiableList(programs);
this.lastEndTime = lastEndTime;
}
public List<Channel> getChannels() {
return channels;
}
public List<Program> getPrograms() {
return programs;
}
public Instant getLastEndTime() {
return lastEndTime;
}
@Override
public String toString() {
return "Tv{" +
"channels=" + channels +
", programs=" + programs +
", lastEndTime=" + lastEndTime +
'}';
}
public static Tv readSchedule(final String resource, final Set<String> allChannels) throws Exception {
//try /*(InputStream is = new FileInputStream(resource))*/ {
/*
ObjectMapper mapper = new XmlMapper(new XmlFactory()); // create once, reuse
//mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
ObjectReader or = mapper.readerFor(Tv.class);
return or.readValue(is);
ObjectMapper objectMapper = new XmlMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
//final Object ret = objectMapper.readValue(is, Tv.class);
final byte[] xml = Files.readAllBytes(new File(resource).toPath());
System.out.println(new String(xml));
final Object ret = objectMapper.readValue(xml, Tv.class);
objectMapper.writeValue(new File("out.xml"), ret);
*/
final DateTimeFormatter INSTANT = new DateTimeFormatterBuilder()
.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
.appendValue(MONTH_OF_YEAR, 2)
.appendValue(DAY_OF_MONTH, 2)
.appendValue(HOUR_OF_DAY, 2)
.appendValue(MINUTE_OF_HOUR, 2)
.appendValue(SECOND_OF_MINUTE, 2)
.appendLiteral(' ')
.appendOffset("+HHMM", "0000")
.parseStrict()
.toFormatter(Locale.US)
.withZone(ZoneId.systemDefault())
.withResolverStyle(ResolverStyle.STRICT);
final XmlElement tv = AbstractXmlElement.getFactory().readFromFile(resource);
//System.out.print(tv);
final List<Channel> channels = new ArrayList<>();
final Map<String, String> 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<Program> 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;
}
}
}
programs.sort(ProgramTimeComparator.instance);
return new Tv(channels, programs, lastEndTime);
/*
} catch (Exception e) {
e.printStackTrace();
}
//System.out.println("menu: "+Arrays.toString(ret));
return null;
*/
}
private static String val(final XmlElement x) {
try {
return x == null ? null : x.getValue();
} catch (Exception e) {
return null;
}
}
}