All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gooddata.sdk.service.project.ProjectService Maven / Gradle / Ivy

There is a newer version: 3.11.1+api3
Show newest version
/*
 * Copyright (C) 2004-2019, GoodData(R) Corporation. All rights reserved.
 * This source code is licensed under the BSD-style license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */
package com.gooddata.sdk.service.project;

import com.gooddata.sdk.common.GoodDataException;
import com.gooddata.sdk.common.GoodDataRestException;
import com.gooddata.sdk.common.collections.Page;
import com.gooddata.sdk.common.collections.PageBrowser;
import com.gooddata.sdk.common.collections.PageRequest;
import com.gooddata.sdk.common.util.SpringMutableUri;
import com.gooddata.sdk.model.account.Account;
import com.gooddata.sdk.model.gdc.AsyncTask;
import com.gooddata.sdk.model.gdc.UriResponse;
import com.gooddata.sdk.model.project.CreatedInvitations;
import com.gooddata.sdk.model.project.Invitation;
import com.gooddata.sdk.model.project.Invitations;
import com.gooddata.sdk.model.project.Project;
import com.gooddata.sdk.model.project.ProjectTemplate;
import com.gooddata.sdk.model.project.ProjectTemplates;
import com.gooddata.sdk.model.project.ProjectUsersUpdateResult;
import com.gooddata.sdk.model.project.ProjectValidationResults;
import com.gooddata.sdk.model.project.ProjectValidationType;
import com.gooddata.sdk.model.project.ProjectValidations;
import com.gooddata.sdk.model.project.Projects;
import com.gooddata.sdk.model.project.Role;
import com.gooddata.sdk.model.project.Roles;
import com.gooddata.sdk.model.project.User;
import com.gooddata.sdk.model.project.Users;
import com.gooddata.sdk.service.AbstractPollHandler;
import com.gooddata.sdk.service.AbstractService;
import com.gooddata.sdk.service.FutureResult;
import com.gooddata.sdk.service.GoodDataSettings;
import com.gooddata.sdk.service.PollResult;
import com.gooddata.sdk.service.SimplePollHandler;
import com.gooddata.sdk.service.account.AccountService;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriTemplate;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.gooddata.sdk.common.util.Validate.noNullElements;
import static com.gooddata.sdk.common.util.Validate.notEmpty;
import static com.gooddata.sdk.common.util.Validate.notNull;
import static com.gooddata.sdk.common.util.Validate.notNullState;
import static java.util.Arrays.asList;

