Search in sources :

Example 11 with Fn

use of com.entwinemedia.fn.Fn in project opencast by opencast.

the class SeriesEndpoint method updateSeriesAcl.

@PUT
@Path("{seriesId}/acl")
@Produces({ "application/json", "application/v1.0.0+json" })
@RestQuery(name = "updateseriesacl", description = "Updates a series' access policy.", returnDescription = "", pathParameters = { @RestParameter(name = "seriesId", description = "The series id", isRequired = true, type = STRING) }, restParameters = { @RestParameter(name = "acl", isRequired = true, description = "Access policy", type = STRING) }, reponses = { @RestResponse(description = "The access control list for the specified series is updated.", responseCode = HttpServletResponse.SC_OK), @RestResponse(description = "The specified series does not exist.", responseCode = HttpServletResponse.SC_NOT_FOUND) })
public Response updateSeriesAcl(@HeaderParam("Accept") String acceptHeader, @PathParam("seriesId") String seriesID, @FormParam("acl") String aclJson) throws NotFoundException, SeriesException, UnauthorizedException {
    if (isBlank(aclJson))
        return R.badRequest("Missing form parameter 'acl'");
    JSONParser parser = new JSONParser();
    JSONArray acl;
    try {
        acl = (JSONArray) parser.parse(aclJson);
    } catch (ParseException e) {
        logger.debug("Could not parse ACL ({}): {}", aclJson, getStackTrace(e));
        return R.badRequest("Could not parse ACL");
    }
    List<AccessControlEntry> accessControlEntries = $(acl.toArray()).map(new Fn<Object, AccessControlEntry>() {

        @Override
        public AccessControlEntry apply(Object a) {
            JSONObject ace = (JSONObject) a;
            return new AccessControlEntry((String) ace.get("role"), (String) ace.get("action"), (boolean) ace.get("allow"));
        }
    }).toList();
    seriesService.updateAccessControl(seriesID, new AccessControlList(accessControlEntries));
    return ApiResponses.Json.ok(VERSION_1_0_0, aclJson);
}
Also used : AccessControlList(org.opencastproject.security.api.AccessControlList) JSONObject(org.json.simple.JSONObject) JSONArray(org.json.simple.JSONArray) Fn(com.entwinemedia.fn.Fn) AccessControlEntry(org.opencastproject.security.api.AccessControlEntry) JSONParser(org.json.simple.parser.JSONParser) JSONObject(org.json.simple.JSONObject) ParseException(org.json.simple.parser.ParseException) Path(javax.ws.rs.Path) Produces(javax.ws.rs.Produces) RestQuery(org.opencastproject.util.doc.rest.RestQuery) PUT(javax.ws.rs.PUT)

Example 12 with Fn

use of com.entwinemedia.fn.Fn in project opencast by opencast.

the class DublinCoreUtil method calculateChecksum.

/**
 * Calculate an MD5 checksum for a DublinCore catalog.
 */
public static Checksum calculateChecksum(DublinCoreCatalog dc) {
    // Use 0 as a word separator. This is safe since none of the UTF-8 code points
    // except \u0000 contains a null byte when converting to a byte array.
    final byte[] sep = new byte[] { 0 };
    final MessageDigest md = // consider all DublinCore properties
    $(getPropertiesSorted(dc)).bind(new Fn<CatalogEntry, Stream<String>>() {

        @Override
        public Stream<String> apply(CatalogEntry entry) {
            // get attributes, sorted and serialized as [name, value, name, value, ...]
            final Stream<String> attributesSorted = $(entry.getAttributes().entrySet()).sort(new Comparator<Entry<EName, String>>() {

                @Override
                public int compare(Entry<EName, String> o1, Entry<EName, String> o2) {
                    return o1.getKey().compareTo(o2.getKey());
                }
            }).bind(new Fn<Entry<EName, String>, Stream<String>>() {

                @Override
                public Stream<String> apply(Entry<EName, String> attribute) {
                    return $(attribute.getKey().toString(), attribute.getValue());
                }
            });
            return $(entry.getEName().toString(), entry.getValue()).append(attributesSorted);
        }
    }).append(Opt.nul(dc.getRootTag()).map(toString)).foldl(mkMd5MessageDigest(), new Fn2<MessageDigest, String, MessageDigest>() {

        @Override
        public MessageDigest apply(MessageDigest digest, String s) {
            digest.update(s.getBytes(StandardCharsets.UTF_8));
            // add separator byte (see definition above)
            digest.update(sep);
            return digest;
        }
    });
    try {
        return Checksum.create("md5", Checksum.convertToHex(md.digest()));
    } catch (NoSuchAlgorithmException e) {
        return chuck(e);
    }
}
Also used : EName(org.opencastproject.mediapackage.EName) CatalogEntry(org.opencastproject.mediapackage.XMLCatalogImpl.CatalogEntry) Fn(com.entwinemedia.fn.Fn) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Entry(java.util.Map.Entry) CatalogEntry(org.opencastproject.mediapackage.XMLCatalogImpl.CatalogEntry) Stream(com.entwinemedia.fn.Stream) InputStream(java.io.InputStream) MessageDigest(java.security.MessageDigest)

