Package org.zanata.rest.service

Source Code of org.zanata.rest.service.SourceDocResourceService

/*
* Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the
* @author tags. See the copyright.txt file in the distribution for a full
* listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
* site: http://www.fsf.org.
*/
package org.zanata.rest.service;

import java.lang.reflect.Type;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import lombok.extern.slf4j.Slf4j;

import org.jboss.resteasy.util.GenericType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Transactional;
import org.jboss.seam.annotations.security.Restrict;
import org.zanata.common.EntityStatus;
import org.zanata.common.LocaleId;
import org.zanata.dao.DocumentDAO;
import org.zanata.dao.ProjectIterationDAO;
import org.zanata.exception.ZanataServiceException;
import org.zanata.model.HDocument;
import org.zanata.model.HLocale;
import org.zanata.model.HProject;
import org.zanata.model.HProjectIteration;
import org.zanata.model.HTextFlow;
import org.zanata.rest.NoSuchEntityException;
import org.zanata.rest.ReadOnlyEntityException;
import org.zanata.rest.dto.resource.Resource;
import org.zanata.rest.dto.resource.ResourceMeta;
import org.zanata.rest.dto.resource.TextFlow;
import org.zanata.service.DocumentService;
import org.zanata.service.LocaleService;

/**
* @author Carlos Munoz <a
*         href="mailto:camunoz@redhat.com">camunoz@redhat.com</a>
*/
@Name("sourceDocResourceService")
@Path(SourceDocResource.SERVICE_PATH)
@Slf4j
@Transactional
public class SourceDocResourceService implements SourceDocResource {

    @Context
    private Request request;

    @Context
    private UriInfo uri;

    /** Project Identifier. */
    @PathParam("projectSlug")
    private String projectSlug;

    /** Project Iteration identifier. */
    @PathParam("iterationSlug")
    private String iterationSlug;

    @In
    private ProjectIterationDAO projectIterationDAO;

    @In
    private DocumentDAO documentDAO;

    @In
    private LocaleService localeServiceImpl;

    @In
    private DocumentService documentServiceImpl;

    @In
    private ResourceUtils resourceUtils;

    @In
    private ETagUtils eTagUtils;

    @Override
    public Response head() {
        HProjectIteration hProjectIteration = retrieveAndCheckIteration(false);
        EntityTag etag =
                projectIterationDAO.getResourcesETag(hProjectIteration);
        Response.ResponseBuilder response = request.evaluatePreconditions(etag);
        if (response != null) {
            return response.build();
        }
        return Response.ok().tag(etag).build();
    }

    @Override
    public Response get(Set<String> extensions) {
        HProjectIteration hProjectIteration = retrieveAndCheckIteration(false);

        EntityTag etag =
                projectIterationDAO.getResourcesETag(hProjectIteration);

        Response.ResponseBuilder response = request.evaluatePreconditions(etag);
        if (response != null) {
            return response.build();
        }

        List<ResourceMeta> resources = new ArrayList<ResourceMeta>();

        for (HDocument doc : hProjectIteration.getDocuments().values()) {
            // TODO we shouldn't need this check
            if (!doc.isObsolete()) {
                ResourceMeta resource = new ResourceMeta();
                resourceUtils.transferToAbstractResourceMeta(doc, resource);
                resources.add(resource);
            }
        }

        Type genericType = new GenericType<List<ResourceMeta>>() {
        }.getGenericType();
        Object entity =
                new GenericEntity<List<ResourceMeta>>(resources, genericType);
        return Response.ok(entity).tag(etag).build();
    }

    @Override
    @Restrict("#{s:hasPermission(sourceDocResourceService.securedIteration, 'import-template')}")
    public
            Response post(Resource resource, Set<String> extensions,
                    boolean copytrans) {
        HProjectIteration hProjectIteration = retrieveAndCheckIteration(true);

        resourceUtils.validateExtensions(extensions); // gettext, comment

        String resourceName = resource.getName();
        if (!Pattern.matches(SourceDocResource.RESOURCE_NAME_REGEX,
                resourceName)) {
            log.warn("bad resource name in post(): {}", resourceName);
            throw new WebApplicationException(Response
                    .status(Response.Status.BAD_REQUEST)
                    .entity("not a legal resource name: " + resourceName)
                    .build());
        }

        HDocument document =
                documentDAO.getByDocIdAndIteration(hProjectIteration,
                        resourceName);

        // already existing non-obsolete document.
        if (document != null) {
            if (!document.isObsolete()) {
                // updates must happen through PUT on the actual resource
                return Response
                        .status(Response.Status.CONFLICT)
                        .entity("A document with name " + resourceName
                                + " already exists.").build();
            }
        }

        // TODO No need for docId param since it's resource.getName()
        document =
                this.documentServiceImpl.saveDocument(this.projectSlug,
                        this.iterationSlug, resource, extensions, copytrans);

        EntityTag etag =
                eTagUtils.generateETagForDocument(hProjectIteration,
                        document.getDocId(), extensions);

        return Response
                .created(
                        URI.create("r/"
                                + resourceUtils.encodeDocId(document.getDocId())))
                .tag(etag).build();
    }

    @Override
    public Response getResource(String idNoSlash, Set<String> extensions) {
        log.debug("start get resource");
        String id = URIHelper.convertFromDocumentURIId(idNoSlash);
        HProjectIteration hProjectIteration = retrieveAndCheckIteration(false);

        resourceUtils.validateExtensions(extensions);

        final Set<String> extSet = new HashSet<String>(extensions);
        EntityTag etag =
                eTagUtils
                        .generateETagForDocument(hProjectIteration, id, extSet);

        Response.ResponseBuilder response = request.evaluatePreconditions(etag);
        if (response != null) {
            return response.build();
        }

        HDocument doc =
                documentDAO.getByDocIdAndIteration(hProjectIteration, id);

        if (doc == null || doc.isObsolete()) {
            return Response.status(Response.Status.NOT_FOUND)
                    .entity("document not found").build();
        }

        Resource entity = new Resource(doc.getDocId());
        log.debug("get resource details {}", entity.toString());
        resourceUtils.transferToResource(doc, entity);

        for (HTextFlow htf : doc.getTextFlows()) {
            TextFlow tf =
                    new TextFlow(htf.getResId(), doc.getLocale().getLocaleId());
            resourceUtils.transferToTextFlow(htf, tf);
            resourceUtils.transferToTextFlowExtensions(htf,
                    tf.getExtensions(true), extensions);
            entity.getTextFlows().add(tf);
        }

        // handle extensions
        resourceUtils.transferToResourceExtensions(doc,
                entity.getExtensions(true), extensions);
        log.debug("Get resource :{}", entity.toString());
        return Response.ok().entity(entity).tag(etag)
                .lastModified(doc.getLastChanged()).build();
    }

    @Override
    @Restrict("#{s:hasPermission(sourceDocResourceService.securedIteration, 'import-template')}")
    public
            Response putResource(String idNoSlash, Resource resource,
                    Set<String> extensions, boolean copytrans) {
        log.debug("start put resource");
        String id = URIHelper.convertFromDocumentURIId(idNoSlash);
        Response.ResponseBuilder response;
        HProjectIteration hProjectIteration = retrieveAndCheckIteration(true);

        resourceUtils.validateExtensions(extensions);

        HDocument document =
                this.documentDAO.getByDocIdAndIteration(hProjectIteration, id);
        if (document == null || document.isObsolete()) {
            response = Response.created(uri.getAbsolutePath());
        } else {
            response = Response.ok();
        }

        resource.setName(id);
        document =
                this.documentServiceImpl.saveDocument(projectSlug,
                        iterationSlug, resource, extensions, copytrans);

        EntityTag etag =
                eTagUtils.generateETagForDocument(hProjectIteration,
                        document.getDocId(), extensions);

        log.debug("put resource successfully");
        return response.tag(etag).build();
    }

    @Override
    @Restrict("#{s:hasPermission(sourceDocResourceService.securedIteration, 'import-template')}")
    public
            Response deleteResource(String idNoSlash) {
        String id = URIHelper.convertFromDocumentURIId(idNoSlash);
        HProjectIteration hProjectIteration = retrieveAndCheckIteration(true);

        EntityTag etag =
                eTagUtils.generateETagForDocument(hProjectIteration, id,
                        new HashSet<String>());

        Response.ResponseBuilder response = request.evaluatePreconditions(etag);
        if (response != null) {
            return response.build();
        }

        HDocument document =
                documentDAO.getByDocIdAndIteration(hProjectIteration, id);
        documentServiceImpl.makeObsolete(document);
        return Response.ok().build();
    }

