class CatalogRest {

    @POST
    @Path("{catalogId}/records/{recordId}/tags")
    @Produces(MediaType.TEXT_PLAIN)
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @RolesAllowed("user")
    @ApiOperation("Creates a Tag for the identified VersionedRecord.")
    @ActionId(value = Modify.TYPE)
    @ResourceId(type = ValueType.PATH, value = "recordId")
    public Response createTag(@Context ContainerRequestContext context,
                       @PathParam("catalogId") String catalogId,
                       @PathParam("recordId") String recordId,
                       @FormDataParam("title") String title,
                       @FormDataParam("description") String description,
                       @FormDataParam("iri") String iri,
                       @FormDataParam("commit") String commitId) {
        try (RepositoryConnection conn = configProvider.getRepository().getConnection()) {
            checkStringParam(iri, "Tag iri is required");
            checkStringParam(title, "Tag title is required");
            checkStringParam(commitId, "Tag commit is required");
            IRI recordIri = vf.createIRI(recordId);
            IRI commitIri = vf.createIRI(commitId);
            IRI tagIri = vf.createIRI(iri);
            if (!catalogUtilsService.commitInRecord(recordIri, commitIri, conn)) {
                throw ErrorUtils.sendError("Commit " + commitId + " is not in record " + recordId,
                        Response.Status.BAD_REQUEST);
            }

            OrmFactory<Tag> factory = factoryRegistry.getFactoryOfType(Tag.class).orElseThrow(() ->
                    ErrorUtils.sendError("Tag Factory not found", Response.Status.INTERNAL_SERVER_ERROR));
            OffsetDateTime now = OffsetDateTime.now();
            Tag tag = factory.createNew(tagIri);
            tag.setProperty(vf.createLiteral(title), vf.createIRI(_Thing.title_IRI));
            if (description != null) {
                tag.setProperty(vf.createLiteral(description), vf.createIRI(_Thing.description_IRI));
            }
            tag.setProperty(vf.createLiteral(now), vf.createIRI(_Thing.issued_IRI));
            tag.setProperty(vf.createLiteral(now), vf.createIRI(_Thing.modified_IRI));
            tag.setProperty(getActiveUser(context, engineManager).getResource(),
                    vf.createIRI(DCTERMS.PUBLISHER.stringValue()));
            tag.setCommit(commitFactory.createNew(commitIri));
            catalogManager.addVersion(vf.createIRI(catalogId), recordIri, tag);
            return Response.status(201).entity(tag.getResource().stringValue()).build();
        } catch (IllegalArgumentException ex) {
            throw ErrorUtils.sendError(ex, ex.getMessage(), Response.Status.BAD_REQUEST);
        } catch (MobiException ex) {
            throw ErrorUtils.sendError(ex, ex.getMessage(), Response.Status.INTERNAL_SERVER_ERROR);
        }
    }

}