Example 13 with Fn

use of com.entwinemedia.fn.Fn in project opencast by opencast.

the class MetadataField method createDateMetadata.

/**
 * Create a metadata field based on a {@link Date}.
 *
 * @param inputID
 *          The identifier of the new metadata field
 * @param label
 *          The label of the new metadata field
 * @param readOnly
 *          Define if the new metadata is or not a readonly field
 * @param required
 *          Define if the new metadata field is or not required
 * @param pattern
 *          The date pattern for {@link SimpleDateFormat}.
 * @param order
 *          The ui order for the new field, 0 at the top and progressively down from there.
 * @return The new metadata field
 */
public static MetadataField<Date> createDateMetadata(String inputID, Opt<String> outputID, String label, boolean readOnly, boolean required, final String pattern, Opt<Integer> order, Opt<String> namespace) {
    final SimpleDateFormat dateFormat = getSimpleDateFormatter(pattern);
    Fn<Opt<Date>, JValue> dateToJSON = new Fn<Opt<Date>, JValue>() {

        @Override
        public JValue apply(Opt<Date> date) {
            if (date.isNone())
                return Jsons.BLANK;
            else {
                return v(dateFormat.format(date.get()), Jsons.BLANK);
            }
        }
    };
    Fn<Object, Date> jsonToDate = new Fn<Object, Date>() {

        @Override
        public Date apply(Object value) {
            try {
                String date = (String) value;
                if (StringUtils.isBlank(date))
                    return null;
                return dateFormat.parse(date);
            } catch (java.text.ParseException e) {
                logger.error("Not able to parse date {}: {}", value, e.getMessage());
                return null;
            }
        }
    };
    MetadataField<Date> dateField = new MetadataField<>(inputID, outputID, label, readOnly, required, null, Opt.none(), Type.DATE, JsonType.DATE, Opt.<Map<String, String>>none(), Opt.<String>none(), dateToJSON, jsonToDate, order, namespace);
    if (StringUtils.isNotBlank(pattern)) {
        dateField.setPattern(Opt.some(pattern));
    }
    return dateField;
}
Also used : Fn(com.entwinemedia.fn.Fn) Date(java.util.Date) Opt(com.entwinemedia.fn.data.Opt) JValue(com.entwinemedia.fn.data.json.JValue) JObject(com.entwinemedia.fn.data.json.JObject) SimpleDateFormat(java.text.SimpleDateFormat)

Example 14 with Fn

use of com.entwinemedia.fn.Fn in project opencast by opencast.

the class MetadataField method createTemporalMetadata.