/**
 * List projects, create a project, ...
 * 

* Usage example: *


 *     ProjectService projectService = gd.getProjectService();
 *     Collection<Project> projects = projectService.getProjects();
 *     Project project = projectService.createProject(new Project("my project", "MyToken"));
 * 
*/ public class ProjectService extends AbstractService { public static final UriTemplate PROJECT_TEMPLATE = new UriTemplate(Project.URI); public static final UriTemplate PROJECT_USERS_TEMPLATE = new UriTemplate(Users.URI); public static final UriTemplate PROJECT_USER_TEMPLATE = new UriTemplate(User.URI); public static final UriTemplate LIST_PROJECTS_TEMPLATE = new UriTemplate(Projects.LIST_PROJECTS_URI); private final AccountService accountService; /** * Constructs service for GoodData project management (list projects, create a project, ...). * @param restTemplate RESTful HTTP Spring template * @param accountService GoodData account service * @param settings settings */ public ProjectService(final RestTemplate restTemplate, final AccountService accountService, final GoodDataSettings settings) { super(restTemplate, settings); this.accountService = notNull(accountService, "accountService"); } /** * Get all projects current user has access to. * * @return collection of all projects current user has access to * @throws com.gooddata.sdk.common.GoodDataException when projects can't be accessed * @deprecated use {@link #listProjects()} or {@link #listProjects(PageRequest)} instead. * Deprecated since version 3.0.0. Will be removed in one of future versions. */ @Deprecated public Collection getProjects() { return listProjects().allItemsStream().collect(Collectors.toList()); } /** * Get browser of projects that current user has access to. * * @return {@link PageBrowser} list of found projects or empty list */ public PageBrowser listProjects() { final String userId = accountService.getCurrent().getId(); return new PageBrowser<>(page -> listProjects(getProjectsUri(userId, page))); } /** * Get defined page of paged list of projects that current user has access to. * * @param startPage page to be retrieved first * @return {@link PageBrowser} list of found projects or empty list */ public PageBrowser listProjects(final PageRequest startPage) { notNull(startPage, "startPage"); final String userId = accountService.getCurrent().getId(); return new PageBrowser<>(startPage, page -> listProjects(getProjectsUri(userId, page))); } private Page listProjects(final URI uri) { try { final Projects projects = restTemplate.getForObject(uri, Projects.class); if (projects == null) { return new Page<>(); } return projects; } catch (GoodDataException | RestClientException e) { throw new GoodDataException("Unable to list projects", e); } } private static URI getProjectsUri(final String userId) { notEmpty(userId, "userId"); return LIST_PROJECTS_TEMPLATE.expand(userId); } private static URI getProjectsUri(final String userId, final PageRequest page) { return page.getPageUri(new SpringMutableUri(getProjectsUri(userId))); } /** * Create new project. * * @param project project to be created * @return created project (including very useful id) * @throws com.gooddata.sdk.common.GoodDataException when projects creation fails */ public FutureResult createProject(final Project project) { notNull(project, "project"); final UriResponse uri; try { uri = restTemplate.postForObject(Projects.URI, project, UriResponse.class); } catch (GoodDataException | RestClientException e) { throw new GoodDataException("Unable to create project", e); } if (uri == null) { throw new GoodDataException("Empty response when project POSTed to API"); } return new PollResult<>(this, new SimplePollHandler(uri.getUri(), Project.class) { @Override public boolean isFinished(ClientHttpResponse response) throws IOException { final Project project = extractData(response, Project.class); return !project.isPreparing(); } @Override protected void onFinish() { if (!getResult().isEnabled()) { throw new GoodDataException("Created project " + uri + " is not enabled"); } } @Override public void handlePollException(final GoodDataRestException e) { throw new GoodDataException("Creating project " + uri + " failed", e); } }); } /** * Get project by URI. * * @param uri URI of project resource (/gdc/projects/{id}) * @return project * @throws com.gooddata.sdk.common.GoodDataException when project can't be accessed */ public Project getProjectByUri(final String uri) { notEmpty(uri, "uri"); try { return restTemplate.getForObject(uri, Project.class); } catch (GoodDataRestException e) { if (HttpStatus.NOT_FOUND.value() == e.getStatusCode()) { throw new ProjectNotFoundException(uri, e); } else { throw e; } } catch (RestClientException e) { throw new GoodDataException("Unable to get project " + uri, e); } } /** * Get project by id. * * @param id id of project * @return project * @throws com.gooddata.sdk.common.GoodDataException when project can't be accessed */ public Project getProjectById(String id) { notEmpty(id, "id"); return getProjectByUri(PROJECT_TEMPLATE.expand(id).toString()); } /** * Removes given project * @param project project to be removed * @throws com.gooddata.sdk.common.GoodDataException when project can't be deleted */ public void removeProject(final Project project) { notNull(project, "project"); notNull(project.getUri(), "project.uri"); try { restTemplate.delete(project.getUri()); } catch (GoodDataRestException | RestClientException e) { throw new GoodDataException("Unable to delete project " + project.getUri(), e); } } public Collection getProjectTemplates(final Project project) { notNull(project, "project"); notNull(project.getId(), "project.id"); try { final ProjectTemplates templates = restTemplate.getForObject(ProjectTemplate.URI, ProjectTemplates.class, project.getId()); return templates != null && templates.getTemplatesInfo() != null ? templates.getTemplatesInfo() : Collections.emptyList(); } catch (GoodDataRestException | RestClientException e) { throw new GoodDataException("Unable to get project templates", e); } } /** * Get available validation types for project. Which can be passed to {@link #validateProject(Project, ProjectValidationType...)}. * * @param project project to fetch validation types for * @return available validations */ public Set getAvailableProjectValidationTypes(final Project project) { notNull(project, "project"); notNull(project.getId(), "project.id"); try { final ProjectValidations projectValidations = restTemplate.getForObject(ProjectValidations.URI, ProjectValidations.class, project.getId()); return projectValidations != null ? projectValidations.getValidations() : Collections.emptySet(); } catch (GoodDataRestException | RestClientException e) { throw new GoodDataException("Unable to get project available validation types", e); } } /** * Validate project using all available validations. * * @param project project to validate * @return results of validation */ public FutureResult validateProject(final Project project) { return validateProject(project, getAvailableProjectValidationTypes(project)); } /** * Validate project with given validations * * @param project project to validate * @param validations validations to use * @return results of validation */ public FutureResult validateProject(final Project project, ProjectValidationType... validations) { return validateProject(project, new HashSet<>(asList(validations))); } /** * Validate project with given validations * * @param project project to validate * @param validations validations to use * @return results of validation */ public FutureResult validateProject(final Project project, Set validations) { notNull(project, "project"); notNull(project.getId(), "project.id"); final AsyncTask task; try { task = restTemplate.postForObject(ProjectValidations.URI, new ProjectValidations(validations), AsyncTask.class, project.getId()); } catch (GoodDataException | RestClientException e) { throw new GoodDataException("Unable to to start project validation", e); } return new PollResult<>(this, // PollHandler able to poll on different URIs (by the Location header) // poll class is Void because the object returned varies between invocations (even on the same URI) new AbstractPollHandler(notNullState(task, "project validation task").getUri(), Void.class, ProjectValidationResults.class) { @Override public boolean isFinished(ClientHttpResponse response) throws IOException { final URI location = response.getHeaders().getLocation(); if (location != null) { setPollingUri(location.toString()); } final boolean finished = super.isFinished(response); if (finished) { try { final ProjectValidationResults result = restTemplate.getForObject(getPollingUri(), getResultClass()); setResult(result); } catch (GoodDataException | RestClientException e) { throw new GoodDataException("Unable to obtain validation results from " + getPollingUri()); } } return finished; } @Override public void handlePollResult(final Void pollResult) { } @Override public void handlePollException(final GoodDataRestException e) { throw new GoodDataException("Project validation failed: " + getPollingUri(), e); } }); } /** * Get browser of users by given project. * * @param project project of users * @return {@link PageBrowser} list of found users or empty list */ public PageBrowser listUsers(final Project project) { notNull(project, "project"); return new PageBrowser<>(page -> listUsers(getUsersUri(project, page))); } /** * Get defined page of paged list of users by given project. * * @param project project of users * @param startPage page to be retrieved first * @return {@link PageBrowser} list of found users or empty list */ public PageBrowser listUsers(final Project project, final PageRequest startPage) { notNull(project, "project"); notNull(startPage, "startPage"); return new PageBrowser<>(startPage, page -> listUsers(getUsersUri(project, page))); } private Page listUsers(final URI uri) { try { final Users users = restTemplate.getForObject(uri, Users.class); if (users == null) { return new Page<>(); } return users; } catch (GoodDataException | RestClientException e) { throw new GoodDataException("Unable to list users", e); } } private static URI getUsersUri(final Project project) { notNull(project.getId(), "project.id"); return PROJECT_USERS_TEMPLATE.expand(project.getId()); } private static URI getUsersUri(final Project project, final PageRequest page) { return page.getPageUri(new SpringMutableUri(getUsersUri(project))); } private static URI getUserUri(final Project project, final Account account) { notNull(account.getId(), "account.id"); return PROJECT_USER_TEMPLATE.expand(project.getId(), account.getId()); } /** * Get set of user role by given project. * * Note: This makes n+1 API calls to retrieve all role details. * * @param project project of roles * @return set of found roles or empty set */ public Set getRoles(final Project project) { notNull(project, "project"); notNull(project.getId(), "project.id"); final Roles roles = restTemplate.getForObject(Roles.URI, Roles.class, project.getId()); if (roles == null) { return Collections.emptySet(); } else { final Set result = new HashSet<>(); for (String roleUri : roles.getRoles()) { final Role role = restTemplate.getForObject(roleUri, Role.class); notNullState(role, "role").setUri(roleUri); result.add(role); } return result; } } /** * Get role by given URI. * * @param uri role uri * @return found role * @throws RoleNotFoundException when the role doesn't exist */ public Role getRoleByUri(String uri) { notEmpty(uri, "uri"); try { final Role role = restTemplate.getForObject(uri, Role.class); notNullState(role, "role").setUri(uri); return role; } catch (GoodDataRestException e) { if (HttpStatus.NOT_FOUND.value() == e.getStatusCode()) { throw new RoleNotFoundException(uri, e); } else { throw e; } } catch (RestClientException e) { throw new GoodDataException("Unable to get role " + uri, e); } } /** * Send project invitations to users * @param project target project * @param invitations invitations * @return created invitation */ public CreatedInvitations sendInvitations(final Project project, final Invitation... invitations) { notNull(project, "project"); notNull(project.getId(), "project.id"); noNullElements(invitations, "invitations"); try { return restTemplate.postForObject(Invitations.URI, new Invitations(invitations), CreatedInvitations.class, project.getId()); } catch (RestClientException e) { final String emails = Arrays.stream(invitations).map(Invitation::getEmail).collect(Collectors.joining(",")); throw new GoodDataException("Unable to invite " + emails + " to project " + project.getId(), e); } } /** * get user in project * * @param project where to find * @param account which user to find * @return User representation in project * @throws UserInProjectNotFoundException when user is not in project */ public User getUser(final Project project, final Account account) { notNull(account, "account"); notEmpty(account.getId(), "account.id"); notNull(project, "project"); try { return restTemplate.getForObject(getUserUri(project, account), User.class); } catch (GoodDataRestException e) { if (HttpStatus.NOT_FOUND.value() == e.getStatusCode()) { throw new UserInProjectNotFoundException("User " + account.getId() + " is not in project", e); } else { throw e; } } catch (RestClientException e) { throw new GoodDataException("Unable to get user " + account.getId() + " in project", e); } } /** Add user in to the project * * @param project where to add user * @param account to be added * @param userRoles list of user roles * @return user added to the project * @throws ProjectUsersUpdateException in case of failure */ public User addUserToProject(final Project project, final Account account, final Role... userRoles) { notNull(project, "project"); notNull(account, "account"); notEmpty(account.getUri(), "account.uri"); notNull(userRoles, "userRoles"); validateRoleURIs(userRoles); notEmpty(project.getId(), "project.id"); final User user = new User(account, userRoles); doPostProjectUsersUpdate(project, user); return getUser(project, account); } /** * Checks whether all the roles have URI specified. */ private void validateRoleURIs(final Role[] userRoles) { final List invalidRoles = new ArrayList<>(); for(Role role: userRoles) { if(role.getUri() == null) { invalidRoles.add(role.getIdentifier()); } } if (!invalidRoles.isEmpty()) { throw new IllegalArgumentException("Roles with URI not specified found: " + invalidRoles); } } /** * Update user in the project * * @param project in which to update user * @param users to update * @throws ProjectUsersUpdateException in case of failure */ public void updateUserInProject(final Project project, final User... users) { notNull(project, "project"); notNull(users, "users"); notEmpty(project.getId(), "project.id"); doPostProjectUsersUpdate(project, users); } private void doPostProjectUsersUpdate(final Project project, final User... users) { final URI usersUri = getUsersUri(project); try { final ProjectUsersUpdateResult projectUsersUpdateResult = restTemplate.postForObject(usersUri, new Users(users), ProjectUsersUpdateResult.class); if (! notNullState(projectUsersUpdateResult, "projectUsersUpdateResult").getFailed().isEmpty()) { throw new ProjectUsersUpdateException("Unable to update users: " + projectUsersUpdateResult.getFailed()); } } catch (RestClientException e) { throw new GoodDataException("Unable to update users in project", e); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy