1 package user.jobengine.server.steps;
\r
4 import java.io.IOException;
\r
5 import java.nio.file.FileVisitResult;
\r
6 import java.nio.file.Files;
\r
7 import java.nio.file.Path;
\r
8 import java.nio.file.Paths;
\r
9 import java.nio.file.SimpleFileVisitor;
\r
10 import java.nio.file.attribute.BasicFileAttributes;
\r
11 import java.text.ParseException;
\r
12 import java.text.SimpleDateFormat;
\r
13 import java.util.Calendar;
\r
14 import java.util.Date;
\r
15 import java.util.List;
\r
17 import org.apache.commons.lang.StringUtils;
\r
18 import org.apache.logging.log4j.LogManager;
\r
19 import org.apache.logging.log4j.Logger;
\r
20 import org.apache.logging.log4j.Marker;
\r
22 import com.ibm.nosql.json.api.BasicDBObject;
\r
23 import com.ibm.nosql.json.api.DB;
\r
24 import com.ibm.nosql.json.api.DBCollection;
\r
25 import com.ibm.nosql.json.api.DBObject;
\r
27 import user.commons.CalendarUtils;
\r
28 import user.commons.nosql.NoSQLUtils;
\r
29 import user.commons.octopus.IOctopusAPI;
\r
30 import user.commons.octopus.OctopusAPI;
\r
31 import user.jobengine.server.IJobEngine;
\r
32 import user.jobengine.server.IJobRuntime;
\r
34 public class RecordingsArchiveItemBuilderStep extends JobStep {
\r
35 private static final String MEDIATYPE = "Visszarögzített";
\r
36 private static final Logger logger = LogManager.getLogger();
\r
37 private static final String STATUSFOLDER = ".STATUS";
\r
38 private static final String LXFEXT = ".lxf";
\r
39 private static final String CATCHEDEXT = ".catched";
\r
40 private static final SimpleDateFormat startTimeformat = new SimpleDateFormat("HHmm");
\r
41 private static final SimpleDateFormat startDateformat = new SimpleDateFormat("yyMMdd");
\r
42 private static final String SCHEDULED_FORMAT = "yyyy.MM.dd HH:mm";
\r
44 private Marker marker;
\r
45 private DBCollection existingRecordings;
\r
47 private ArchiveItem createArchiveItem(Path mediaFilePath, Path catchedFilePath) {
\r
48 ArchiveItem result = null;
\r
51 Date recordDate = startDateformat.parse(mediaFilePath.getParent().toFile().getName());
\r
52 String clipName = mediaFilePath.toFile().getName();
\r
53 Date scheduledStart = getScheduledStart(clipName, recordDate);
\r
54 IOctopusAPI octopusAPI = new OctopusAPI();
\r
56 DBObject rundown = octopusAPI.getRundown(scheduledStart);
\r
57 if (rundown == null) {
\r
58 logger.error(marker, "A '{}' anyaghoz nem található tükör '{}' kezdéssel, ezért nem archiválható.", clipName, scheduledStart);
\r
61 result = processRundow(octopusAPI, rundown);
\r
65 if (clipName.startsWith("1900")) {
\r
66 Calendar cal = CalendarUtils.createCalendar(scheduledStart);
\r
67 cal.add(Calendar.MINUTE, 5);
\r
68 rundown = octopusAPI.getRundown(cal.getTime());
\r
69 if (rundown == null) {
\r
70 logger.error(marker, "A '{}' anyaghoz nem található tükör '{}' kezdéssel, ezért nem archiválható.", clipName, scheduledStart);
\r
73 ArchiveItem item2 = processRundow(octopusAPI, rundown);
\r
77 result.setItemTitle(result.getItemTitle() + " + NAPIAKT");
\r
78 result.setMediaDescription(result.getMediaDescription() + "\r\n\r\n****** NAPIAKT ******\r\n\r\n" + item2.getMediaDescription());
\r
81 result.setMediaTitle(clipName);
\r
82 result.setMediaType(MEDIATYPE);
\r
83 result.setMediaFile(mediaFilePath.toString());
\r
84 result.setCatchedFile(catchedFilePath.toString());
\r
85 } catch (Exception e) {
\r
87 logger.error(getJobRuntime().getMarker(), "A metaadat nem elérhető. A rendszer üzenete: {}", e.getMessage());
\r
94 private void createCatchedFile(Path catchedFilePath) throws IOException {
\r
96 EscortFiles.ensureUNCFolder(catchedFilePath.getParent());
\r
97 Files.createFile(catchedFilePath);
\r
98 } catch (IOException e) {
\r
100 logger.error(marker, "A '{}' jelzőfájl nem hozható létre. A rendszer üzenete: {}", catchedFilePath, e.getMessage());
\r
106 public Object[] execute(String sourcePath, IJobEngine jobEngine, IJobRuntime jobRuntime) throws Exception {
\r
107 final ArchiveItem[] archiveItems = { null };
\r
108 DB db = NoSQLUtils.getNoSQLDB();
\r
109 existingRecordings = db.getCollection("tmp_existing_recordings");
\r
110 marker = getJobRuntime().getMarker();
\r
112 Files.walkFileTree(Paths.get(sourcePath), new SimpleFileVisitor<Path>() {
\r
115 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
\r
116 FileVisitResult result = FileVisitResult.SKIP_SUBTREE;
\r
118 if (dir.equals(Paths.get(sourcePath)) || "2017".equals(dir.toFile().getName().toUpperCase())
\r
119 || "2018".equals(dir.toFile().getName().toUpperCase()))
\r
120 result = FileVisitResult.CONTINUE;
\r
122 if ("2017".equals(dir.getParent().toFile().getName().toUpperCase())
\r
123 || "2018".equals(dir.getParent().toFile().getName().toUpperCase())) {
\r
125 startDateformat.parse(dir.toFile().getName());
\r
126 result = FileVisitResult.CONTINUE;
\r
127 } catch (ParseException e) {
\r
132 if (result == FileVisitResult.CONTINUE)
\r
138 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
\r
139 FileVisitResult result = FileVisitResult.TERMINATE;
\r
140 ArchiveItem item = null;
\r
142 item = processPathItem(file);
\r
143 } catch (IOException e) {
\r
144 logger.catching(e);
\r
145 logger.error(marker, "Az '{}' állomány feldolgozása sikertelen. A rendszer hibaüzenete: {}", file, e.getMessage());
\r
148 if (item == null) {
\r
149 result = FileVisitResult.CONTINUE;
\r
152 archiveItems[0] = item;
\r
159 } catch (Exception e) {
\r
160 logger.catching(e);
\r
161 logger.error(marker, "Az '{}' mappa elérése sikertelen. A rendszer hibaüzenete: {}", sourcePath, e.getMessage());
\r
165 ArchiveItem archiveItem = archiveItems[0];
\r
166 String targetFileName = null;
\r
168 if (archiveItem == null || archiveItem.getMediaFile() == null) {
\r
169 logger.warn(marker, "Az archiváló folyamat nem talált új anyagot.");
\r
170 throw new Exception("No media to archive");
\r
172 String mediaFile = archiveItem.getMediaFile();
\r
173 String name = new File(mediaFile).getName();
\r
174 int extPos = name.toLowerCase().lastIndexOf(LXFEXT);
\r
175 targetFileName = String.format("20%s-%s", Paths.get(mediaFile).getParent().getFileName(), name.substring(0, extPos));
\r
176 if (targetFileName.length() > 32) {
\r
177 targetFileName = targetFileName.substring(0, 28) + "_PGM";
\r
179 logger.info(marker, "Az archiváló folyamat az '{}' anyagot archiválja.", mediaFile);
\r
182 return new Object[] { archiveItem, targetFileName };
\r
185 private Date getScheduledStart(String clipName, Date recordDate) {
\r
187 if (StringUtils.isBlank(clipName)) {
\r
188 logger.warn(marker, "A fájlnak nincs neve, ezért nem archiválható.");
\r
191 if (recordDate == null) {
\r
192 logger.warn(marker, "Az '{}' fájl rögzítésének ideje nem meghatározható, ezért nem archiválható.", clipName);
\r
196 Date timePart = null;
\r
198 String clipNameTime = clipName.split("_")[0];
\r
199 timePart = startTimeformat.parse(clipNameTime);
\r
200 } catch (ParseException e) {
\r
201 logger.warn(marker, "A '{}' fájl neve nem időbélyeggel kezdődik, ezért nem archiválható.", clipName);
\r
204 return CalendarUtils.createCalendar(CalendarUtils.createCalendar(recordDate), timePart).getTime();
\r
207 private ArchiveItem processPathItem(Path mediaFilePath) throws IOException {
\r
208 File mediaFile = mediaFilePath.toFile();
\r
210 Path dotStorePath = Paths.get(mediaFilePath.getParent().toString(), STATUSFOLDER);
\r
211 Path catchedFilePath = Paths.get(dotStorePath.toString(), mediaFile.getName() + CATCHEDEXT);
\r
212 File catchedFile = catchedFilePath.toFile();
\r
213 if (catchedFile.exists()) {
\r
214 //logger.info("'{}' file is already catched", mediaFilePath);
\r
217 createCatchedFile(catchedFilePath);
\r
218 if (!catchedFile.exists()) {
\r
219 logger.warn("'{}' catchfile not exists.", catchedFilePath);
\r
223 if (mediaFile.isDirectory() || !mediaFile.getName().toLowerCase().endsWith(LXFEXT.toLowerCase())
\r
224 || mediaFilePath.getParent().toFile().getName().length() != 6 || !mediaFile.getName().toLowerCase().contains("_pgm_")) {
\r
225 logger.info("Skipping '{}'", mediaFilePath);
\r
229 ArchiveItem archiveItem = createArchiveItem(mediaFilePath, catchedFilePath);
\r
231 if (archiveItem == null) {
\r
232 logger.warn("'{}' has no metadata specified.", mediaFilePath);
\r
236 DBObject existingRecording = existingRecordings.findOne(new BasicDBObject("title", archiveItem.getItemTitle().substring(0, 16)));
\r
238 if (existingRecording != null) {
\r
239 logger.warn("'{}' already archived, skipping.", archiveItem.getItemTitle());
\r
243 if (StringUtils.isBlank(archiveItem.getItemHouseId())) {
\r
244 logger.warn("'{}' has no Item HouseID specified in metadata.", mediaFilePath);
\r
248 if (StringUtils.isBlank(archiveItem.getItemTitle())) {
\r
249 logger.warn("'{}' has no Item Title specified in metadata.", mediaFilePath);
\r
253 if (StringUtils.isBlank(archiveItem.getMediaHouseId())) {
\r
254 logger.warn("'{}' has no Media HouseID specified in metadata.", mediaFilePath);
\r
258 if (StringUtils.isBlank(archiveItem.getMediaTitle())) {
\r
259 logger.warn("'{}' has no Media Title specified in metadata.", mediaFilePath);
\r
262 return archiveItem;
\r
265 private ArchiveItem processRundow(IOctopusAPI octopusAPI, DBObject r) throws Exception {
\r
266 BasicDBObject rundown = (BasicDBObject) r;
\r
267 long rundownID = rundown.getLong(IOctopusAPI.ID);
\r
268 logger.info("Processing rundown {} {}", rundownID, rundown.getString(IOctopusAPI.NAME));
\r
270 List<DBObject> stories = octopusAPI.getRundownFullStories(rundownID);
\r
271 if (stories == null)
\r
274 String name = NoSQLUtils.asString(NoSQLUtils.asDBObject(rundown, IOctopusAPI.RUNDOWN_TYPE), IOctopusAPI.NAME);
\r
275 if (StringUtils.isBlank(name))
\r
277 String channel = NoSQLUtils.asString(NoSQLUtils.asDBObject(rundown, IOctopusAPI.CHANNEL), IOctopusAPI.NAME);
\r
278 Date scheduledStart = rundown.getDate(IOctopusAPI.SCHEDULED_START);
\r
279 if (scheduledStart == null)
\r
282 ArchiveItem result = new ArchiveItem();
\r
283 result.setItemHouseId(String.valueOf(rundownID));
\r
284 String start = CalendarUtils.toString(CalendarUtils.createCalendar(scheduledStart), SCHEDULED_FORMAT);
\r
285 result.setItemTitle(String.format("%s %s %s", start, name, channel));
\r
287 StringBuilder sb = new StringBuilder();
\r
288 for (DBObject s : stories) {
\r
289 BasicDBObject story = (BasicDBObject) s;
\r
292 sb.append(story.getString(IOctopusAPI.PARENT_STORY_ID));
\r
293 sb.append(" [" + story.getString(IOctopusAPI.FORMAT) + "] ");
\r
294 sb.append(story.getString(IOctopusAPI.NAME));
\r
297 String content = story.getString(IOctopusAPI.SCRIPT_CONTENT);
\r
298 if (content != null) {
\r
299 content = content.replace("\r\n\r\n\r\n\r\n", "\r\n");
\r
300 content = content.replace("\r\n\r\n\r\n", "\r\n");
\r
301 content = content.replace("\r\n\r\n", "\r\n");
\r
302 sb.append(content);
\r
306 result.setMediaHouseId(result.getItemHouseId());
\r
307 result.setMediaDescription(sb.toString());
\r