2e0bfd0ee8f2b1417cd47d3876335dc68879720c
[mediacube.git] /
1 package user.jobengine.server.steps;\r
2 \r
3 import java.io.File;\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
16 \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
21 \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
26 \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
33 \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
43 \r
44         private Marker marker;\r
45         private DBCollection existingRecordings;\r
46 \r
47         private ArchiveItem createArchiveItem(Path mediaFilePath, Path catchedFilePath) {\r
48                 ArchiveItem result = null;\r
49                 try {\r
50 \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
55 \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
59                                 return null;\r
60                         }\r
61                         result = processRundow(octopusAPI, rundown);\r
62                         if (result == null)\r
63                                 return null;\r
64 \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
71                                         return null;\r
72                                 }\r
73                                 ArchiveItem item2 = processRundow(octopusAPI, rundown);\r
74                                 if (item2 == null)\r
75                                         return null;\r
76 \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
79                         }\r
80 \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
86                         logger.catching(e);\r
87                         logger.error(getJobRuntime().getMarker(), "A metaadat nem elérhető. A rendszer üzenete: {}", e.getMessage());\r
88                         return null;\r
89                 }\r
90 \r
91                 return result;\r
92         }\r
93 \r
94         private void createCatchedFile(Path catchedFilePath) throws IOException {\r
95                 try {\r
96                         EscortFiles.ensureUNCFolder(catchedFilePath.getParent());\r
97                         Files.createFile(catchedFilePath);\r
98                 } catch (IOException e) {\r
99                         logger.catching(e);\r
100                         logger.error(marker, "A '{}' jelzőfájl nem hozható létre. A rendszer üzenete: {}", catchedFilePath, e.getMessage());\r
101                         throw e;\r
102                 }\r
103         }\r
104 \r
105         @StepEntry\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
111                 try {\r
112                         Files.walkFileTree(Paths.get(sourcePath), new SimpleFileVisitor<Path>() {\r
113 \r
114                                 @Override\r
115                                 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {\r
116                                         FileVisitResult result = FileVisitResult.SKIP_SUBTREE;\r
117 \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
121                                         else {\r
122                                                 if ("2017".equals(dir.getParent().toFile().getName().toUpperCase())\r
123                                                                 || "2018".equals(dir.getParent().toFile().getName().toUpperCase())) {\r
124                                                         try {\r
125                                                                 startDateformat.parse(dir.toFile().getName());\r
126                                                                 result = FileVisitResult.CONTINUE;\r
127                                                         } catch (ParseException e) {\r
128                                                         }\r
129                                                 }\r
130                                         }\r
131 \r
132                                         if (result == FileVisitResult.CONTINUE)\r
133                                                 logger.info(dir);\r
134                                         return result;\r
135                                 }\r
136 \r
137                                 @Override\r
138                                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {\r
139                                         FileVisitResult result = FileVisitResult.TERMINATE;\r
140                                         ArchiveItem item = null;\r
141                                         try {\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
146                                                 throw e;\r
147                                         }\r
148                                         if (item == null) {\r
149                                                 result = FileVisitResult.CONTINUE;\r
150                                         } else {\r
151                                                 logger.info(file);\r
152                                                 archiveItems[0] = item;\r
153                                         }\r
154                                         return result;\r
155                                 }\r
156 \r
157                         });\r
158 \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
162                         throw e;\r
163                 } finally {\r
164                 }\r
165                 ArchiveItem archiveItem = archiveItems[0];\r
166                 String targetFileName = null;\r
167 \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
171                 } else {\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, 27) + "_PGM";\r
178                         }\r
179                         logger.info(marker, "Az archiváló folyamat az '{}' anyagot archiválja.", mediaFile);\r
180                 }\r
181 \r
182                 return new Object[] { archiveItem, targetFileName };\r
183         }\r
184 \r
185         private Date getScheduledStart(String clipName, Date recordDate) {\r
186 \r
187                 if (StringUtils.isBlank(clipName)) {\r
188                         logger.warn(marker, "A fájlnak nincs neve, ezért nem archiválható.");\r
189                         return null;\r
190                 }\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
193                         return null;\r
194                 }\r
195 \r
196                 Date timePart = null;\r
197                 try {\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
202                         return null;\r
203                 }\r
204                 return CalendarUtils.createCalendar(CalendarUtils.createCalendar(recordDate), timePart).getTime();\r
205         }\r
206 \r
207         private ArchiveItem processPathItem(Path mediaFilePath) throws IOException {\r
208                 File mediaFile = mediaFilePath.toFile();\r
209 \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
215                         return null;\r
216                 }\r
217                 createCatchedFile(catchedFilePath);\r
218                 if (!catchedFile.exists()) {\r
219                         logger.warn("'{}' catchfile not exists.", catchedFilePath);\r
220                         return null;\r
221                 }\r
222 \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
226                         return null;\r
227                 }\r
228 \r
229                 ArchiveItem archiveItem = createArchiveItem(mediaFilePath, catchedFilePath);\r
230 \r
231                 if (archiveItem == null) {\r
232                         logger.warn("'{}' has no metadata specified.", mediaFilePath);\r
233                         return null;\r
234                 }\r
235 \r
236                 DBObject existingRecording = existingRecordings.findOne(new BasicDBObject("title", archiveItem.getItemTitle().substring(0, 16)));\r
237 \r
238                 if (existingRecording != null) {\r
239                         logger.warn("'{}' already archived, skipping.", archiveItem.getItemTitle());\r
240                         return null;\r
241                 }\r
242 \r
243                 if (StringUtils.isBlank(archiveItem.getItemHouseId())) {\r
244                         logger.warn("'{}' has no Item HouseID specified in metadata.", mediaFilePath);\r
245                         return null;\r
246                 }\r
247 \r
248                 if (StringUtils.isBlank(archiveItem.getItemTitle())) {\r
249                         logger.warn("'{}' has no Item Title specified in metadata.", mediaFilePath);\r
250                         return null;\r
251                 }\r
252 \r
253                 if (StringUtils.isBlank(archiveItem.getMediaHouseId())) {\r
254                         logger.warn("'{}' has no Media HouseID specified in metadata.", mediaFilePath);\r
255                         return null;\r
256                 }\r
257 \r
258                 if (StringUtils.isBlank(archiveItem.getMediaTitle())) {\r
259                         logger.warn("'{}' has no Media Title specified in metadata.", mediaFilePath);\r
260                         return null;\r
261                 }\r
262                 return archiveItem;\r
263         }\r
264 \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
269 \r
270                 List<DBObject> stories = octopusAPI.getRundownFullStories(rundownID);\r
271                 if (stories == null)\r
272                         return null;\r
273 \r
274                 String name = NoSQLUtils.asString(NoSQLUtils.asDBObject(rundown, IOctopusAPI.RUNDOWN_TYPE), IOctopusAPI.NAME);\r
275                 if (StringUtils.isBlank(name))\r
276                         return null;\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
280                         return null;\r
281 \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
286 \r
287                 StringBuilder sb = new StringBuilder();\r
288                 for (DBObject s : stories) {\r
289                         BasicDBObject story = (BasicDBObject) s;\r
290 \r
291                         sb.append("*** ");\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
295                         sb.append(" ***");\r
296                         sb.append("\r\n");\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
303                                 sb.append("\r\n");\r
304                         }\r
305                 }\r
306                 result.setMediaHouseId(result.getItemHouseId());\r
307                 result.setMediaDescription(sb.toString());\r
308                 return result;\r
309         }\r
310 }\r