private static MetadataField<String> createTemporalMetadata(String inputID, Opt<String> outputID, String label, boolean readOnly, boolean required, final String pattern, final Type type, final JsonType jsonType, Opt<Integer> order, Opt<String> namespace) {
    if (StringUtils.isBlank(pattern)) {
        throw new IllegalArgumentException("For temporal metadata field " + inputID + " of type " + type + " there needs to be a pattern.");
    }
    final SimpleDateFormat dateFormat = getSimpleDateFormatter(pattern);
    Fn<Object, String> jsonToDateString = new Fn<Object, String>() {

        @Override
        public String apply(Object value) {
            String date = (String) value;
            if (StringUtils.isBlank(date))
                return "";
            try {
                dateFormat.parse(date);
            } catch (java.text.ParseException e) {
                logger.error("Not able to parse date string {}: {}", value, getMessage(e));
                return null;
            }
            return date;
        }
    };
    Fn<Opt<String>, JValue> dateToJSON = new Fn<Opt<String>, JValue>() {

        @Override
        public JValue apply(Opt<String> periodEncodedString) {
            if (periodEncodedString.isNone() || StringUtils.isBlank(periodEncodedString.get())) {
                return Jsons.BLANK;
            }
            // Try to parse the metadata as DCIM metadata.
            DCMIPeriod p = EncodingSchemeUtils.decodePeriod(periodEncodedString.get());
            if (p != null) {
                return v(dateFormat.format(p.getStart()), Jsons.BLANK);
            }
            // Not DCIM metadata so it might already be formatted (given from the front and is being returned there
            try {
                dateFormat.parse(periodEncodedString.get());
                return v(periodEncodedString.get(), Jsons.BLANK);
            } catch (Exception e) {
                logger.error("Unable to parse temporal metadata '{}' as either DCIM data or a formatted date using pattern {} because: {}", periodEncodedString.get(), pattern, getStackTrace(e));
                throw new IllegalArgumentException(e);
            }
        }
    };
    MetadataField<String> temporalStart = new MetadataField<>(inputID, outputID, label, readOnly, required, null, Opt.none(), type, jsonType, Opt.<Map<String, String>>none(), Opt.<String>none(), dateToJSON, jsonToDateString, order, namespace);
    temporalStart.setPattern(Opt.some(pattern));
    return temporalStart;
}
Also used : Fn(com.entwinemedia.fn.Fn) ParseException(org.json.simple.parser.ParseException) Opt(com.entwinemedia.fn.data.Opt) JValue(com.entwinemedia.fn.data.json.JValue) JObject(com.entwinemedia.fn.data.json.JObject) SimpleDateFormat(java.text.SimpleDateFormat)

Example 15 with Fn

use of com.entwinemedia.fn.Fn in project opencast by opencast.

the class SchedulerServiceImpl method updateEventInternal.

