1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.mediapackage;
23
24 import static org.apache.commons.lang3.StringUtils.isNotBlank;
25 import static org.opencastproject.util.IoSupport.withResource;
26 import static org.opencastproject.util.data.functions.Misc.chuck;
27
28 import org.apache.commons.io.FilenameUtils;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import java.io.InputStream;
33 import java.net.URI;
34 import java.util.List;
35 import java.util.Objects;
36 import java.util.Optional;
37 import java.util.function.Consumer;
38 import java.util.function.Function;
39 import java.util.function.Predicate;
40 import java.util.stream.Collectors;
41
42
43 public final class MediaPackageSupport {
44
45 private MediaPackageSupport() {
46 }
47
48 private static final List NIL = java.util.Collections.EMPTY_LIST;
49
50
51
52
53
54
55
56
57
58
59
60 public enum MergeMode {
61 Merge, Replace, Skip, Fail
62 }
63
64
65 private static final Logger logger = LoggerFactory.getLogger(MediaPackageSupport.class.getName());
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public static MediaPackage merge(MediaPackage dest, MediaPackage src, MergeMode mode) throws MediaPackageException {
85 try {
86 for (MediaPackageElement e : src.elements()) {
87 if (dest.getElementById(e.getIdentifier()) == null)
88 dest.add(e);
89 else {
90 if (MergeMode.Replace == mode) {
91 logger.debug("Replacing element " + e.getIdentifier() + " while merging " + dest + " with " + src);
92 dest.remove(dest.getElementById(e.getIdentifier()));
93 dest.add(e);
94 } else if (MergeMode.Skip == mode) {
95 logger.debug("Skipping element " + e.getIdentifier() + " while merging " + dest + " with " + src);
96 continue;
97 } else if (MergeMode.Merge == mode) {
98 logger.debug("Renaming element " + e.getIdentifier() + " while merging " + dest + " with " + src);
99 e.setIdentifier(null);
100 dest.add(e);
101 } else if (MergeMode.Fail == mode) {
102 throw new MediaPackageException("Target media package " + dest + " already contains element with id "
103 + e.getIdentifier());
104 }
105 }
106 }
107 } catch (UnsupportedElementException e) {
108 throw new MediaPackageException(e);
109 }
110 return dest;
111 }
112
113
114
115
116
117
118
119
120 public static boolean contains(String identifier, MediaPackage mp) {
121 for (MediaPackageElement element : mp.getElements()) {
122 if (element.getIdentifier().equals(identifier))
123 return true;
124 }
125 return false;
126 }
127
128
129
130
131
132
133 public static Optional<String> getFileName(MediaPackageElement mpe) {
134 URI uri = mpe.getURI();
135 if (uri == null) {
136 return Optional.empty();
137 }
138 String name = FilenameUtils.getName(uri.toString());
139 if (name == null || name.isBlank()) {
140 return Optional.empty();
141 }
142 return Optional.of(name);
143 }
144
145
146
147
148
149
150
151 public static MediaPackage copy(MediaPackage mp) {
152 return (MediaPackage) mp.clone();
153 }
154
155
156 public static void updateElement(MediaPackage mp, MediaPackageElement e) {
157 mp.removeElementById(e.getIdentifier());
158 mp.add(e);
159 }
160
161
162 public static Consumer<MediaPackageElement> updateElement(final MediaPackage mp) {
163 return e -> updateElement(mp, e);
164 }
165
166
167 public static final class Filters {
168 private Filters() {
169 }
170
171
172 public static final Predicate<MediaPackageElement> isPublication = Publication.class::isInstance;
173 public static final Predicate<MediaPackageElement> isNotPublication = isPublication.negate();
174
175 public static final Predicate<MediaPackageElement> hasChecksum = e -> e.getChecksum() != null;
176
177 public static final Predicate<MediaPackageElement> hasNoChecksum = hasChecksum.negate();
178
179
180 public static boolean ofChannel(Publication p, String channelId) {
181 return p.getChannel().equals(channelId);
182 }
183
184
185 public static boolean hasTagAny(MediaPackageElement mpe, List<String> tags) {
186 return mpe.containsTag(tags);
187 }
188
189
190
191
192
193
194 public static Function<MediaPackageElement, Boolean> matchesFlavor(final MediaPackageElementFlavor flavor) {
195 return mpe -> flavor.matches(mpe.getFlavor());
196 }
197
198 public static boolean isEpisodeDublinCore(MediaPackageElement mpe) {
199
200 return MediaPackageElements.EPISODE.matches(mpe.getFlavor());
201 }
202
203 public static boolean isSmilCatalog(MediaPackageElement mpe) {
204
205 return MediaPackageElements.SMIL.matches(mpe.getFlavor());
206 }
207 }
208
209
210
211
212
213
214
215
216
217
218
219 public static Optional<List<String>> sanityCheck(MediaPackage mp) {
220 List<String> errors = java.util.stream.Stream.of(
221 mp.getIdentifier() == null ? "no ID" : null,
222 (mp.getIdentifier() != null && isNotBlank(mp.getIdentifier().toString())) ? null : "blank ID"
223 )
224 .filter(Objects::nonNull)
225 .collect(Collectors.toList());
226
227 return errors.isEmpty() ? Optional.empty() : Optional.of(errors);
228 }
229
230
231 public static MediaPackage loadFromClassPath(String path) {
232 return withResource(
233 MediaPackageSupport.class.getResourceAsStream(path),
234 (InputStream is) -> {
235 try {
236 return MediaPackageBuilderFactory.newInstance()
237 .newMediaPackageBuilder()
238 .loadFromXml(is);
239 } catch (Exception e) {
240 return chuck(e);
241 }
242 }
243 );
244 }
245 }