    @Override
    public Response getResourceMeta(String idNoSlash, Set<String> extensions) {
        log.debug("start to get resource meta");
        String id = URIHelper.convertFromDocumentURIId(idNoSlash);
        HProjectIteration hProjectIteration = retrieveAndCheckIteration(false);

        EntityTag etag =
                eTagUtils.generateETagForDocument(hProjectIteration, id,
                        extensions);

        Response.ResponseBuilder response = request.evaluatePreconditions(etag);
        if (response != null) {
            return response.build();
        }

        HDocument doc =
                documentDAO.getByDocIdAndIteration(hProjectIteration, id);

        if (doc == null) {
            return Response.status(Response.Status.NOT_FOUND)
                    .entity("document not found").build();
        }

        ResourceMeta entity = new ResourceMeta(doc.getDocId());
        resourceUtils.transferToAbstractResourceMeta(doc, entity);

        // transfer extensions
        resourceUtils.transferToResourceExtensions(doc,
                entity.getExtensions(true), extensions);

        log.debug("successfuly get resource meta: {}", entity);
        return Response.ok().entity(entity).tag(etag).build();
    }

    @Override
    @Restrict("#{s:hasPermission(sourceDocResourceService.securedIteration, 'import-template')}")
    public
            Response putResourceMeta(String idNoSlash,
                    ResourceMeta messageBody, Set<String> extensions) {
        log.debug("start to put resource meta");
        String id = URIHelper.convertFromDocumentURIId(idNoSlash);
        HProjectIteration hProjectIteration = retrieveAndCheckIteration(true);

        EntityTag etag =
                eTagUtils.generateETagForDocument(hProjectIteration, id,
                        extensions);

        Response.ResponseBuilder response = request.evaluatePreconditions(etag);
        if (response != null) {
            return response.build();
        }

        log.debug("pass evaluation");
        log.debug("put resource meta: {}", messageBody);

        HDocument document =
                documentDAO.getByDocIdAndIteration(hProjectIteration, id);
        if (document == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
        if (document.isObsolete()) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
        HLocale hLocale =
                validateTargetLocale(messageBody.getLang(), projectSlug,
                        iterationSlug);
        boolean changed =
                resourceUtils.transferFromResourceMetadata(messageBody,
                        document, extensions, hLocale,
                        document.getRevision() + 1);

        if (changed) {
            documentDAO.flush();
            etag =
                    eTagUtils.generateETagForDocument(hProjectIteration, id,
                            extensions);
        }

        log.debug("put resource meta successfully");
        return Response.ok().tag(etag).lastModified(document.getLastChanged())
                .build();

    }

    private HProjectIteration retrieveAndCheckIteration(boolean writeOperation) {
        HProjectIteration hProjectIteration =
                projectIterationDAO.getBySlug(projectSlug, iterationSlug);
        HProject hProject =
                hProjectIteration == null ? null : hProjectIteration
                        .getProject();

        if (hProjectIteration == null) {
            throw new NoSuchEntityException("Project Iteration '" + projectSlug
                    + ":" + iterationSlug + "' not found.");
        } else if (hProjectIteration.getStatus().equals(EntityStatus.OBSOLETE)
                || hProject.getStatus().equals(EntityStatus.OBSOLETE)) {
            throw new NoSuchEntityException("Project Iteration '" + projectSlug
                    + ":" + iterationSlug + "' not found.");
        } else if (writeOperation) {
            if (hProjectIteration.getStatus().equals(EntityStatus.READONLY)
                    || hProject.getStatus().equals(EntityStatus.READONLY)) {
                throw new ReadOnlyEntityException("Project Iteration '"
                        + projectSlug + ":" + iterationSlug + "' is read-only.");
            } else {
                return hProjectIteration;
            }
        } else {
            return hProjectIteration;
        }
    }

    private HLocale validateTargetLocale(LocaleId locale, String projectSlug,
            String iterationSlug) {
        HLocale hLocale;
        try {
            hLocale =
                    localeServiceImpl.validateLocaleByProjectIteration(locale,
                            projectSlug, iterationSlug);
            return hLocale;
        } catch (ZanataServiceException e) {
            log.warn(
                    "Exception validating target locale {} in proj {} iter {}",
                    e, locale, projectSlug, iterationSlug);
            throw new WebApplicationException(Response
                    .status(Response.Status.FORBIDDEN).entity(e.getMessage())
                    .build());
        }
    }

    public HProjectIteration getSecuredIteration() {
        return retrieveAndCheckIteration(false);
    }

}
TOP

Related Classes of org.zanata.rest.service.SourceDocResourceService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.