/*******************************************************************************
* Copyright (c) 2010-2014 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.skalli.core.rest.resources;
import java.io.IOException;
import java.io.Reader;
import java.text.MessageFormat;
import org.apache.commons.lang.StringUtils;
import org.eclipse.skalli.model.ExtensionEntityBase;
import org.eclipse.skalli.model.Project;
import org.eclipse.skalli.model.ValidationException;
import org.eclipse.skalli.services.entity.EntityServices;
import org.eclipse.skalli.services.extension.rest.ResourceBase;
import org.eclipse.skalli.services.extension.rest.ResourceRepresentation;
import org.eclipse.skalli.services.extension.rest.RestException;
import org.eclipse.skalli.services.extension.rest.RestUtils;
import org.eclipse.skalli.services.permit.Permits;
import org.eclipse.skalli.services.project.ProjectService;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.resource.Get;
import org.restlet.resource.Put;
public class ProjectResource extends ResourceBase {
private static final String ID_PREFIX = "rest:api/projects/{0}"; //$NON-NLS-1$
private static final String ERROR_ID_IO_ERROR = ID_PREFIX +":00"; //$NON-NLS-1$
private static final String ERROR_ID_PARSING_ERROR = ID_PREFIX + ":10"; //$NON-NLS-1$
private static final String ERROR_ID_VALIDATION_FAILED = ID_PREFIX + ":20"; //$NON-NLS-1$
@Get
public Representation retrieve() {
if (!Permits.isAllowed(getAction(), getPath())) {
return createUnauthorizedRepresentation();
}
if (!isSupportedMediaType()) {
setStatus(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE);
return null;
}
String id = (String) getRequestAttributes().get(RestUtils.PARAM_ID);
ProjectService projectService = ((ProjectService)EntityServices.getByEntityClass(Project.class));
Project project = projectService.getProject(id);
if (project == null) {
setStatus(Status.CLIENT_ERROR_NOT_FOUND, MessageFormat.format("Project {0} not found", id)); //$NON-NLS-1$
return null;
}
String[] extensions = ProjectConverter.ALL_EXTENSIONS;
String extensionParam = getQueryAttribute("extensions"); //$NON-NLS-1$
if (extensionParam != null) {
extensions = StringUtils.split(extensionParam, ',');
}
if (enforceOldStyleConverters()) {
return new ResourceRepresentation<Project>(project, new ProjectConverter(getHost(), extensions));
}
return new ResourceRepresentation<Project>(getResourceContext(), project, new ProjectConverter(extensions));
}
@Put
public Representation update(Representation entity) {
if (!Permits.isAllowed(getAction(), getPath())) {
return createUnauthorizedRepresentation();
}
String id = (String) getRequestAttributes().get(RestUtils.PARAM_ID);
ProjectService projectService = ((ProjectService)EntityServices.getByEntityClass(Project.class));
Project project = projectService.loadProject(id);
if (project == null) {
setStatus(Status.CLIENT_ERROR_NOT_FOUND, MessageFormat.format("Project {0} not found", id));
return null;
}
if (entity == null || !entity.isAvailable()) {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST, "Request entity required");
return null;
}
if (!isSupportedMediaType()) {
setStatus(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE);
return null;
}
try {
Reader entityReader = entity.getReader();
if (entityReader == null) {
setStatus(Status.CLIENT_ERROR_BAD_REQUEST, "Request entity required");
return null;
}
Project uploaded = new ResourceRepresentation<Project>(getResourceContext(),
new ProjectConverter()).read(entityReader);
updateProject(project, uploaded);
} catch (RestException e) {
String errorId = MessageFormat.format(ERROR_ID_PARSING_ERROR, id);
return createParseErrorRepresentation(errorId, e);
} catch (IOException e) {
String errorId = MessageFormat.format(ERROR_ID_IO_ERROR, id);
return createIOErrorRepresentation(errorId, e);
}
try {
projectService.persist(project, Permits.getLoggedInUser());
} catch (ValidationException e) {
String errorId = MessageFormat.format(ERROR_ID_VALIDATION_FAILED, id);
return createValidationFailedRepresentation(errorId, id, e);
}
setStatus(Status.SUCCESS_NO_CONTENT);
return null;
}
/**
* Merges the source project into the target project.
* <p>
* The {@link Project#getProjectId() symbolic name} of the target project
* will only be overwritten, if it is not blank in the source project
* (projects always must have a non-blank symbolic name!).
* The UUID of the target project is never changed. All other properties
* of the target project will be overwritten.
* <p>
* The extensions of the target project will only be overwritten selectively,
* i.e. if the source project provides a certain extension then the corresponding
* extensions of the target project will be replaced. If the target project does
* not have theextension yet, it will be added. Extensions that are present
* in the target project but not in the source project will not be removed.
*
* @param target the project retrieved from the project service
* @param source the project read from the request entity
*/
private void updateProject(Project target, Project source) {
if (StringUtils.isNotBlank(source.getProjectId())) {
target.setProjectId(source.getProjectId());
}
target.setName(source.getName());
target.setShortName(source.getShortName());
target.setDescriptionFormat(source.getDescriptionFormat());
target.setDescription(source.getDescription());
target.setProjectTemplateId(source.getProjectTemplateId());
target.setPhase(source.getPhase());
for (ExtensionEntityBase extension : source.getAllExtensions()) {
Class<? extends ExtensionEntityBase> extensionClass = extension.getClass();
if (source.isInherited(extensionClass)) {
target.setInherited(extensionClass, true);
} else {
target.removeExtension(extensionClass);
target.addExtension(extension);
}
}
}
}