private void updateEventInternal(final String mpId, String modificationOrigin, Opt<Date> startDateTime, Opt<Date> endDateTime, Opt<String> captureAgentId, Opt<Set<String>> userIds, Opt<MediaPackage> mediaPackage, Opt<Map<String, String>> wfProperties, Opt<Map<String, String>> caMetadata, Opt<Opt<Boolean>> optOutOption, Opt<String> trxId) throws NotFoundException, SchedulerException {
    notEmpty(mpId, "mpId");
    notEmpty(modificationOrigin, "modificationOrigin");
    notNull(startDateTime, "startDateTime");
    notNull(endDateTime, "endDateTime");
    notNull(captureAgentId, "captureAgentId");
    notNull(userIds, "userIds");
    notNull(mediaPackage, "mediaPackage");
    notNull(wfProperties, "wfProperties");
    notNull(caMetadata, "caMetadata");
    notNull(optOutOption, "optOutStatus");
    notNull(trxId, "trxId");
    try {
        AQueryBuilder query = assetManager.createQuery();
        Props p = new Props(query);
        ASelectQuery select = query.select(query.snapshot(), p.start().target(), p.end().target(), query.propertiesOf(WORKFLOW_NAMESPACE, CA_NAMESPACE), p.agent().target(), p.source().target(), p.checksum().target(), p.optOut().target(), p.presenters().target()).where(withOrganization(query).and(query.mediaPackageId(mpId).and(query.version().isLatest()).and(query.hasPropertiesOf(p.namespace()))));
        Opt<ARecord> optEvent = select.run().getRecords().head();
        if (optEvent.isNone())
            throw new NotFoundException("No event found while updating event " + mpId);
        ARecord record = optEvent.get();
        if (record.getSnapshot().isNone())
            throw new NotFoundException("No mediapackage found while updating event " + mpId);
        Opt<DublinCoreCatalog> dublinCoreOpt = loadEpisodeDublinCoreFromAsset(record.getSnapshot().get());
        if (dublinCoreOpt.isNone())
            throw new NotFoundException("No dublincore found while updating event " + mpId);
        verifyActive(mpId, record);
        Date start = record.getProperties().apply(Properties.getDate(START_DATE_CONFIG));
        Date end = record.getProperties().apply(Properties.getDate(END_DATE_CONFIG));
        if ((startDateTime.isSome() || endDateTime.isSome()) && endDateTime.getOr(end).before(startDateTime.getOr(start)))
            throw new SchedulerException("The end date is before the start date");
        String agentId = record.getProperties().apply(Properties.getString(AGENT_CONFIG));
        Opt<String> seriesId = Opt.nul(record.getSnapshot().get().getMediaPackage().getSeries());
        boolean oldOptOut = record.getProperties().apply(Properties.getBoolean(OPTOUT_CONFIG));
        // Get opt out status
        Opt<Boolean> optOut = Opt.none();
        for (Opt<Boolean> optOutToUpdate : optOutOption) {
            optOut = Opt.some(getOptOutStatus(seriesId, optOutToUpdate));
        }
        if (trxId.isNone()) {
            // Check for locked transactions
            Opt<String> source = record.getProperties().apply(Properties.getStringOpt(SOURCE_CONFIG));
            if (source.isSome() && persistence.hasTransaction(source.get())) {
                logger.warn("Unable to update event '{}', source '{}' is currently locked due to an active transaction!", mpId, source.get());
                throw new SchedulerTransactionLockException("Unable to update event, locked source " + source.get());
            }
            // Set to opted out
            boolean isNewOptOut = optOut.isSome() && optOut.get();
            // Changed to ready for recording
            boolean readyForRecording = optOut.isSome() && !optOut.get();
            // Has a conflict related property be changed?
            boolean propertyChanged = captureAgentId.isSome() || startDateTime.isSome() || endDateTime.isSome();
            // Check for conflicting events
            if (!isNewOptOut && (readyForRecording || (propertyChanged && !oldOptOut))) {
                List<MediaPackage> conflictingEvents = $(findConflictingEvents(captureAgentId.getOr(agentId), startDateTime.getOr(start), endDateTime.getOr(end))).filter(new Fn<MediaPackage, Boolean>() {

                    @Override
                    public Boolean apply(MediaPackage mp) {
                        return !mpId.equals(mp.getIdentifier().compact());
                    }
                }).toList();
                if (conflictingEvents.size() > 0) {
                    logger.info("Unable to update event {}, conflicting events found: {}", mpId, conflictingEvents);
                    throw new SchedulerConflictException("Unable to update event, conflicting events found for event " + mpId);
                }
            }
        }
        Set<String> presenters = getPresenters(record.getProperties().apply(getStringOpt(PRESENTERS_CONFIG)).getOr(""));
        Map<String, String> wfProps = record.getProperties().filter(filterByNamespace._2(WORKFLOW_NAMESPACE)).group(toKey, toValue);
        Map<String, String> caProperties = record.getProperties().filter(filterByNamespace._2(CA_NAMESPACE)).group(toKey, toValue);
        boolean propertiesChanged = false;
        boolean dublinCoreChanged = false;
        // Get workflow properties
        for (Map<String, String> wfPropsToUpdate : wfProperties) {
            propertiesChanged = true;
            wfProps = wfPropsToUpdate;
        }
        // Get capture agent properties
        for (Map<String, String> caMetadataToUpdate : caMetadata) {
            propertiesChanged = true;
            caProperties = caMetadataToUpdate;
        }
        if (captureAgentId.isSome())
            propertiesChanged = true;
        Opt<AccessControlList> acl = Opt.none();
        Opt<DublinCoreCatalog> dublinCore = Opt.none();
        Opt<AccessControlList> aclOld = loadEpisodeAclFromAsset(record.getSnapshot().get());
        for (MediaPackage mpToUpdate : mediaPackage) {
            // Check for series change
            if (ne(record.getSnapshot().get().getMediaPackage().getSeries(), mpToUpdate.getSeries())) {
                propertiesChanged = true;
                seriesId = Opt.nul(mpToUpdate.getSeries());
            }
            // Check for ACL change and send update
            Option<AccessControlList> aclNew = authorizationService.getAcl(mpToUpdate, AclScope.Episode);
            if (aclNew.isSome()) {
                if (aclOld.isNone() || !AccessControlUtil.equals(aclNew.get(), aclOld.get())) {
                    acl = aclNew.toOpt();
                }
            }
            // Check for dublin core change and send update
            Opt<DublinCoreCatalog> dublinCoreNew = DublinCoreUtil.loadEpisodeDublinCore(workspace, mpToUpdate);
            if (dublinCoreNew.isSome() && !DublinCoreUtil.equals(dublinCoreOpt.get(), dublinCoreNew.get())) {
                dublinCoreChanged = true;
                propertiesChanged = true;
                dublinCore = dublinCoreNew;
            }
        }
        Opt<Map<String, String>> finalCaProperties = Opt.none();
        if (propertiesChanged) {
            finalCaProperties = Opt.some(getFinalAgentProperties(caProperties, wfProps, captureAgentId.getOr(agentId), seriesId, some(dublinCore.getOr(dublinCoreOpt.get()))));
        }
        String checksum = calculateChecksum(workspace, getEventCatalogUIAdapterFlavors(), startDateTime.getOr(start), endDateTime.getOr(end), captureAgentId.getOr(agentId), userIds.getOr(presenters), mediaPackage.getOr(record.getSnapshot().get().getMediaPackage()), some(dublinCore.getOr(dublinCoreOpt.get())), wfProperties.getOr(wfProps), finalCaProperties.getOr(caProperties), optOut.getOr(oldOptOut), acl.getOr(aclOld.getOr(new AccessControlList())));
        if (trxId.isNone()) {
            String oldChecksum = record.getProperties().apply(Properties.getString(CHECKSUM));
            if (checksum.equals(oldChecksum)) {
                logger.debug("Updated event {} has same checksum, ignore update", mpId);
                return;
            }
        }
        // Update asset
        persistEvent(mpId, modificationOrigin, checksum, startDateTime, endDateTime, captureAgentId, userIds, mediaPackage, wfProperties, finalCaProperties, optOut, Opt.<String>none(), trxId);
        if (trxId.isNone()) {
            // Send updates
            sendUpdateAddEvent(mpId, acl, dublinCore, startDateTime, endDateTime, userIds, Opt.some(agentId), finalCaProperties, optOut);
            // Update last modified
            if (propertiesChanged || dublinCoreChanged || optOutOption.isSome() || startDateTime.isSome() || endDateTime.isSome()) {
                touchLastEntry(agentId);
                for (String agent : captureAgentId) {
                    touchLastEntry(agent);
                }
            }
        }
    } catch (NotFoundException e) {
        throw e;
    } catch (SchedulerException e) {
        throw e;
    } catch (Exception e) {
        logger.error("Failed to update event with id '{}': {}", mpId, getStackTrace(e));
        throw new SchedulerException(e);
    }
}
Also used : AccessControlList(org.opencastproject.security.api.AccessControlList) SchedulerException(org.opencastproject.scheduler.api.SchedulerException) AQueryBuilder(org.opencastproject.assetmanager.api.query.AQueryBuilder) NotFoundException(org.opencastproject.util.NotFoundException) Log.getHumanReadableTimeString(org.opencastproject.util.Log.getHumanReadableTimeString) ARecord(org.opencastproject.assetmanager.api.query.ARecord) SchedulerTransactionLockException(org.opencastproject.scheduler.api.SchedulerTransactionLockException) Fn(com.entwinemedia.fn.Fn) SchedulerConflictException(org.opencastproject.scheduler.api.SchedulerConflictException) Date(java.util.Date) SchedulerException(org.opencastproject.scheduler.api.SchedulerException) SchedulerConflictException(org.opencastproject.scheduler.api.SchedulerConflictException) IOException(java.io.IOException) ServiceException(org.osgi.framework.ServiceException) SchedulerTransactionLockException(org.opencastproject.scheduler.api.SchedulerTransactionLockException) ConfigurationException(org.osgi.service.cm.ConfigurationException) SeriesException(org.opencastproject.series.api.SeriesException) MediaPackageException(org.opencastproject.mediapackage.MediaPackageException) ValidationException(net.fortuna.ical4j.model.ValidationException) UnauthorizedException(org.opencastproject.security.api.UnauthorizedException) NotFoundException(org.opencastproject.util.NotFoundException) MediaPackage(org.opencastproject.mediapackage.MediaPackage) ASelectQuery(org.opencastproject.assetmanager.api.query.ASelectQuery) DublinCoreCatalog(org.opencastproject.metadata.dublincore.DublinCoreCatalog) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap)

Aggregations

Fn (com.entwinemedia.fn.Fn)16 Opt (com.entwinemedia.fn.data.Opt)5 JValue (com.entwinemedia.fn.data.json.JValue)5 JObject (com.entwinemedia.fn.data.json.JObject)4 ParseException (org.json.simple.parser.ParseException)4 ArrayList (java.util.ArrayList)3 Date (java.util.Date)3 NotFoundException (org.opencastproject.util.NotFoundException)3 IOException (java.io.IOException)2 MessageDigest (java.security.MessageDigest)2 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)2 SimpleDateFormat (java.text.SimpleDateFormat)2 HashMap (java.util.HashMap)2 List (java.util.List)2 Map (java.util.Map)2 EntityManager (javax.persistence.EntityManager)2 Path (javax.ws.rs.Path)2 Produces (javax.ws.rs.Produces)2 JSONArray (org.json.simple.JSONArray)2 Property (org.opencastproject.assetmanager.api.Property)2