diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java index a2e7e5213..f7566b86b 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java @@ -1,598 +1,608 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH 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 - */ -package org.eclipse.hawkbit.repository; - -import java.util.Collection; -import java.util.List; -import java.util.Set; - -import javax.validation.constraints.NotNull; - -import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; -import org.eclipse.hawkbit.repository.exception.DistributionSetCreationFailedMissingMandatoryModuleException; -import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; -import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; -import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; -import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; -import org.eclipse.hawkbit.repository.model.Action; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetFilter; -import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; -import org.eclipse.hawkbit.repository.model.DistributionSetTag; -import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; -import org.eclipse.hawkbit.repository.model.DistributionSetType; -import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; -import org.eclipse.hawkbit.repository.model.Tag; -import org.eclipse.hawkbit.repository.model.Target; -import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder; -import org.hibernate.validator.constraints.NotEmpty; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.security.access.prepost.PreAuthorize; - -/** - * Management service for {@link DistributionSet}s. - * - */ -public interface DistributionSetManagement { - - // TODO rename/document the whole with details thing (document what the - // details are and maybe find a better name, e.g. with dependencies?) - - /** - * Assigns {@link SoftwareModule} to existing {@link DistributionSet}. - * - * @param ds - * to assign and update - * @param softwareModules - * to get assigned - * @return the updated {@link DistributionSet}. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSet assignSoftwareModules(@NotNull DistributionSet ds, Set softwareModules); - - /** - * Assign a {@link DistributionSetTag} assignment to given - * {@link DistributionSet}s. - * - * @param dsIds - * to assign for - * @param tag - * to assign - * @return list of assigned ds - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - List assignTag(@NotEmpty Collection dsIds, @NotNull DistributionSetTag tag); - - /** - * Count all {@link DistributionSet}s in the repository that are not marked - * as deleted. - * - * @return number of {@link DistributionSet}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Long countDistributionSetsAll(); - - /** - * Count all {@link DistributionSet}s in the repository that are not marked - * as deleted. - * - * @param type - * to look for - * - * @return number of {@link DistributionSet}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Long countDistributionSetsByType(@NotNull DistributionSetType type); - - /** - * @return number of {@link DistributionSetType}s in the repository. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Long countDistributionSetTypesAll(); - - /** - * Creates a new {@link DistributionSet}. - * - * @param dSet - * {@link DistributionSet} to be created - * @return the new persisted {@link DistributionSet} - * - * @throws EntityAlreadyExistsException - * if a given entity already exists - * @throws DistributionSetCreationFailedMissingMandatoryModuleException - * is {@link DistributionSet} does not contain mandatory - * {@link SoftwareModule}s. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) - DistributionSet createDistributionSet(@NotNull DistributionSet dSet); - - /** - * creates a list of distribution set meta data entries. - * - * @param metadata - * the meta data entries to create or update - * @return the updated or created distribution set meta data entries - * @throws EntityAlreadyExistsException - * in case one of the meta data entry already exists for the - * specific key - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - List createDistributionSetMetadata(@NotEmpty Collection metadata); - - /** - * creates or updates a single distribution set meta data entry. - * - * @param metadata - * the meta data entry to create or update - * @return the updated or created distribution set meta data entry - * @throws EntityAlreadyExistsException - * in case the meta data entry already exists for the specific - * key - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSetMetadata createDistributionSetMetadata(@NotNull DistributionSetMetadata metadata); - - /** - * Creates multiple {@link DistributionSet}s. - * - * @param distributionSets - * to be created - * @return the new {@link DistributionSet}s - * @throws EntityAlreadyExistsException - * if a given entity already exists - * @throws DistributionSetCreationFailedMissingMandatoryModuleException - * is {@link DistributionSet} does not contain mandatory - * {@link SoftwareModule}s. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) - List createDistributionSets(@NotNull Collection distributionSets); - - /** - * Creates new {@link DistributionSetType}. - * - * @param type - * to create - * @return created {@link Entity} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) - DistributionSetType createDistributionSetType(@NotNull DistributionSetType type); - - /** - * Creates multiple {@link DistributionSetType}s. - * - * @param types - * to create - * @return created {@link Entity} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) - List createDistributionSetTypes(@NotNull Collection types); - - /** - *

- * {@link DistributionSet} can be deleted/erased from the repository if they - * have never been assigned to any {@link UpdateAction} or {@link Target}. - *

- * - *

- * If they have been assigned that need to be marked as deleted which as a - * result means that they cannot be assigned anymore to any targets. (define - * e.g. findByDeletedFalse()) - *

- * - * @param set - * to delete - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) - void deleteDistributionSet(@NotNull DistributionSet set); - - /** - * Deleted {@link DistributionSet}s by their IDs. That is either a soft - * delete of the entities have been linked to an {@link UpdateAction} before - * or a hard delete if not. - * - * @param distributionSetIDs - * to be deleted - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) - void deleteDistributionSet(@NotEmpty Long... distributionSetIDs); - - /** - * deletes a distribution set meta data entry. - * - * @param id - * the ID of the distribution set meta data to delete - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - void deleteDistributionSetMetadata(@NotNull final DistributionSet distributionSet, @NotNull final String key); - - /** - * Deletes or mark as delete in case the type is in use. - * - * @param type - * to delete - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) - void deleteDistributionSetType(@NotNull DistributionSetType type); - - /** - * retrieves the distribution set for a given action. - * - * @param action - * the action associated with the distribution set - * @return the distribution set which is associated with the action - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - DistributionSet findDistributionSetByAction(@NotNull Action action); - - /** - * Find {@link DistributionSet} based on given ID without details, e.g. - * {@link DistributionSet#getAgentHub()}. - * - * @param distid - * to look for. - * @return {@link DistributionSet} or null if it does not exist - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - DistributionSet findDistributionSetById(@NotNull Long distid); - - /** - * Find {@link DistributionSet} based on given ID including (lazy loaded) - * details, e.g. {@link DistributionSet#getAgentHub()}. - * - * Note: for performance reasons it is recommended to use - * {@link #findDistributionSetById(Long)} if details are not necessary. - * - * @param distid - * to look for. - * @return {@link DistributionSet} or null if it does not exist - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - DistributionSet findDistributionSetByIdWithDetails(@NotNull Long distid); - - /** - * Find distribution set by name and version. - * - * @param distributionName - * name of {@link DistributionSet}; case insensitive - * @param version - * version of {@link DistributionSet} - * @return the page with the found {@link DistributionSet} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - DistributionSet findDistributionSetByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version); - - /** - * finds all meta data by the given distribution set id. - * - * @param distributionSetId - * the distribution set id to retrieve the meta data from - * @param pageable - * the page request to page the result - * @return a paged result of all meta data entries for a given distribution - * set id - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId, - @NotNull Pageable pageable); - - /** - * finds all meta data by the given distribution set id. - * - * @param distributionSetId - * the distribution set id to retrieve the meta data from - * @param rsqlParam - * rsql query string - * @param pageable - * the page request to page the result - * @return a paged result of all meta data entries for a given distribution - * set id - * - * @throws RSQLParameterUnsupportedFieldException - * if a field in the RSQL string is used but not provided by the - * given {@code fieldNameProvider} - * @throws RSQLParameterSyntaxException - * if the RSQL syntax is wrong - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId, - @NotNull String rsqlParam, @NotNull Pageable pageable); - - /** - * Retrieves {@link DistributionSet} List for overview purposes (no - * {@link SoftwareModule}s and {@link DistributionSetTag}s). - * - * Please use {@link #findDistributionSetListWithDetails(Iterable)} if - * details are required. - * - * @param dist - * List of {@link DistributionSet} IDs to be found - * @return the found {@link DistributionSet}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - List findDistributionSetsAll(Collection dist); - - // TODO discuss: use enum instead of the true,false,null switch ? - /** - * finds all {@link DistributionSet}s. - * - * @param pageReq - * the pagination parameter - * @param deleted - * if TRUE, {@link DistributionSet}s marked as deleted are - * returned. If FALSE, on {@link DistributionSet}s with - * {@link DistributionSet#isDeleted()} == FALSE are returned. - * null if both are to be returned - * @param complete - * to true for returning only completed distribution - * sets or false for only incomplete ones nor - * null to return both. - * @param complete - * set to if false incomplete DS should also be - * shown. - * - * - * @return all found {@link DistributionSet}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findDistributionSetsByDeletedAndOrCompleted(@NotNull Pageable pageReq, Boolean deleted, - Boolean complete); - - /** - * finds all {@link DistributionSet}s. - * - * @param rsqlParam - * rsql query string - * @param pageReq - * the pagination parameter - * @param deleted - * if TRUE, {@link DistributionSet}s marked as deleted are - * returned. If FALSE, on {@link DistributionSet}s with - * {@link DistributionSet#isDeleted()} == FALSE are returned. - * null if both are to be returned - * @return all found {@link DistributionSet}s - * - * @throws RSQLParameterUnsupportedFieldException - * if a field in the RSQL string is used but not provided by the - * given {@code fieldNameProvider} - * @throws RSQLParameterSyntaxException - * if the RSQL syntax is wrong - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findDistributionSetsAll(@NotNull String rsqlParam, @NotNull Pageable pageReq, - Boolean deleted); - - /** - * method retrieves all {@link DistributionSet}s from the repository in the - * following order: - *

- * 1) {@link DistributionSet}s which have the given {@link Target} as - * {@link TargetStatus#getInstalledDistributionSet()} - *

- * 2) {@link DistributionSet}s which have the given {@link Target} as - * {@link Target#getAssignedDistributionSet()} - *

- * 3) {@link DistributionSet}s which have no connection to the given - * {@link Target} ordered by ID of the DistributionSet. - * - * @param pageable - * the page request to page the result set * - * @param distributionSetFilterBuilder - * has details of filters to be applied - * @param assignedOrInstalled - * the controllerID of the Target to be ordered by - * @return - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findDistributionSetsAllOrderedByLinkTarget(@NotNull Pageable pageable, - @NotNull DistributionSetFilterBuilder distributionSetFilterBuilder, @NotEmpty String assignedOrInstalled); - - /** - * retrieves {@link DistributionSet}s by filtering on the given parameters. - * - * @param pageable - * page parameter - * @param distributionSetFilter - * has details of filters to be applied. - * @return the page of found {@link DistributionSet} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findDistributionSetsByFilters(@NotNull Pageable pageable, - @NotNull DistributionSetFilter distributionSetFilter); - - /** - * @param id - * as {@link DistributionSetType#getId()} - * @return {@link DistributionSetType} if found or null if not - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - DistributionSetType findDistributionSetTypeById(@NotNull Long id); - - /** - * @param key - * as {@link DistributionSetType#getKey()} - * @return {@link DistributionSetType} if found or null if not - */ - - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - DistributionSetType findDistributionSetTypeByKey(@NotNull String key); - - /** - * @param name - * as {@link DistributionSetType#getName()} - * @return {@link DistributionSetType} if found or null if not - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - DistributionSetType findDistributionSetTypeByName(@NotEmpty String name); - - /** - * @param pageable - * parameter - * @return all {@link DistributionSetType}s in the repository. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findDistributionSetTypesAll(@NotNull Pageable pageable); - - /** - * Generic predicate based query for {@link DistributionSetType}. - * - * @param rsqlParam - * rsql query string - * @param pageable - * parameter for paging - * - * @return the found {@link SoftwareModuleType}s - * - * @throws RSQLParameterUnsupportedFieldException - * if a field in the RSQL string is used but not provided by the - * given {@code fieldNameProvider} - * @throws RSQLParameterSyntaxException - * if the RSQL syntax is wrong - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findDistributionSetTypesAll(@NotNull String rsqlParam, @NotNull Pageable pageable); - - /** - * finds a single distribution set meta data by its id. - * - * @param id - * the id of the distribution set meta data containing the meta - * data key and the ID of the distribution set - * @return the found DistributionSetMetadata or {@code null} if not exits - * @throws EntityNotFoundException - * in case the meta data does not exists for the given key - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - DistributionSetMetadata findOne(@NotNull DistributionSet distributionSet, @NotNull String key); - - /** - * Checks if a {@link DistributionSet} is currently in use by a target in - * the repository. - * - * @param distributionSet - * to check - * - * @return true if in use - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - boolean isDistributionSetInUse(@NotNull DistributionSet distributionSet); - - /** - * {@link Entity} based method call for - * {@link #toggleTagAssignment(Collection, String)}. - * - * @param sets - * to toggle for - * @param tag - * to toggle - * @return {@link DistributionSetTagAssignmentResult} with all meta data of - * the assignment outcome. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSetTagAssignmentResult toggleTagAssignment(@NotEmpty Collection sets, - @NotNull DistributionSetTag tag); - - /** - * Toggles {@link DistributionSetTag} assignment to given - * {@link DistributionSet}s by means that if some (or all) of the targets in - * the list have the {@link Tag} not yet assigned, they will be. If all of - * theme have the tag already assigned they will be removed instead. - * - * @param dsIds - * to toggle for - * @param tagName - * to toggle - * @return {@link DistributionSetTagAssignmentResult} with all meta data of - * the assignment outcome. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSetTagAssignmentResult toggleTagAssignment(@NotEmpty Collection dsIds, @NotNull String tagName); - - /** - * Unassign all {@link DistributionSet} from a given - * {@link DistributionSetTag} . - * - * @param tag - * to unassign all ds - * @return list of unassigned ds - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - List unAssignAllDistributionSetsByTag(@NotNull DistributionSetTag tag); - - /** - * Unassigns a {@link SoftwareModule} form an existing - * {@link DistributionSet}. - * - * @param ds - * to get unassigned form - * @param softwareModule - * to get unassigned - * @return the updated {@link DistributionSet}. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSet unassignSoftwareModule(@NotNull DistributionSet ds, @NotNull SoftwareModule softwareModule); - - /** - * Unassign a {@link DistributionSetTag} assignment to given - * {@link DistributionSet}. - * - * @param dsId - * to unassign for - * @param distributionSetTag - * to unassign - * @return the unassigned ds or if no ds is unassigned - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSet unAssignTag(@NotNull Long dsId, @NotNull DistributionSetTag distributionSetTag); - - /** - * Updates existing {@link DistributionSet}. - * - * @param ds - * to update - * @return the saved {@link Entity}. - * @throws NullPointerException - * of {@link DistributionSet#getId()} is null - * @throw DataDependencyViolationException in case of illegal update - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSet updateDistributionSet(@NotNull DistributionSet ds); - - /** - * updates a distribution set meta data value if corresponding entry exists. - * - * @param metadata - * the meta data entry to be updated - * @return the updated meta data entry - * @throws EntityNotFoundException - * in case the meta data entry does not exists and cannot be - * updated - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSetMetadata updateDistributionSetMetadata(@NotNull DistributionSetMetadata metadata); - - /** - * Updates existing {@link DistributionSetType}. However, keep in mind that - * is not possible to change the {@link DistributionSetTypeElement}s while - * the DS type is already in use. - * - * @param dsType - * to update - * @return updated {@link Entity} - * - * @throws EntityReadOnlyException - * if use tries to change the {@link DistributionSetTypeElement} - * s while the DS type is already in use. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - DistributionSetType updateDistributionSetType(@NotNull DistributionSetType dsType); - -} +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH 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 + */ +package org.eclipse.hawkbit.repository; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import javax.validation.constraints.NotNull; + +import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; +import org.eclipse.hawkbit.repository.exception.DistributionSetCreationFailedMissingMandatoryModuleException; +import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; +import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; +import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; +import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; +import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.DistributionSetFilter; +import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder; +import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; +import org.eclipse.hawkbit.repository.model.DistributionSetTag; +import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; +import org.eclipse.hawkbit.repository.model.DistributionSetType; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.eclipse.hawkbit.repository.model.Tag; +import org.eclipse.hawkbit.repository.model.Target; +import org.hibernate.validator.constraints.NotEmpty; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.security.access.prepost.PreAuthorize; + +/** + * Management service for {@link DistributionSet}s. + * + */ +public interface DistributionSetManagement { + + // TODO rename/document the whole with details thing (document what the + // details are and maybe find a better name, e.g. with dependencies?) + + /** + * Assigns {@link SoftwareModule} to existing {@link DistributionSet}. + * + * @param ds + * to assign and update + * @param softwareModules + * to get assigned + * @return the updated {@link DistributionSet}. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + DistributionSet assignSoftwareModules(@NotNull DistributionSet ds, Set softwareModules); + + /** + * Assign a {@link DistributionSetTag} assignment to given + * {@link DistributionSet}s. + * + * @param dsIds + * to assign for + * @param tag + * to assign + * @return list of assigned ds + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + List assignTag(@NotEmpty Collection dsIds, @NotNull DistributionSetTag tag); + + /** + * Count all {@link DistributionSet}s in the repository that are not marked + * as deleted. + * + * @return number of {@link DistributionSet}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Long countDistributionSetsAll(); + + /** + * Count all {@link DistributionSet}s in the repository that are not marked + * as deleted. + * + * @param type + * to look for + * + * @return number of {@link DistributionSet}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Long countDistributionSetsByType(@NotNull DistributionSetType type); + + /** + * @return number of {@link DistributionSetType}s in the repository. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Long countDistributionSetTypesAll(); + + /** + * Creates a new {@link DistributionSet}. + * + * @param dSet + * {@link DistributionSet} to be created + * @return the new persisted {@link DistributionSet} + * + * @throws EntityAlreadyExistsException + * if a given entity already exists + * @throws DistributionSetCreationFailedMissingMandatoryModuleException + * is {@link DistributionSet} does not contain mandatory + * {@link SoftwareModule}s. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) + DistributionSet createDistributionSet(@NotNull DistributionSet dSet); + + /** + * creates a list of distribution set meta data entries. + * + * @param metadata + * the meta data entries to create or update + * @return the updated or created distribution set meta data entries + * @throws EntityAlreadyExistsException + * in case one of the meta data entry already exists for the + * specific key + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + List createDistributionSetMetadata(@NotEmpty Collection metadata); + + /** + * creates or updates a single distribution set meta data entry. + * + * @param metadata + * the meta data entry to create or update + * @return the updated or created distribution set meta data entry + * @throws EntityAlreadyExistsException + * in case the meta data entry already exists for the specific + * key + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + DistributionSetMetadata createDistributionSetMetadata(@NotNull DistributionSetMetadata metadata); + + /** + * Creates multiple {@link DistributionSet}s. + * + * @param distributionSets + * to be created + * @return the new {@link DistributionSet}s + * @throws EntityAlreadyExistsException + * if a given entity already exists + * @throws DistributionSetCreationFailedMissingMandatoryModuleException + * is {@link DistributionSet} does not contain mandatory + * {@link SoftwareModule}s. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) + List createDistributionSets(@NotNull Collection distributionSets); + + /** + * Creates new {@link DistributionSetType}. + * + * @param type + * to create + * @return created {@link Entity} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) + DistributionSetType createDistributionSetType(@NotNull DistributionSetType type); + + /** + * Creates multiple {@link DistributionSetType}s. + * + * @param types + * to create + * @return created {@link Entity} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) + List createDistributionSetTypes(@NotNull Collection types); + + /** + *

+ * {@link DistributionSet} can be deleted/erased from the repository if they + * have never been assigned to any {@link UpdateAction} or {@link Target}. + *

+ * + *

+ * If they have been assigned that need to be marked as deleted which as a + * result means that they cannot be assigned anymore to any targets. (define + * e.g. findByDeletedFalse()) + *

+ * + * @param set + * to delete + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) + void deleteDistributionSet(@NotNull DistributionSet set); + + /** + * Deleted {@link DistributionSet}s by their IDs. That is either a soft + * delete of the entities have been linked to an {@link UpdateAction} before + * or a hard delete if not. + * + * @param distributionSetIDs + * to be deleted + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) + void deleteDistributionSet(@NotEmpty Long... distributionSetIDs); + + /** + * deletes a distribution set meta data entry. + * + * @param id + * the ID of the distribution set meta data to delete + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + void deleteDistributionSetMetadata(@NotNull final DistributionSet distributionSet, @NotNull final String key); + + /** + * Deletes or mark as delete in case the type is in use. + * + * @param type + * to delete + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) + void deleteDistributionSetType(@NotNull DistributionSetType type); + + /** + * retrieves the distribution set for a given action. + * + * @param action + * the action associated with the distribution set + * @return the distribution set which is associated with the action + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + DistributionSet findDistributionSetByAction(@NotNull Action action); + + /** + * Find {@link DistributionSet} based on given ID without details, e.g. + * {@link DistributionSet#getAgentHub()}. + * + * @param distid + * to look for. + * @return {@link DistributionSet} or null if it does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + DistributionSet findDistributionSetById(@NotNull Long distid); + + /** + * Find {@link DistributionSet} based on given ID including (lazy loaded) + * details, e.g. {@link DistributionSet#getAgentHub()}. + * + * Note: for performance reasons it is recommended to use + * {@link #findDistributionSetById(Long)} if details are not necessary. + * + * @param distid + * to look for. + * @return {@link DistributionSet} or null if it does not exist + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + DistributionSet findDistributionSetByIdWithDetails(@NotNull Long distid); + + /** + * Find distribution set by name and version. + * + * @param distributionName + * name of {@link DistributionSet}; case insensitive + * @param version + * version of {@link DistributionSet} + * @return the page with the found {@link DistributionSet} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + DistributionSet findDistributionSetByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version); + + /** + * finds all meta data by the given distribution set id. + * + * @param distributionSetId + * the distribution set id to retrieve the meta data from + * @param pageable + * the page request to page the result + * @return a paged result of all meta data entries for a given distribution + * set id + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId, + @NotNull Pageable pageable); + + /** + * finds all meta data by the given distribution set id. + * + * @param distributionSetId + * the distribution set id to retrieve the meta data from + * @return list of distributionSetMetadata for a given distribution set Id + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + List findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId); + + /** + * finds all meta data by the given distribution set id. + * + * @param distributionSetId + * the distribution set id to retrieve the meta data from + * @param rsqlParam + * rsql query string + * @param pageable + * the page request to page the result + * @return a paged result of all meta data entries for a given distribution + * set id + * + * @throws RSQLParameterUnsupportedFieldException + * if a field in the RSQL string is used but not provided by the + * given {@code fieldNameProvider} + * @throws RSQLParameterSyntaxException + * if the RSQL syntax is wrong + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId, + @NotNull String rsqlParam, @NotNull Pageable pageable); + + /** + * Retrieves {@link DistributionSet} List for overview purposes (no + * {@link SoftwareModule}s and {@link DistributionSetTag}s). + * + * Please use {@link #findDistributionSetListWithDetails(Iterable)} if + * details are required. + * + * @param dist + * List of {@link DistributionSet} IDs to be found + * @return the found {@link DistributionSet}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + List findDistributionSetsAll(Collection dist); + + // TODO discuss: use enum instead of the true,false,null switch ? + /** + * finds all {@link DistributionSet}s. + * + * @param pageReq + * the pagination parameter + * @param deleted + * if TRUE, {@link DistributionSet}s marked as deleted are + * returned. If FALSE, on {@link DistributionSet}s with + * {@link DistributionSet#isDeleted()} == FALSE are returned. + * null if both are to be returned + * @param complete + * to true for returning only completed distribution + * sets or false for only incomplete ones nor + * null to return both. + * @param complete + * set to if false incomplete DS should also be + * shown. + * + * + * @return all found {@link DistributionSet}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findDistributionSetsByDeletedAndOrCompleted(@NotNull Pageable pageReq, Boolean deleted, + Boolean complete); + + /** + * finds all {@link DistributionSet}s. + * + * @param rsqlParam + * rsql query string + * @param pageReq + * the pagination parameter + * @param deleted + * if TRUE, {@link DistributionSet}s marked as deleted are + * returned. If FALSE, on {@link DistributionSet}s with + * {@link DistributionSet#isDeleted()} == FALSE are returned. + * null if both are to be returned + * @return all found {@link DistributionSet}s + * + * @throws RSQLParameterUnsupportedFieldException + * if a field in the RSQL string is used but not provided by the + * given {@code fieldNameProvider} + * @throws RSQLParameterSyntaxException + * if the RSQL syntax is wrong + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findDistributionSetsAll(@NotNull String rsqlParam, @NotNull Pageable pageReq, + Boolean deleted); + + /** + * method retrieves all {@link DistributionSet}s from the repository in the + * following order: + *

+ * 1) {@link DistributionSet}s which have the given {@link Target} as + * {@link TargetStatus#getInstalledDistributionSet()} + *

+ * 2) {@link DistributionSet}s which have the given {@link Target} as + * {@link Target#getAssignedDistributionSet()} + *

+ * 3) {@link DistributionSet}s which have no connection to the given + * {@link Target} ordered by ID of the DistributionSet. + * + * @param pageable + * the page request to page the result set * + * @param distributionSetFilterBuilder + * has details of filters to be applied + * @param assignedOrInstalled + * the controllerID of the Target to be ordered by + * @return + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findDistributionSetsAllOrderedByLinkTarget(@NotNull Pageable pageable, + @NotNull DistributionSetFilterBuilder distributionSetFilterBuilder, @NotEmpty String assignedOrInstalled); + + /** + * retrieves {@link DistributionSet}s by filtering on the given parameters. + * + * @param pageable + * page parameter + * @param distributionSetFilter + * has details of filters to be applied. + * @return the page of found {@link DistributionSet} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findDistributionSetsByFilters(@NotNull Pageable pageable, + @NotNull DistributionSetFilter distributionSetFilter); + + /** + * @param id + * as {@link DistributionSetType#getId()} + * @return {@link DistributionSetType} if found or null if not + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + DistributionSetType findDistributionSetTypeById(@NotNull Long id); + + /** + * @param key + * as {@link DistributionSetType#getKey()} + * @return {@link DistributionSetType} if found or null if not + */ + + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + DistributionSetType findDistributionSetTypeByKey(@NotNull String key); + + /** + * @param name + * as {@link DistributionSetType#getName()} + * @return {@link DistributionSetType} if found or null if not + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + DistributionSetType findDistributionSetTypeByName(@NotEmpty String name); + + /** + * @param pageable + * parameter + * @return all {@link DistributionSetType}s in the repository. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findDistributionSetTypesAll(@NotNull Pageable pageable); + + /** + * Generic predicate based query for {@link DistributionSetType}. + * + * @param rsqlParam + * rsql query string + * @param pageable + * parameter for paging + * + * @return the found {@link SoftwareModuleType}s + * + * @throws RSQLParameterUnsupportedFieldException + * if a field in the RSQL string is used but not provided by the + * given {@code fieldNameProvider} + * @throws RSQLParameterSyntaxException + * if the RSQL syntax is wrong + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findDistributionSetTypesAll(@NotNull String rsqlParam, @NotNull Pageable pageable); + + /** + * finds a single distribution set meta data by its id. + * + * @param id + * the id of the distribution set meta data containing the meta + * data key and the ID of the distribution set + * @return the found DistributionSetMetadata or {@code null} if not exits + * @throws EntityNotFoundException + * in case the meta data does not exists for the given key + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + DistributionSetMetadata findOne(@NotNull DistributionSet distributionSet, @NotNull String key); + + /** + * Checks if a {@link DistributionSet} is currently in use by a target in + * the repository. + * + * @param distributionSet + * to check + * + * @return true if in use + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + boolean isDistributionSetInUse(@NotNull DistributionSet distributionSet); + + /** + * {@link Entity} based method call for + * {@link #toggleTagAssignment(Collection, String)}. + * + * @param sets + * to toggle for + * @param tag + * to toggle + * @return {@link DistributionSetTagAssignmentResult} with all meta data of + * the assignment outcome. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + DistributionSetTagAssignmentResult toggleTagAssignment(@NotEmpty Collection sets, + @NotNull DistributionSetTag tag); + + /** + * Toggles {@link DistributionSetTag} assignment to given + * {@link DistributionSet}s by means that if some (or all) of the targets in + * the list have the {@link Tag} not yet assigned, they will be. If all of + * theme have the tag already assigned they will be removed instead. + * + * @param dsIds + * to toggle for + * @param tagName + * to toggle + * @return {@link DistributionSetTagAssignmentResult} with all meta data of + * the assignment outcome. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + DistributionSetTagAssignmentResult toggleTagAssignment(@NotEmpty Collection dsIds, @NotNull String tagName); + + /** + * Unassign all {@link DistributionSet} from a given + * {@link DistributionSetTag} . + * + * @param tag + * to unassign all ds + * @return list of unassigned ds + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + List unAssignAllDistributionSetsByTag(@NotNull DistributionSetTag tag); + + /** + * Unassigns a {@link SoftwareModule} form an existing + * {@link DistributionSet}. + * + * @param ds + * to get unassigned form + * @param softwareModule + * to get unassigned + * @return the updated {@link DistributionSet}. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + DistributionSet unassignSoftwareModule(@NotNull DistributionSet ds, @NotNull SoftwareModule softwareModule); + + /** + * Unassign a {@link DistributionSetTag} assignment to given + * {@link DistributionSet}. + * + * @param dsId + * to unassign for + * @param distributionSetTag + * to unassign + * @return the unassigned ds or if no ds is unassigned + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + DistributionSet unAssignTag(@NotNull Long dsId, @NotNull DistributionSetTag distributionSetTag); + + /** + * Updates existing {@link DistributionSet}. + * + * @param ds + * to update + * @return the saved {@link Entity}. + * @throws NullPointerException + * of {@link DistributionSet#getId()} is null + * @throw DataDependencyViolationException in case of illegal update + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + DistributionSet updateDistributionSet(@NotNull DistributionSet ds); + + /** + * updates a distribution set meta data value if corresponding entry exists. + * + * @param metadata + * the meta data entry to be updated + * @return the updated meta data entry + * @throws EntityNotFoundException + * in case the meta data entry does not exists and cannot be + * updated + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + DistributionSetMetadata updateDistributionSetMetadata(@NotNull DistributionSetMetadata metadata); + + /** + * Updates existing {@link DistributionSetType}. However, keep in mind that + * is not possible to change the {@link DistributionSetTypeElement}s while + * the DS type is already in use. + * + * @param dsType + * to update + * @return updated {@link Entity} + * + * @throws EntityReadOnlyException + * if use tries to change the {@link DistributionSetTypeElement} + * s while the DS type is already in use. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + DistributionSetType updateDistributionSetType(@NotNull DistributionSetType dsType); + +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java index 0934e871e..e48aaa3ab 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java @@ -1,486 +1,504 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH 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 - */ -package org.eclipse.hawkbit.repository; - -import java.util.Collection; -import java.util.List; - -import javax.validation.constraints.NotNull; - -import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; -import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; -import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; -import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; -import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; -import org.hibernate.validator.constraints.NotEmpty; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.security.access.prepost.PreAuthorize; - -/** - * Service for managing {@link SoftwareModule}s. - * - */ -public interface SoftwareManagement { - - /** - * Counts {@link SoftwareModule}s with given - * {@link SoftwareModule#getName()} or {@link SoftwareModule#getVersion()} - * and {@link SoftwareModule#getType()} that are not marked as deleted. - * - * @param searchText - * to search for in name and version - * @param type - * to filter the result - * @return number of found {@link SoftwareModule}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Long countSoftwareModuleByFilters(String searchText, SoftwareModuleType type); - - /** - * Count all {@link SoftwareModule}s in the repository that are not marked - * as deleted. - * - * @return number of {@link SoftwareModule}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Long countSoftwareModulesAll(); - - /** - * Counts {@link SoftwareModule}s with given {@link SoftwareModuleType}. - * - * @param type - * to count - * @return number of found {@link SoftwareModule}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Long countSoftwareModulesByType(@NotNull SoftwareModuleType type); - - /** - * @return number of {@link SoftwareModuleType}s in the repository. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Long countSoftwareModuleTypesAll(); - - /** - * Create {@link SoftwareModule}s in the repository. - * - * @param swModules - * {@link SoftwareModule}s to create - * @return SoftwareModule - * @throws EntityAlreadyExistsException - * if a given entity already exists - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) - List createSoftwareModule(@NotNull Collection swModules); - - /** - * - * @param swModule - * SoftwareModule to create - * @return SoftwareModule - * @throws EntityAlreadyExistsException - * if a given entity already exists - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) - SoftwareModule createSoftwareModule(@NotNull SoftwareModule swModule); - - /** - * creates a list of software module meta data entries. - * - * @param metadata - * the meta data entries to create or update - * @return the updated or created software module meta data entries - * @throws EntityAlreadyExistsException - * in case one of the meta data entry already exists for the - * specific key - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - List createSoftwareModuleMetadata(@NotNull Collection metadata); - - /** - * creates or updates a single software module meta data entry. - * - * @param metadata - * the meta data entry to create or update - * @return the updated or created software module meta data entry - * @throws EntityAlreadyExistsException - * in case the meta data entry already exists for the specific - * key - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - SoftwareModuleMetadata createSoftwareModuleMetadata(@NotNull SoftwareModuleMetadata metadata); - - /** - * Creates multiple {@link SoftwareModuleType}s. - * - * @param types - * to create - * @return created {@link Entity} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) - List createSoftwareModuleType(@NotNull final Collection types); - - /** - * Creates new {@link SoftwareModuleType}. - * - * @param type - * to create - * @return created {@link Entity} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) - SoftwareModuleType createSoftwareModuleType(@NotNull SoftwareModuleType type); - - /** - * Deletes the given {@link SoftwareModule} {@link Entity}. - * - * @param bsm - * is the {@link SoftwareModule} to be deleted - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) - void deleteSoftwareModule(@NotNull SoftwareModule bsm); - - /** - * deletes a software module meta data entry. - * - * @param id - * the ID of the software module meta data to delete - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - void deleteSoftwareModuleMetadata(@NotNull SoftwareModule softwareModule, @NotNull String key); - - /** - * Deletes {@link SoftwareModule}s which is any if the given ids. - * - * @param ids - * of the Software Modules to be deleted - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) - void deleteSoftwareModules(@NotNull Collection ids); - - /** - * Deletes or marks as delete in case the type is in use. - * - * @param type - * to delete - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) - void deleteSoftwareModuleType(@NotNull SoftwareModuleType type); - - /** - * @param pageable - * the page request to page the result set - * @param set - * to search for - * @return all {@link SoftwareModule}s that are assigned to given - * {@link DistributionSet}. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findSoftwareModuleByAssignedTo(@NotNull Pageable pageable, @NotNull DistributionSet set); - - /** - * @param pageable - * the page request to page the result set - * @param set - * to search for - * @param type - * to filter - * @return all {@link SoftwareModule}s that are assigned to given - * {@link DistributionSet} filtered by {@link SoftwareModuleType}. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findSoftwareModuleByAssignedToAndType(@NotNull Pageable pageable, @NotNull DistributionSet set, - @NotNull SoftwareModuleType type); - - /** - * Filter {@link SoftwareModule}s with given - * {@link SoftwareModule#getName()} or {@link SoftwareModule#getVersion()} - * and {@link SoftwareModule#getType()} that are not marked as deleted. - * - * @param pageable - * page parameter - * @param searchText - * to be filtered as "like" on {@link SoftwareModule#getName()} - * @param type - * to be filtered as "like" on {@link SoftwareModule#getType()} - * @return the page of found {@link SoftwareModule} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Slice findSoftwareModuleByFilters(@NotNull Pageable pageable, String searchText, - SoftwareModuleType type); - - /** - * Finds {@link SoftwareModule} by given id. - * - * @param id - * to search for - * @return the found {@link SoftwareModule}s or null if not - * found. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR - + SpringEvalExpressions.IS_CONTROLLER) - SoftwareModule findSoftwareModuleById(@NotNull Long id); - - /** - * retrieves {@link SoftwareModule} by their name AND version AND type.. - * - * @param name - * of the {@link SoftwareModule} - * @param version - * of the {@link SoftwareModule} - * @param type - * of the {@link SoftwareModule} - * @return the found {@link SoftwareModule} or null - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - SoftwareModule findSoftwareModuleByNameAndVersion(@NotEmpty String name, @NotEmpty String version, - @NotNull SoftwareModuleType type); - - /** - * finds a single software module meta data by its id. - * - * @param id - * the id of the software module meta data containing the meta - * data key and the ID of the software module - * @return the found SoftwareModuleMetadata or {@code null} if not exits - * @throws EntityNotFoundException - * in case the meta data does not exists for the given key - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - SoftwareModuleMetadata findSoftwareModuleMetadata(@NotNull SoftwareModule softwareModule, @NotEmpty String key); - - /** - * finds all meta data by the given software module id. - * - * @param swId - * the software module id to retrieve the meta data from - * @param pageable - * the page request to page the result - * @return a paged result of all meta data entries for a given software - * module id - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findSoftwareModuleMetadataBySoftwareModuleId(@NotNull Long swId, - @NotNull Pageable pageable); - - /** - * finds all meta data by the given software module id. - * - * @param softwareModuleId - * the software module id to retrieve the meta data from - * @param spec - * the specification to filter the result - * @param pageable - * the page request to page the result - * @return a paged result of all meta data entries for a given software - * module id - * - * @throws RSQLParameterUnsupportedFieldException - * if a field in the RSQL string is used but not provided by the - * given {@code fieldNameProvider} - * @throws RSQLParameterSyntaxException - * if the RSQL syntax is wrong - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findSoftwareModuleMetadataBySoftwareModuleId(@NotNull Long softwareModuleId, - @NotNull String rsqlParam, @NotNull Pageable pageable); - - /** - * Filter {@link SoftwareModule}s with given - * {@link SoftwareModule#getName()} or {@link SoftwareModule#getVersion()} - * search text and {@link SoftwareModule#getType()} that are not marked as - * deleted and sort them by means of given distribution set related modules - * on top of the list. - * - * After that the modules are sorted by {@link SoftwareModule#getName()} and - * {@link SoftwareModule#getVersion()} in ascending order. - * - * @param pageable - * page parameter - * @param orderByDistributionId - * the ID of distribution set to be ordered on top - * @param searchText - * filtered as "like" on {@link SoftwareModule#getName()} - * @param type - * filtered as "equal" on {@link SoftwareModule#getType()} - * @return the page of found {@link SoftwareModule} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Slice findSoftwareModuleOrderBySetAssignmentAndModuleNameAscModuleVersionAsc( - @NotNull Pageable pageable, @NotNull Long orderByDistributionId, String searchText, - SoftwareModuleType type); - - /** - * Retrieves all software modules. Deleted ones are filtered. - * - * @param pageable - * pagination parameter - * @return the found {@link SoftwareModule}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Slice findSoftwareModulesAll(@NotNull Pageable pageable); - - /** - * Retrieves all software modules with a given list of ids - * {@link SoftwareModule#getId()}. - * - * @param ids - * to search for - * @return {@link List} of found {@link SoftwareModule}s - */ - List findSoftwareModulesById(@NotEmpty Collection ids); - - /** - * Retrieves all {@link SoftwareModule}s with a given specification. - * - * @param spec - * the specification to filter the software modules - * @param pageable - * pagination parameter - * @return the found {@link SoftwareModule}s - * - * @throws RSQLParameterUnsupportedFieldException - * if a field in the RSQL string is used but not provided by the - * given {@code fieldNameProvider} - * @throws RSQLParameterSyntaxException - * if the RSQL syntax is wrong - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findSoftwareModulesByPredicate(@NotNull String rsqlParam, @NotNull Pageable pageable); - - /** - * retrieves the {@link SoftwareModule}s by their {@link SoftwareModuleType} - * . - * - * @param pageable - * page parameters - * @param type - * to be filtered on - * @return the found {@link SoftwareModule}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Slice findSoftwareModulesByType(@NotNull Pageable pageable, @NotNull SoftwareModuleType type); - - /** - * - * @param id - * to search for - * @return {@link SoftwareModuleType} in the repository with given - * {@link SoftwareModuleType#getId()} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - SoftwareModuleType findSoftwareModuleTypeById(@NotNull Long id); - - /** - * - * @param key - * to search for - * @return {@link SoftwareModuleType} in the repository with given - * {@link SoftwareModuleType#getKey()} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - SoftwareModuleType findSoftwareModuleTypeByKey(@NotNull String key); - - /** - * - * @param name - * to search for - * @return all {@link SoftwareModuleType}s in the repository with given - * {@link SoftwareModuleType#getName()} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - SoftwareModuleType findSoftwareModuleTypeByName(@NotNull String name); - - /** - * @param pageable - * parameter - * @return all {@link SoftwareModuleType}s in the repository. - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findSoftwareModuleTypesAll(@NotNull Pageable pageable); - - /** - * Retrieves all {@link SoftwareModuleType}s with a given specification. - * - * @param spec - * the specification to filter the software modules types - * @param pageable - * pagination parameter - * @return the found {@link SoftwareModuleType}s - * - * @throws RSQLParameterUnsupportedFieldException - * if a field in the RSQL string is used but not provided by the - * given {@code fieldNameProvider} - * @throws RSQLParameterSyntaxException - * if the RSQL syntax is wrong - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - Page findSoftwareModuleTypesAll(@NotNull String rsqlParam, @NotNull Pageable pageable); - - /** - * Retrieves software module including details ( - * {@link SoftwareModule#getArtifacts()}). - * - * @param id - * parameter - * @param isDeleted - * parameter - * @return the found {@link SoftwareModule}s - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - SoftwareModule findSoftwareModuleWithDetails(@NotNull Long id); - - /** - * Updates existing {@link SoftwareModule}. Update-able values are - * {@link SoftwareModule#getDescription()} - * {@link SoftwareModule#getVendor()}. - * - * @param sm - * to update - * - * @return the saved {@link Entity}. - * - * @throws NullPointerException - * of {@link SoftwareModule#getId()} is null - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - SoftwareModule updateSoftwareModule(@NotNull SoftwareModule sm); - - /** - * updates a distribution set meta data value if corresponding entry exists. - * - * @param metadata - * the meta data entry to be updated - * @return the updated meta data entry - * @throws EntityNotFoundException - * in case the meta data entry does not exists and cannot be - * updated - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - SoftwareModuleMetadata updateSoftwareModuleMetadata(@NotNull SoftwareModuleMetadata metadata); - - /** - * Updates existing {@link SoftwareModuleType}. Update-able value is - * {@link SoftwareModuleType#getDescription()} and - * {@link SoftwareModuleType#getColour()}. - * - * @param sm - * to update - * @return updated {@link Entity} - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) - SoftwareModuleType updateSoftwareModuleType(@NotNull SoftwareModuleType sm); - -} +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH 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 + */ +package org.eclipse.hawkbit.repository; + +import java.util.Collection; +import java.util.List; + +import javax.validation.constraints.NotNull; + +import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; +import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; +import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; +import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; +import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; +import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.hibernate.validator.constraints.NotEmpty; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.security.access.prepost.PreAuthorize; + +/** + * Service for managing {@link SoftwareModule}s. + * + */ +public interface SoftwareManagement { + + /** + * Counts {@link SoftwareModule}s with given + * {@link SoftwareModule#getName()} or {@link SoftwareModule#getVersion()} + * and {@link SoftwareModule#getType()} that are not marked as deleted. + * + * @param searchText + * to search for in name and version + * @param type + * to filter the result + * @return number of found {@link SoftwareModule}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Long countSoftwareModuleByFilters(String searchText, SoftwareModuleType type); + + /** + * Count all {@link SoftwareModule}s in the repository that are not marked + * as deleted. + * + * @return number of {@link SoftwareModule}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Long countSoftwareModulesAll(); + + /** + * Counts {@link SoftwareModule}s with given {@link SoftwareModuleType}. + * + * @param type + * to count + * @return number of found {@link SoftwareModule}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Long countSoftwareModulesByType(@NotNull SoftwareModuleType type); + + /** + * @return number of {@link SoftwareModuleType}s in the repository. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Long countSoftwareModuleTypesAll(); + + /** + * Create {@link SoftwareModule}s in the repository. + * + * @param swModules + * {@link SoftwareModule}s to create + * @return SoftwareModule + * @throws EntityAlreadyExistsException + * if a given entity already exists + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) + List createSoftwareModule(@NotNull Collection swModules); + + /** + * + * @param swModule + * SoftwareModule to create + * @return SoftwareModule + * @throws EntityAlreadyExistsException + * if a given entity already exists + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) + SoftwareModule createSoftwareModule(@NotNull SoftwareModule swModule); + + /** + * creates a list of software module meta data entries. + * + * @param metadata + * the meta data entries to create or update + * @return the updated or created software module meta data entries + * @throws EntityAlreadyExistsException + * in case one of the meta data entry already exists for the + * specific key + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + List createSoftwareModuleMetadata(@NotNull Collection metadata); + + /** + * creates or updates a single software module meta data entry. + * + * @param metadata + * the meta data entry to create or update + * @return the updated or created software module meta data entry + * @throws EntityAlreadyExistsException + * in case the meta data entry already exists for the specific + * key + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + SoftwareModuleMetadata createSoftwareModuleMetadata(@NotNull SoftwareModuleMetadata metadata); + + /** + * Creates multiple {@link SoftwareModuleType}s. + * + * @param types + * to create + * @return created {@link Entity} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) + List createSoftwareModuleType(@NotNull final Collection types); + + /** + * Creates new {@link SoftwareModuleType}. + * + * @param type + * to create + * @return created {@link Entity} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY) + SoftwareModuleType createSoftwareModuleType(@NotNull SoftwareModuleType type); + + /** + * Deletes the given {@link SoftwareModule} {@link Entity}. + * + * @param bsm + * is the {@link SoftwareModule} to be deleted + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) + void deleteSoftwareModule(@NotNull SoftwareModule bsm); + + /** + * deletes a software module meta data entry. + * + * @param id + * the ID of the software module meta data to delete + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + void deleteSoftwareModuleMetadata(@NotNull SoftwareModule softwareModule, @NotNull String key); + + /** + * Deletes {@link SoftwareModule}s which is any if the given ids. + * + * @param ids + * of the Software Modules to be deleted + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) + void deleteSoftwareModules(@NotNull Collection ids); + + /** + * Deletes or marks as delete in case the type is in use. + * + * @param type + * to delete + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY) + void deleteSoftwareModuleType(@NotNull SoftwareModuleType type); + + /** + * @param pageable + * the page request to page the result set + * @param set + * to search for + * @return all {@link SoftwareModule}s that are assigned to given + * {@link DistributionSet}. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findSoftwareModuleByAssignedTo(@NotNull Pageable pageable, @NotNull DistributionSet set); + + /** + * @param pageable + * the page request to page the result set + * @param set + * to search for + * @param type + * to filter + * @return all {@link SoftwareModule}s that are assigned to given + * {@link DistributionSet} filtered by {@link SoftwareModuleType}. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findSoftwareModuleByAssignedToAndType(@NotNull Pageable pageable, @NotNull DistributionSet set, + @NotNull SoftwareModuleType type); + + /** + * Filter {@link SoftwareModule}s with given + * {@link SoftwareModule#getName()} or {@link SoftwareModule#getVersion()} + * and {@link SoftwareModule#getType()} that are not marked as deleted. + * + * @param pageable + * page parameter + * @param searchText + * to be filtered as "like" on {@link SoftwareModule#getName()} + * @param type + * to be filtered as "like" on {@link SoftwareModule#getType()} + * @return the page of found {@link SoftwareModule} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Slice findSoftwareModuleByFilters(@NotNull Pageable pageable, String searchText, + SoftwareModuleType type); + + /** + * Finds {@link SoftwareModule} by given id. + * + * @param id + * to search for + * @return the found {@link SoftwareModule}s or null if not + * found. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + + SpringEvalExpressions.IS_CONTROLLER) + SoftwareModule findSoftwareModuleById(@NotNull Long id); + + /** + * retrieves {@link SoftwareModule} by their name AND version AND type.. + * + * @param name + * of the {@link SoftwareModule} + * @param version + * of the {@link SoftwareModule} + * @param type + * of the {@link SoftwareModule} + * @return the found {@link SoftwareModule} or null + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + SoftwareModule findSoftwareModuleByNameAndVersion(@NotEmpty String name, @NotEmpty String version, + @NotNull SoftwareModuleType type); + + /** + * finds a single software module meta data by its id. + * + * @param id + * the id of the software module meta data containing the meta + * data key and the ID of the software module + * @return the found SoftwareModuleMetadata or {@code null} if not exits + * @throws EntityNotFoundException + * in case the meta data does not exists for the given key + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + SoftwareModuleMetadata findSoftwareModuleMetadata(@NotNull SoftwareModule softwareModule, @NotEmpty String key); + + /** + * finds all meta data by the given software module id. + * + * @param swId + * the software module id to retrieve the meta data from + * @param pageable + * the page request to page the result + * @return a paged result of all meta data entries for a given software + * module id + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findSoftwareModuleMetadataBySoftwareModuleId(@NotNull Long swId, + @NotNull Pageable pageable); + + /** + * finds all meta data by the given software module id. + * + * @param softwareModuleId + * the software module id to retrieve the meta data from + * @param spec + * the specification to filter the result + * @param pageable + * the page request to page the result + * @return a paged result of all meta data entries for a given software + * module id + * + * @throws RSQLParameterUnsupportedFieldException + * if a field in the RSQL string is used but not provided by the + * given {@code fieldNameProvider} + * @throws RSQLParameterSyntaxException + * if the RSQL syntax is wrong + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findSoftwareModuleMetadataBySoftwareModuleId(@NotNull Long softwareModuleId, + @NotNull String rsqlParam, @NotNull Pageable pageable); + + /** + * Filter {@link SoftwareModule}s with given + * {@link SoftwareModule#getName()} or {@link SoftwareModule#getVersion()} + * search text and {@link SoftwareModule#getType()} that are not marked as + * deleted and sort them by means of given distribution set related modules + * on top of the list. + * + * After that the modules are sorted by {@link SoftwareModule#getName()} and + * {@link SoftwareModule#getVersion()} in ascending order. + * + * @param pageable + * page parameter + * @param orderByDistributionId + * the ID of distribution set to be ordered on top + * @param searchText + * filtered as "like" on {@link SoftwareModule#getName()} + * @param type + * filtered as "equal" on {@link SoftwareModule#getType()} + * @return the page of found {@link SoftwareModule} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Slice findSoftwareModuleOrderBySetAssignmentAndModuleNameAscModuleVersionAsc( + @NotNull Pageable pageable, @NotNull Long orderByDistributionId, String searchText, + SoftwareModuleType type); + + /** + * Retrieves all software modules. Deleted ones are filtered. + * + * @param pageable + * pagination parameter + * @return the found {@link SoftwareModule}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Slice findSoftwareModulesAll(@NotNull Pageable pageable); + + /** + * Retrieves all software modules with a given list of ids + * {@link SoftwareModule#getId()}. + * + * @param ids + * to search for + * @return {@link List} of found {@link SoftwareModule}s + */ + List findSoftwareModulesById(@NotEmpty Collection ids); + + /** + * Retrieves all {@link SoftwareModule}s with a given specification. + * + * @param spec + * the specification to filter the software modules + * @param pageable + * pagination parameter + * @return the found {@link SoftwareModule}s + * + * @throws RSQLParameterUnsupportedFieldException + * if a field in the RSQL string is used but not provided by the + * given {@code fieldNameProvider} + * @throws RSQLParameterSyntaxException + * if the RSQL syntax is wrong + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findSoftwareModulesByPredicate(@NotNull String rsqlParam, @NotNull Pageable pageable); + + /** + * retrieves the {@link SoftwareModule}s by their {@link SoftwareModuleType} + * . + * + * @param pageable + * page parameters + * @param type + * to be filtered on + * @return the found {@link SoftwareModule}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Slice findSoftwareModulesByType(@NotNull Pageable pageable, @NotNull SoftwareModuleType type); + + /** + * + * @param id + * to search for + * @return {@link SoftwareModuleType} in the repository with given + * {@link SoftwareModuleType#getId()} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + SoftwareModuleType findSoftwareModuleTypeById(@NotNull Long id); + + /** + * + * @param key + * to search for + * @return {@link SoftwareModuleType} in the repository with given + * {@link SoftwareModuleType#getKey()} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + SoftwareModuleType findSoftwareModuleTypeByKey(@NotNull String key); + + /** + * + * @param name + * to search for + * @return all {@link SoftwareModuleType}s in the repository with given + * {@link SoftwareModuleType#getName()} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + SoftwareModuleType findSoftwareModuleTypeByName(@NotNull String name); + + /** + * @param pageable + * parameter + * @return all {@link SoftwareModuleType}s in the repository. + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findSoftwareModuleTypesAll(@NotNull Pageable pageable); + + /** + * Retrieves all {@link SoftwareModuleType}s with a given specification. + * + * @param spec + * the specification to filter the software modules types + * @param pageable + * pagination parameter + * @return the found {@link SoftwareModuleType}s + * + * @throws RSQLParameterUnsupportedFieldException + * if a field in the RSQL string is used but not provided by the + * given {@code fieldNameProvider} + * @throws RSQLParameterSyntaxException + * if the RSQL syntax is wrong + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + Page findSoftwareModuleTypesAll(@NotNull String rsqlParam, @NotNull Pageable pageable); + + /** + * Retrieves software module including details ( + * {@link SoftwareModule#getArtifacts()}). + * + * @param id + * parameter + * @param isDeleted + * parameter + * @return the found {@link SoftwareModule}s + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + SoftwareModule findSoftwareModuleWithDetails(@NotNull Long id); + + /** + * Updates existing {@link SoftwareModule}. Update-able values are + * {@link SoftwareModule#getDescription()} + * {@link SoftwareModule#getVendor()}. + * + * @param sm + * to update + * + * @return the saved {@link Entity}. + * + * @throws NullPointerException + * of {@link SoftwareModule#getId()} is null + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + SoftwareModule updateSoftwareModule(@NotNull SoftwareModule sm); + + /** + * updates a distribution set meta data value if corresponding entry exists. + * + * @param metadata + * the meta data entry to be updated + * @return the updated meta data entry + * @throws EntityNotFoundException + * in case the meta data entry does not exists and cannot be + * updated + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + SoftwareModuleMetadata updateSoftwareModuleMetadata(@NotNull SoftwareModuleMetadata metadata); + + /** + * Updates existing {@link SoftwareModuleType}. Update-able value is + * {@link SoftwareModuleType#getDescription()} and + * {@link SoftwareModuleType#getColour()}. + * + * @param sm + * to update + * @return updated {@link Entity} + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) + SoftwareModuleType updateSoftwareModuleType(@NotNull SoftwareModuleType sm); + + /** + * finds all meta data by the given software module id. + * + * @param softwareModuleId + * the software module id to retrieve the meta data from + + * + * @throws RSQLParameterUnsupportedFieldException + * if a field in the RSQL string is used but not provided by the + * given {@code fieldNameProvider} + * @throws RSQLParameterSyntaxException + * if the RSQL syntax is wrong + * @return result of all meta data entries for a given software + * module id + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + List findSoftwareModuleMetadataBySoftwareModuleId(Long softwareModuleId); + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java index b94677fb9..306b9bd80 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java @@ -173,39 +173,36 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Override @Modifying @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public void deleteDistributionSet(final Long... distributionSetIDs) { - final List toHardDelete = new ArrayList<>(); + public void deleteDistributionSet(final Long... distributionSetIDs) { + final List toHardDelete = new ArrayList<>(); - final List assigned = distributionSetRepository - .findAssignedToTargetDistributionSetsById(distributionSetIDs); - assigned.addAll(distributionSetRepository - .findAssignedToRolloutDistributionSetsById(distributionSetIDs)); + final List assigned = distributionSetRepository + .findAssignedToTargetDistributionSetsById(distributionSetIDs); + assigned.addAll(distributionSetRepository.findAssignedToRolloutDistributionSetsById(distributionSetIDs)); - // soft delete assigned - if (!assigned.isEmpty()) { - distributionSetRepository.deleteDistributionSet(assigned - .toArray(new Long[assigned.size()])); - } + // soft delete assigned + if (!assigned.isEmpty()) { + distributionSetRepository.deleteDistributionSet(assigned.toArray(new Long[assigned.size()])); + } - // mark the rest as hard delete - for (final Long setId : distributionSetIDs) { - if (!assigned.contains(setId)) { - toHardDelete.add(setId); - } - } + // mark the rest as hard delete + for (final Long setId : distributionSetIDs) { + if (!assigned.contains(setId)) { + toHardDelete.add(setId); + } + } - // hard delete the rest if exixts - if (!toHardDelete.isEmpty()) { - // don't give the delete statement an empty list, JPA/Oracle cannot - // handle the empty list - distributionSetRepository.deleteByIdIn(toHardDelete); - } + // hard delete the rest if exixts + if (!toHardDelete.isEmpty()) { + // don't give the delete statement an empty list, JPA/Oracle cannot + // handle the empty list + distributionSetRepository.deleteByIdIn(toHardDelete); + } - afterCommit.afterCommit(() -> eventBus - .post(new DistributionDeletedEvent(tenantAware - .getCurrentTenant(), distributionSetIDs))); + afterCommit.afterCommit( + () -> eventBus.post(new DistributionDeletedEvent(tenantAware.getCurrentTenant(), distributionSetIDs))); - } + } @Override @Modifying @@ -530,6 +527,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Transactional(isolation = Isolation.READ_UNCOMMITTED) @Modifying public void deleteDistributionSetMetadata(final DistributionSet distributionSet, final String key) { + entityManager.merge((JpaDistributionSet) distributionSet).setLastModifiedAt(0L); distributionSetMetadataRepository.delete(new DsMetadataCompositeKey(distributionSet, key)); } @@ -544,6 +542,15 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { pageable); } + @Override + public List findDistributionSetMetadataByDistributionSetId(final Long distributionSetId) { + + return new ArrayList(distributionSetMetadataRepository + .findAll((Specification) (root, query, cb) -> cb.equal( + root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id), + distributionSetId))); + } + @Override public Page findDistributionSetMetadataByDistributionSetId(final Long distributionSetId, final String rsqlParam, final Pageable pageable) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java index b561667a9..afe1a1e02 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java @@ -1,663 +1,672 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH 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 - */ -package org.eclipse.hawkbit.repository.jpa; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import javax.persistence.EntityManager; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.ListJoin; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; - -import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; -import org.eclipse.hawkbit.repository.ArtifactManagement; -import org.eclipse.hawkbit.repository.SoftwareManagement; -import org.eclipse.hawkbit.repository.SoftwareModuleFields; -import org.eclipse.hawkbit.repository.SoftwareModuleMetadataFields; -import org.eclipse.hawkbit.repository.SoftwareModuleTypeFields; -import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; -import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; -import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; -import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_; -import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; -import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata; -import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata_; -import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType; -import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule_; -import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey; -import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; -import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification; -import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; -import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.LocalArtifact; -import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; -import org.eclipse.hawkbit.repository.model.SoftwareModuleType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.AuditorAware; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.domain.SliceImpl; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.transaction.annotation.Isolation; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; - -import com.google.common.base.Strings; -import com.google.common.collect.Sets; - -/** - * JPA implementation of {@link SoftwareManagement}. - * - */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) -@Validated -public class JpaSoftwareManagement implements SoftwareManagement { - - @Autowired - private EntityManager entityManager; - - @Autowired - private DistributionSetRepository distributionSetRepository; - - @Autowired - private DistributionSetTypeRepository distributionSetTypeRepository; - - @Autowired - private SoftwareModuleRepository softwareModuleRepository; - - @Autowired - private SoftwareModuleMetadataRepository softwareModuleMetadataRepository; - - @Autowired - private SoftwareModuleTypeRepository softwareModuleTypeRepository; - - @Autowired - private NoCountPagingRepository criteriaNoCountDao; - - @Autowired - private AuditorAware auditorProvider; - - @Autowired - private ArtifactManagement artifactManagement; - - @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public SoftwareModule updateSoftwareModule(final SoftwareModule sm) { - checkNotNull(sm.getId()); - - final JpaSoftwareModule module = softwareModuleRepository.findOne(sm.getId()); - - boolean updated = false; - if (null == sm.getDescription() || !sm.getDescription().equals(module.getDescription())) { - module.setDescription(sm.getDescription()); - updated = true; - } - if (null == sm.getVendor() || !sm.getVendor().equals(module.getVendor())) { - module.setVendor(sm.getVendor()); - updated = true; - } - - return updated ? softwareModuleRepository.save(module) : module; - } - - @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public SoftwareModuleType updateSoftwareModuleType(final SoftwareModuleType sm) { - checkNotNull(sm.getId()); - - final JpaSoftwareModuleType type = softwareModuleTypeRepository.findOne(sm.getId()); - - boolean updated = false; - if (sm.getDescription() == null || !sm.getDescription().equals(type.getDescription())) { - type.setDescription(sm.getDescription()); - updated = true; - } - if (sm.getColour() != null && !sm.getColour().equals(type.getColour())) { - type.setColour(sm.getColour()); - updated = true; - } - return updated ? softwareModuleTypeRepository.save(type) : type; - } - - @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public SoftwareModule createSoftwareModule(final SoftwareModule swModule) { - if (null != swModule.getId()) { - throw new EntityAlreadyExistsException(); - } - return softwareModuleRepository.save((JpaSoftwareModule) swModule); - } - - @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public List createSoftwareModule(final Collection swModules) { - swModules.forEach(swModule -> { - if (null != swModule.getId()) { - throw new EntityAlreadyExistsException(); - } - }); - - @SuppressWarnings({ "unchecked", "rawtypes" }) - final Collection jpaCast = (Collection) swModules; - - return new ArrayList<>(softwareModuleRepository.save(jpaCast)); - } - - @Override - public Slice findSoftwareModulesByType(final Pageable pageable, final SoftwareModuleType type) { - - final List> specList = new LinkedList<>(); - - Specification spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type); - specList.add(spec); - - spec = SoftwareModuleSpecification.isDeletedFalse(); - specList.add(spec); - - return convertSmPage(findSwModuleByCriteriaAPI(pageable, specList), pageable); - } - - private static Slice convertSmPage(final Slice findAll, - final Pageable pageable) { - return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, 0); - } - - private static Page convertSmPage(final Page findAll, final Pageable pageable) { - return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - private static Page convertSmMdPage(final Page findAll, - final Pageable pageable) { - return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - @Override - public Long countSoftwareModulesByType(final SoftwareModuleType type) { - - final List> specList = new ArrayList<>(); - - Specification spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type); - specList.add(spec); - - spec = SoftwareModuleSpecification.isDeletedFalse(); - specList.add(spec); - - return countSwModuleByCriteriaAPI(specList); - } - - @Override - public SoftwareModule findSoftwareModuleById(final Long id) { - return artifactManagement.findSoftwareModuleById(id); - } - - @Override - public SoftwareModule findSoftwareModuleByNameAndVersion(final String name, final String version, - final SoftwareModuleType type) { - - return softwareModuleRepository.findOneByNameAndVersionAndType(name, version, (JpaSoftwareModuleType) type); - } - - private boolean isUnassigned(final JpaSoftwareModule bsmMerged) { - return distributionSetRepository.findByModules(bsmMerged).isEmpty(); - } - - private Slice findSwModuleByCriteriaAPI(final Pageable pageable, - final List> specList) { - return criteriaNoCountDao.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable, - JpaSoftwareModule.class); - } - - private Long countSwModuleByCriteriaAPI(final List> specList) { - return softwareModuleRepository.count(SpecificationsBuilder.combineWithAnd(specList)); - } - - private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) { - for (final LocalArtifact localArtifact : swModule.getLocalArtifacts()) { - artifactManagement.deleteLocalArtifact(localArtifact); - } - } - - @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public void deleteSoftwareModules(final Collection ids) { - final List swModulesToDelete = softwareModuleRepository.findByIdIn(ids); - final Set assignedModuleIds = new HashSet<>(); - swModulesToDelete.forEach(swModule -> { - - // delete binary data of artifacts - deleteGridFsArtifacts(swModule); - - if (isUnassigned(swModule)) { - - softwareModuleRepository.delete(swModule); - - } else { - - assignedModuleIds.add(swModule.getId()); - } - }); - - if (!assignedModuleIds.isEmpty()) { - String currentUser = null; - if (auditorProvider != null) { - currentUser = auditorProvider.getCurrentAuditor(); - } - softwareModuleRepository.deleteSoftwareModule(System.currentTimeMillis(), currentUser, - assignedModuleIds.toArray(new Long[0])); - } - } - - @Override - public Slice findSoftwareModulesAll(final Pageable pageable) { - - final List> specList = new ArrayList<>(); - - Specification spec = SoftwareModuleSpecification.isDeletedFalse(); - specList.add(spec); - - spec = (root, query, cb) -> { - if (!query.getResultType().isAssignableFrom(Long.class)) { - root.fetch(JpaSoftwareModule_.type); - } - return cb.conjunction(); - }; - - specList.add(spec); - - return convertSmPage(findSwModuleByCriteriaAPI(pageable, specList), pageable); - } - - @Override - public Long countSoftwareModulesAll() { - - final List> specList = new ArrayList<>(); - - final Specification spec = SoftwareModuleSpecification.isDeletedFalse(); - specList.add(spec); - - return countSwModuleByCriteriaAPI(specList); - } - - @Override - public SoftwareModule findSoftwareModuleWithDetails(final Long id) { - return artifactManagement.findSoftwareModuleWithDetails(id); - } - - @Override - public Page findSoftwareModulesByPredicate(final String rsqlParam, final Pageable pageable) { - final Specification spec = RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class); - - return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable); - } - - @Override - public Page findSoftwareModuleTypesAll(final String rsqlParam, final Pageable pageable) { - - final Specification spec = RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class); - - return convertSmTPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable); - } - - private static Page convertSmTPage(final Page findAll, - final Pageable pageable) { - return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements()); - } - - @Override - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) - public List findSoftwareModulesById(final Collection ids) { - return new ArrayList<>(softwareModuleRepository.findByIdIn(ids)); - } - - @Override - public Slice findSoftwareModuleByFilters(final Pageable pageable, final String searchText, - final SoftwareModuleType type) { - - final List> specList = new ArrayList<>(); - - Specification spec = SoftwareModuleSpecification.isDeletedFalse(); - specList.add(spec); - - if (!Strings.isNullOrEmpty(searchText)) { - spec = SoftwareModuleSpecification.likeNameOrVersion(searchText); - specList.add(spec); - } - - if (null != type) { - spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type); - specList.add(spec); - } - - spec = (root, query, cb) -> { - if (!query.getResultType().isAssignableFrom(Long.class)) { - root.fetch(JpaSoftwareModule_.type); - } - return cb.conjunction(); - }; - - specList.add(spec); - - return convertSmPage(findSwModuleByCriteriaAPI(pageable, specList), pageable); - } - - @Override - public Slice findSoftwareModuleOrderBySetAssignmentAndModuleNameAscModuleVersionAsc( - final Pageable pageable, final Long orderByDistributionId, final String searchText, - final SoftwareModuleType ty) { - final JpaSoftwareModuleType type = (JpaSoftwareModuleType) ty; - - final List resultList = new ArrayList<>(); - final int pageSize = pageable.getPageSize(); - final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); - - // get the assigned software modules - final CriteriaQuery assignedQuery = cb.createQuery(JpaSoftwareModule.class); - final Root assignedRoot = assignedQuery.from(JpaSoftwareModule.class); - assignedQuery.distinct(true); - final ListJoin assignedDsJoin = assignedRoot - .join(JpaSoftwareModule_.assignedTo); - // build the specifications and then to predicates necessary by the - // given filters - final Predicate[] specPredicate = specificationsToPredicate(buildSpecificationList(searchText, type), - assignedRoot, assignedQuery, cb, - cb.equal(assignedDsJoin.get(JpaDistributionSet_.id), orderByDistributionId)); - // if we have some predicates then add it to the where clause of the - // multi select - assignedQuery.where(specPredicate); - assignedQuery.orderBy(cb.asc(assignedRoot.get(JpaSoftwareModule_.name)), - cb.asc(assignedRoot.get(JpaSoftwareModule_.version))); - // don't page the assigned query on database, we need all assigned - // software modules to filter - // them out in the unassigned query - final List assignedSoftwareModules = entityManager.createQuery(assignedQuery) - .getResultList(); - // map result - if (pageable.getOffset() < assignedSoftwareModules.size()) { - assignedSoftwareModules - .subList(pageable.getOffset(), Math.min(assignedSoftwareModules.size(), pageable.getPageSize())) - .forEach(sw -> resultList.add(new AssignedSoftwareModule(sw, true))); - } - - if (assignedSoftwareModules.size() >= pageSize) { - return new SliceImpl<>(resultList); - } - - // get the unassigned software modules - final CriteriaQuery unassignedQuery = cb.createQuery(JpaSoftwareModule.class); - unassignedQuery.distinct(true); - final Root unassignedRoot = unassignedQuery.from(JpaSoftwareModule.class); - - Predicate[] unassignedSpec; - if (!assignedSoftwareModules.isEmpty()) { - unassignedSpec = specificationsToPredicate(buildSpecificationList(searchText, type), unassignedRoot, - unassignedQuery, cb, cb.not(unassignedRoot.get(JpaSoftwareModule_.id) - .in(assignedSoftwareModules.stream().map(sw -> sw.getId()).collect(Collectors.toList())))); - } else { - unassignedSpec = specificationsToPredicate(buildSpecificationList(searchText, type), unassignedRoot, - unassignedQuery, cb); - } - - unassignedQuery.where(unassignedSpec); - unassignedQuery.orderBy(cb.asc(unassignedRoot.get(JpaSoftwareModule_.name)), - cb.asc(unassignedRoot.get(JpaSoftwareModule_.version))); - final List unassignedSoftwareModules = entityManager.createQuery(unassignedQuery) - .setFirstResult(Math.max(0, pageable.getOffset() - assignedSoftwareModules.size())) - .setMaxResults(pageSize).getResultList(); - // map result - unassignedSoftwareModules.forEach(sw -> resultList.add(new AssignedSoftwareModule(sw, false))); - - return new SliceImpl<>(resultList); - } - - private static List> buildSpecificationList(final String searchText, - final JpaSoftwareModuleType type) { - final List> specList = new ArrayList<>(); - if (!Strings.isNullOrEmpty(searchText)) { - specList.add(SoftwareModuleSpecification.likeNameOrVersion(searchText)); - } - if (type != null) { - specList.add(SoftwareModuleSpecification.equalType(type)); - } - specList.add(SoftwareModuleSpecification.isDeletedFalse()); - return specList; - } - - private Predicate[] specificationsToPredicate(final List> specifications, - final Root root, final CriteriaQuery query, final CriteriaBuilder cb, - final Predicate... additionalPredicates) { - final List predicates = new ArrayList<>(); - specifications.forEach(spec -> predicates.add(spec.toPredicate(root, query, cb))); - for (final Predicate predicate : additionalPredicates) { - predicates.add(predicate); - } - return predicates.toArray(new Predicate[predicates.size()]); - } - - @Override - public Long countSoftwareModuleByFilters(final String searchText, final SoftwareModuleType type) { - - final List> specList = new ArrayList<>(); - - Specification spec = SoftwareModuleSpecification.isDeletedFalse(); - specList.add(spec); - - if (!Strings.isNullOrEmpty(searchText)) { - spec = SoftwareModuleSpecification.likeNameOrVersion(searchText); - specList.add(spec); - } - - if (null != type) { - spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type); - specList.add(spec); - } - - return countSwModuleByCriteriaAPI(specList); - } - - @Override - public Page findSoftwareModuleTypesAll(final Pageable pageable) { - return softwareModuleTypeRepository.findByDeleted(pageable, false); - } - - @Override - public Long countSoftwareModuleTypesAll() { - return softwareModuleTypeRepository.countByDeleted(false); - } - - @Override - public SoftwareModuleType findSoftwareModuleTypeByKey(final String key) { - return softwareModuleTypeRepository.findByKey(key); - } - - @Override - public SoftwareModuleType findSoftwareModuleTypeById(final Long id) { - return softwareModuleTypeRepository.findOne(id); - } - - @Override - public SoftwareModuleType findSoftwareModuleTypeByName(final String name) { - return softwareModuleTypeRepository.findByName(name); - } - - @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public SoftwareModuleType createSoftwareModuleType(final SoftwareModuleType type) { - if (type.getId() != null) { - throw new EntityAlreadyExistsException("Given type contains an Id!"); - } - - return softwareModuleTypeRepository.save((JpaSoftwareModuleType) type); - } - - @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public void deleteSoftwareModuleType(final SoftwareModuleType ty) { - final JpaSoftwareModuleType type = (JpaSoftwareModuleType) ty; - - if (softwareModuleRepository.countByType(type) > 0 - || distributionSetTypeRepository.countByElementsSmType(type) > 0) { - final JpaSoftwareModuleType toDelete = entityManager.merge(type); - toDelete.setDeleted(true); - softwareModuleTypeRepository.save(toDelete); - } else { - softwareModuleTypeRepository.delete(type.getId()); - } - } - - @Override - public Page findSoftwareModuleByAssignedTo(final Pageable pageable, final DistributionSet set) { - return softwareModuleRepository.findByAssignedTo(pageable, (JpaDistributionSet) set); - } - - @Override - public Page findSoftwareModuleByAssignedToAndType(final Pageable pageable, - final DistributionSet set, final SoftwareModuleType type) { - return softwareModuleRepository.findByAssignedToAndType(pageable, (JpaDistributionSet) set, - (JpaSoftwareModuleType) type); - } - - @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying - public SoftwareModuleMetadata createSoftwareModuleMetadata(final SoftwareModuleMetadata md) { - final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) md; - - if (softwareModuleMetadataRepository.exists(metadata.getId())) { - throwMetadataKeyAlreadyExists(metadata.getId().getKey()); - } - // merge base software module so optLockRevision gets updated and audit - // log written because - // modifying metadata is modifying the base software module itself for - // auditing purposes. - entityManager.merge((JpaSoftwareModule) metadata.getSoftwareModule()).setLastModifiedAt(-1L); - return softwareModuleMetadataRepository.save(metadata); - } - - @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying - public List createSoftwareModuleMetadata(final Collection md) { - @SuppressWarnings({ "unchecked", "rawtypes" }) - final Collection metadata = (Collection) md; - - for (final JpaSoftwareModuleMetadata softwareModuleMetadata : metadata) { - checkAndThrowAlreadyExistsIfSoftwareModuleMetadataExists(softwareModuleMetadata.getId()); - } - metadata.forEach(m -> entityManager.merge((JpaSoftwareModule) m.getSoftwareModule()).setLastModifiedAt(-1L)); - return new ArrayList<>(softwareModuleMetadataRepository.save(metadata)); - } - - @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying - public SoftwareModuleMetadata updateSoftwareModuleMetadata(final SoftwareModuleMetadata md) { - final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) md; - - // check if exists otherwise throw entity not found exception - findSoftwareModuleMetadata(metadata.getId()); - // touch it to update the lock revision because we are modifying the - // software module - // indirectly - entityManager.merge((JpaSoftwareModule) metadata.getSoftwareModule()).setLastModifiedAt(-1L); - return softwareModuleMetadataRepository.save(metadata); - } - - @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying - public void deleteSoftwareModuleMetadata(final SoftwareModule softwareModule, final String key) { - softwareModuleMetadataRepository.delete(new SwMetadataCompositeKey(softwareModule, key)); - } - - @Override - public Page findSoftwareModuleMetadataBySoftwareModuleId(final Long swId, - final Pageable pageable) { - return softwareModuleMetadataRepository.findBySoftwareModuleId(swId, pageable); - } - - @Override - public Page findSoftwareModuleMetadataBySoftwareModuleId(final Long softwareModuleId, - final String rsqlParam, final Pageable pageable) { - - final Specification spec = RSQLUtility.parse(rsqlParam, - SoftwareModuleMetadataFields.class); - return convertSmMdPage( - softwareModuleMetadataRepository - .findAll( - (Specification) (root, query, cb) -> cb.and( - cb.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule) - .get(JpaSoftwareModule_.id), softwareModuleId), - spec.toPredicate(root, query, cb)), - pageable), - pageable); - } - - @Override - public SoftwareModuleMetadata findSoftwareModuleMetadata(final SoftwareModule softwareModule, final String key) { - return findSoftwareModuleMetadata(new SwMetadataCompositeKey(softwareModule, key)); - } - - private SoftwareModuleMetadata findSoftwareModuleMetadata(final SwMetadataCompositeKey id) { - final SoftwareModuleMetadata findOne = softwareModuleMetadataRepository.findOne(id); - if (findOne == null) { - throw new EntityNotFoundException("Metadata with key '" + id.getKey() + "' does not exist"); - } - return findOne; - } - - private void checkAndThrowAlreadyExistsIfSoftwareModuleMetadataExists(final SwMetadataCompositeKey metadataId) { - if (softwareModuleMetadataRepository.exists(metadataId)) { - throw new EntityAlreadyExistsException( - "Metadata entry with key '" + metadataId.getKey() + "' already exists"); - } - } - - private static void throwMetadataKeyAlreadyExists(final String metadataKey) { - throw new EntityAlreadyExistsException("Metadata entry with key '" + metadataKey + "' already exists"); - } - - @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public void deleteSoftwareModule(final SoftwareModule bsm) { - deleteSoftwareModules(Sets.newHashSet(bsm.getId())); - } - - @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public List createSoftwareModuleType(final Collection types) { - - return types.stream().map(this::createSoftwareModuleType).collect(Collectors.toList()); - } - -} +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH 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 + */ +package org.eclipse.hawkbit.repository.jpa; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.persistence.EntityManager; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.ListJoin; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; +import org.eclipse.hawkbit.repository.ArtifactManagement; +import org.eclipse.hawkbit.repository.SoftwareManagement; +import org.eclipse.hawkbit.repository.SoftwareModuleFields; +import org.eclipse.hawkbit.repository.SoftwareModuleMetadataFields; +import org.eclipse.hawkbit.repository.SoftwareModuleTypeFields; +import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; +import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; +import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; +import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_; +import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; +import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata; +import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata_; +import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType; +import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule_; +import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey; +import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; +import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification; +import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder; +import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.LocalArtifact; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; +import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.AuditorAware; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.SliceImpl; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import com.google.common.base.Strings; +import com.google.common.collect.Sets; + +/** + * JPA implementation of {@link SoftwareManagement}. + * + */ +@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Validated +public class JpaSoftwareManagement implements SoftwareManagement { + + @Autowired + private EntityManager entityManager; + + @Autowired + private DistributionSetRepository distributionSetRepository; + + @Autowired + private DistributionSetTypeRepository distributionSetTypeRepository; + + @Autowired + private SoftwareModuleRepository softwareModuleRepository; + + @Autowired + private SoftwareModuleMetadataRepository softwareModuleMetadataRepository; + + @Autowired + private SoftwareModuleTypeRepository softwareModuleTypeRepository; + + @Autowired + private NoCountPagingRepository criteriaNoCountDao; + + @Autowired + private AuditorAware auditorProvider; + + @Autowired + private ArtifactManagement artifactManagement; + + @Override + @Modifying + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + public SoftwareModule updateSoftwareModule(final SoftwareModule sm) { + checkNotNull(sm.getId()); + + final JpaSoftwareModule module = softwareModuleRepository.findOne(sm.getId()); + + boolean updated = false; + if (null == sm.getDescription() || !sm.getDescription().equals(module.getDescription())) { + module.setDescription(sm.getDescription()); + updated = true; + } + if (null == sm.getVendor() || !sm.getVendor().equals(module.getVendor())) { + module.setVendor(sm.getVendor()); + updated = true; + } + + return updated ? softwareModuleRepository.save(module) : module; + } + + @Override + @Modifying + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + public SoftwareModuleType updateSoftwareModuleType(final SoftwareModuleType sm) { + checkNotNull(sm.getId()); + + final JpaSoftwareModuleType type = softwareModuleTypeRepository.findOne(sm.getId()); + + boolean updated = false; + if (sm.getDescription() == null || !sm.getDescription().equals(type.getDescription())) { + type.setDescription(sm.getDescription()); + updated = true; + } + if (sm.getColour() != null && !sm.getColour().equals(type.getColour())) { + type.setColour(sm.getColour()); + updated = true; + } + return updated ? softwareModuleTypeRepository.save(type) : type; + } + + @Override + @Modifying + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + public SoftwareModule createSoftwareModule(final SoftwareModule swModule) { + if (null != swModule.getId()) { + throw new EntityAlreadyExistsException(); + } + return softwareModuleRepository.save((JpaSoftwareModule) swModule); + } + + @Override + @Modifying + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + public List createSoftwareModule(final Collection swModules) { + swModules.forEach(swModule -> { + if (null != swModule.getId()) { + throw new EntityAlreadyExistsException(); + } + }); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + final Collection jpaCast = (Collection) swModules; + + return new ArrayList<>(softwareModuleRepository.save(jpaCast)); + } + + @Override + public Slice findSoftwareModulesByType(final Pageable pageable, final SoftwareModuleType type) { + + final List> specList = new LinkedList<>(); + + Specification spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type); + specList.add(spec); + + spec = SoftwareModuleSpecification.isDeletedFalse(); + specList.add(spec); + + return convertSmPage(findSwModuleByCriteriaAPI(pageable, specList), pageable); + } + + private static Slice convertSmPage(final Slice findAll, + final Pageable pageable) { + return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, 0); + } + + private static Page convertSmPage(final Page findAll, final Pageable pageable) { + return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements()); + } + + private static Page convertSmMdPage(final Page findAll, + final Pageable pageable) { + return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements()); + } + + @Override + public Long countSoftwareModulesByType(final SoftwareModuleType type) { + + final List> specList = new ArrayList<>(); + + Specification spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type); + specList.add(spec); + + spec = SoftwareModuleSpecification.isDeletedFalse(); + specList.add(spec); + + return countSwModuleByCriteriaAPI(specList); + } + + @Override + public SoftwareModule findSoftwareModuleById(final Long id) { + return artifactManagement.findSoftwareModuleById(id); + } + + @Override + public SoftwareModule findSoftwareModuleByNameAndVersion(final String name, final String version, + final SoftwareModuleType type) { + + return softwareModuleRepository.findOneByNameAndVersionAndType(name, version, (JpaSoftwareModuleType) type); + } + + private boolean isUnassigned(final JpaSoftwareModule bsmMerged) { + return distributionSetRepository.findByModules(bsmMerged).isEmpty(); + } + + private Slice findSwModuleByCriteriaAPI(final Pageable pageable, + final List> specList) { + return criteriaNoCountDao.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable, + JpaSoftwareModule.class); + } + + private Long countSwModuleByCriteriaAPI(final List> specList) { + return softwareModuleRepository.count(SpecificationsBuilder.combineWithAnd(specList)); + } + + private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) { + for (final LocalArtifact localArtifact : swModule.getLocalArtifacts()) { + artifactManagement.deleteLocalArtifact(localArtifact); + } + } + + @Override + @Modifying + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + public void deleteSoftwareModules(final Collection ids) { + final List swModulesToDelete = softwareModuleRepository.findByIdIn(ids); + final Set assignedModuleIds = new HashSet<>(); + swModulesToDelete.forEach(swModule -> { + + // delete binary data of artifacts + deleteGridFsArtifacts(swModule); + + if (isUnassigned(swModule)) { + + softwareModuleRepository.delete(swModule); + + } else { + + assignedModuleIds.add(swModule.getId()); + } + }); + + if (!assignedModuleIds.isEmpty()) { + String currentUser = null; + if (auditorProvider != null) { + currentUser = auditorProvider.getCurrentAuditor(); + } + softwareModuleRepository.deleteSoftwareModule(System.currentTimeMillis(), currentUser, + assignedModuleIds.toArray(new Long[0])); + } + } + + @Override + public Slice findSoftwareModulesAll(final Pageable pageable) { + + final List> specList = new ArrayList<>(); + + Specification spec = SoftwareModuleSpecification.isDeletedFalse(); + specList.add(spec); + + spec = (root, query, cb) -> { + if (!query.getResultType().isAssignableFrom(Long.class)) { + root.fetch(JpaSoftwareModule_.type); + } + return cb.conjunction(); + }; + + specList.add(spec); + + return convertSmPage(findSwModuleByCriteriaAPI(pageable, specList), pageable); + } + + @Override + public Long countSoftwareModulesAll() { + + final List> specList = new ArrayList<>(); + + final Specification spec = SoftwareModuleSpecification.isDeletedFalse(); + specList.add(spec); + + return countSwModuleByCriteriaAPI(specList); + } + + @Override + public SoftwareModule findSoftwareModuleWithDetails(final Long id) { + return artifactManagement.findSoftwareModuleWithDetails(id); + } + + @Override + public Page findSoftwareModulesByPredicate(final String rsqlParam, final Pageable pageable) { + final Specification spec = RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class); + + return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable); + } + + @Override + public Page findSoftwareModuleTypesAll(final String rsqlParam, final Pageable pageable) { + + final Specification spec = RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class); + + return convertSmTPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable); + } + + private static Page convertSmTPage(final Page findAll, + final Pageable pageable) { + return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements()); + } + + @Override + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) + public List findSoftwareModulesById(final Collection ids) { + return new ArrayList<>(softwareModuleRepository.findByIdIn(ids)); + } + + @Override + public Slice findSoftwareModuleByFilters(final Pageable pageable, final String searchText, + final SoftwareModuleType type) { + + final List> specList = new ArrayList<>(); + + Specification spec = SoftwareModuleSpecification.isDeletedFalse(); + specList.add(spec); + + if (!Strings.isNullOrEmpty(searchText)) { + spec = SoftwareModuleSpecification.likeNameOrVersion(searchText); + specList.add(spec); + } + + if (null != type) { + spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type); + specList.add(spec); + } + + spec = (root, query, cb) -> { + if (!query.getResultType().isAssignableFrom(Long.class)) { + root.fetch(JpaSoftwareModule_.type); + } + return cb.conjunction(); + }; + + specList.add(spec); + + return convertSmPage(findSwModuleByCriteriaAPI(pageable, specList), pageable); + } + + @Override + public Slice findSoftwareModuleOrderBySetAssignmentAndModuleNameAscModuleVersionAsc( + final Pageable pageable, final Long orderByDistributionId, final String searchText, + final SoftwareModuleType ty) { + final JpaSoftwareModuleType type = (JpaSoftwareModuleType) ty; + + final List resultList = new ArrayList<>(); + final int pageSize = pageable.getPageSize(); + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + // get the assigned software modules + final CriteriaQuery assignedQuery = cb.createQuery(JpaSoftwareModule.class); + final Root assignedRoot = assignedQuery.from(JpaSoftwareModule.class); + assignedQuery.distinct(true); + final ListJoin assignedDsJoin = assignedRoot + .join(JpaSoftwareModule_.assignedTo); + // build the specifications and then to predicates necessary by the + // given filters + final Predicate[] specPredicate = specificationsToPredicate(buildSpecificationList(searchText, type), + assignedRoot, assignedQuery, cb, + cb.equal(assignedDsJoin.get(JpaDistributionSet_.id), orderByDistributionId)); + // if we have some predicates then add it to the where clause of the + // multi select + assignedQuery.where(specPredicate); + assignedQuery.orderBy(cb.asc(assignedRoot.get(JpaSoftwareModule_.name)), + cb.asc(assignedRoot.get(JpaSoftwareModule_.version))); + // don't page the assigned query on database, we need all assigned + // software modules to filter + // them out in the unassigned query + final List assignedSoftwareModules = entityManager.createQuery(assignedQuery) + .getResultList(); + // map result + if (pageable.getOffset() < assignedSoftwareModules.size()) { + assignedSoftwareModules + .subList(pageable.getOffset(), Math.min(assignedSoftwareModules.size(), pageable.getPageSize())) + .forEach(sw -> resultList.add(new AssignedSoftwareModule(sw, true))); + } + + if (assignedSoftwareModules.size() >= pageSize) { + return new SliceImpl<>(resultList); + } + + // get the unassigned software modules + final CriteriaQuery unassignedQuery = cb.createQuery(JpaSoftwareModule.class); + unassignedQuery.distinct(true); + final Root unassignedRoot = unassignedQuery.from(JpaSoftwareModule.class); + + Predicate[] unassignedSpec; + if (!assignedSoftwareModules.isEmpty()) { + unassignedSpec = specificationsToPredicate(buildSpecificationList(searchText, type), unassignedRoot, + unassignedQuery, cb, cb.not(unassignedRoot.get(JpaSoftwareModule_.id) + .in(assignedSoftwareModules.stream().map(sw -> sw.getId()).collect(Collectors.toList())))); + } else { + unassignedSpec = specificationsToPredicate(buildSpecificationList(searchText, type), unassignedRoot, + unassignedQuery, cb); + } + + unassignedQuery.where(unassignedSpec); + unassignedQuery.orderBy(cb.asc(unassignedRoot.get(JpaSoftwareModule_.name)), + cb.asc(unassignedRoot.get(JpaSoftwareModule_.version))); + final List unassignedSoftwareModules = entityManager.createQuery(unassignedQuery) + .setFirstResult(Math.max(0, pageable.getOffset() - assignedSoftwareModules.size())) + .setMaxResults(pageSize).getResultList(); + // map result + unassignedSoftwareModules.forEach(sw -> resultList.add(new AssignedSoftwareModule(sw, false))); + + return new SliceImpl<>(resultList); + } + + private static List> buildSpecificationList(final String searchText, + final JpaSoftwareModuleType type) { + final List> specList = new ArrayList<>(); + if (!Strings.isNullOrEmpty(searchText)) { + specList.add(SoftwareModuleSpecification.likeNameOrVersion(searchText)); + } + if (type != null) { + specList.add(SoftwareModuleSpecification.equalType(type)); + } + specList.add(SoftwareModuleSpecification.isDeletedFalse()); + return specList; + } + + private Predicate[] specificationsToPredicate(final List> specifications, + final Root root, final CriteriaQuery query, final CriteriaBuilder cb, + final Predicate... additionalPredicates) { + final List predicates = new ArrayList<>(); + specifications.forEach(spec -> predicates.add(spec.toPredicate(root, query, cb))); + for (final Predicate predicate : additionalPredicates) { + predicates.add(predicate); + } + return predicates.toArray(new Predicate[predicates.size()]); + } + + @Override + public Long countSoftwareModuleByFilters(final String searchText, final SoftwareModuleType type) { + + final List> specList = new ArrayList<>(); + + Specification spec = SoftwareModuleSpecification.isDeletedFalse(); + specList.add(spec); + + if (!Strings.isNullOrEmpty(searchText)) { + spec = SoftwareModuleSpecification.likeNameOrVersion(searchText); + specList.add(spec); + } + + if (null != type) { + spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type); + specList.add(spec); + } + + return countSwModuleByCriteriaAPI(specList); + } + + @Override + public Page findSoftwareModuleTypesAll(final Pageable pageable) { + return softwareModuleTypeRepository.findByDeleted(pageable, false); + } + + @Override + public Long countSoftwareModuleTypesAll() { + return softwareModuleTypeRepository.countByDeleted(false); + } + + @Override + public SoftwareModuleType findSoftwareModuleTypeByKey(final String key) { + return softwareModuleTypeRepository.findByKey(key); + } + + @Override + public SoftwareModuleType findSoftwareModuleTypeById(final Long id) { + return softwareModuleTypeRepository.findOne(id); + } + + @Override + public SoftwareModuleType findSoftwareModuleTypeByName(final String name) { + return softwareModuleTypeRepository.findByName(name); + } + + @Override + @Modifying + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + public SoftwareModuleType createSoftwareModuleType(final SoftwareModuleType type) { + if (type.getId() != null) { + throw new EntityAlreadyExistsException("Given type contains an Id!"); + } + + return softwareModuleTypeRepository.save((JpaSoftwareModuleType) type); + } + + @Override + @Modifying + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + public void deleteSoftwareModuleType(final SoftwareModuleType ty) { + final JpaSoftwareModuleType type = (JpaSoftwareModuleType) ty; + + if (softwareModuleRepository.countByType(type) > 0 + || distributionSetTypeRepository.countByElementsSmType(type) > 0) { + final JpaSoftwareModuleType toDelete = entityManager.merge(type); + toDelete.setDeleted(true); + softwareModuleTypeRepository.save(toDelete); + } else { + softwareModuleTypeRepository.delete(type.getId()); + } + } + + @Override + public Page findSoftwareModuleByAssignedTo(final Pageable pageable, final DistributionSet set) { + return softwareModuleRepository.findByAssignedTo(pageable, (JpaDistributionSet) set); + } + + @Override + public Page findSoftwareModuleByAssignedToAndType(final Pageable pageable, + final DistributionSet set, final SoftwareModuleType type) { + return softwareModuleRepository.findByAssignedToAndType(pageable, (JpaDistributionSet) set, + (JpaSoftwareModuleType) type); + } + + @Override + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Modifying + public SoftwareModuleMetadata createSoftwareModuleMetadata(final SoftwareModuleMetadata md) { + final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) md; + + if (softwareModuleMetadataRepository.exists(metadata.getId())) { + throwMetadataKeyAlreadyExists(metadata.getId().getKey()); + } + // merge base software module so optLockRevision gets updated and audit + // log written because + // modifying metadata is modifying the base software module itself for + // auditing purposes. + entityManager.merge((JpaSoftwareModule) metadata.getSoftwareModule()).setLastModifiedAt(-1L); + return softwareModuleMetadataRepository.save(metadata); + } + + @Override + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Modifying + public List createSoftwareModuleMetadata(final Collection md) { + @SuppressWarnings({ "unchecked", "rawtypes" }) + final Collection metadata = (Collection) md; + + for (final JpaSoftwareModuleMetadata softwareModuleMetadata : metadata) { + checkAndThrowAlreadyExistsIfSoftwareModuleMetadataExists(softwareModuleMetadata.getId()); + } + metadata.forEach(m -> entityManager.merge((JpaSoftwareModule) m.getSoftwareModule()).setLastModifiedAt(-1L)); + return new ArrayList<>(softwareModuleMetadataRepository.save(metadata)); + } + + @Override + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Modifying + public SoftwareModuleMetadata updateSoftwareModuleMetadata(final SoftwareModuleMetadata md) { + final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) md; + + // check if exists otherwise throw entity not found exception + findSoftwareModuleMetadata(metadata.getId()); + // touch it to update the lock revision because we are modifying the + // software module + // indirectly + entityManager.merge((JpaSoftwareModule) metadata.getSoftwareModule()).setLastModifiedAt(-1L); + return softwareModuleMetadataRepository.save(metadata); + } + + @Override + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Modifying + public void deleteSoftwareModuleMetadata(final SoftwareModule softwareModule, final String key) { + softwareModuleMetadataRepository.delete(new SwMetadataCompositeKey(softwareModule, key)); + } + + @Override + public Page findSoftwareModuleMetadataBySoftwareModuleId(final Long swId, + final Pageable pageable) { + return softwareModuleMetadataRepository.findBySoftwareModuleId(swId, pageable); + } + + @Override + public Page findSoftwareModuleMetadataBySoftwareModuleId(final Long softwareModuleId, + final String rsqlParam, final Pageable pageable) { + + final Specification spec = RSQLUtility.parse(rsqlParam, + SoftwareModuleMetadataFields.class); + return convertSmMdPage( + softwareModuleMetadataRepository + .findAll( + (Specification) (root, query, cb) -> cb.and( + cb.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule) + .get(JpaSoftwareModule_.id), softwareModuleId), + spec.toPredicate(root, query, cb)), + pageable), + pageable); + } + + @Override + public List findSoftwareModuleMetadataBySoftwareModuleId(final Long softwareModuleId) { + return new ArrayList<> ( softwareModuleMetadataRepository + .findAll( + (Specification) (root, query, cb) -> cb.and( + cb.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule) + .get(JpaSoftwareModule_.id), softwareModuleId)))); + } + + @Override + public SoftwareModuleMetadata findSoftwareModuleMetadata(final SoftwareModule softwareModule, final String key) { + return findSoftwareModuleMetadata(new SwMetadataCompositeKey(softwareModule, key)); + } + + private SoftwareModuleMetadata findSoftwareModuleMetadata(final SwMetadataCompositeKey id) { + final SoftwareModuleMetadata findOne = softwareModuleMetadataRepository.findOne(id); + if (findOne == null) { + throw new EntityNotFoundException("Metadata with key '" + id.getKey() + "' does not exist"); + } + return findOne; + } + + private void checkAndThrowAlreadyExistsIfSoftwareModuleMetadataExists(final SwMetadataCompositeKey metadataId) { + if (softwareModuleMetadataRepository.exists(metadataId)) { + throw new EntityAlreadyExistsException( + "Metadata entry with key '" + metadataId.getKey() + "' already exists"); + } + } + + private static void throwMetadataKeyAlreadyExists(final String metadataKey) { + throw new EntityAlreadyExistsException("Metadata entry with key '" + metadataKey + "' already exists"); + } + + @Override + @Modifying + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + public void deleteSoftwareModule(final SoftwareModule bsm) { + deleteSoftwareModules(Sets.newHashSet(bsm.getId())); + } + + @Override + @Modifying + @Transactional(isolation = Isolation.READ_UNCOMMITTED) + public List createSoftwareModuleType(final Collection types) { + + return types.stream().map(this::createSoftwareModuleType).collect(Collectors.toList()); + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java index b6475f647..b96b59f6a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java @@ -222,7 +222,6 @@ public abstract class AbstractTableDetailsLayout extends populateLog(); populateDescription(); populateDetailsWidget(); - populateMetadataDetails(); } protected void populateLog() { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailslayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailslayout.java index d3892a9dc..cf41bdd4f 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailslayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailslayout.java @@ -40,38 +40,36 @@ import com.vaadin.ui.themes.ValoTheme; @SpringComponent @VaadinSessionScope -public class DistributionSetMetadatadetailslayout extends Table{ - +public class DistributionSetMetadatadetailslayout extends Table { + private static final long serialVersionUID = 2913758299611837718L; - - - private DistributionSetManagement distributionSetManagement; - + + private DistributionSetManagement distributionSetManagement; + private DsMetadataPopupLayout dsMetadataPopupLayout; private static final String METADATA_KEY = "Key"; - - private static final String VIEW ="view"; + + private static final String VIEW = "view"; private SpPermissionChecker permissionChecker; - + private transient EntityFactory entityFactory; private I18N i18n; - - private Long selectedDistSetId; - - /** - * - * @param i18n - * @param permissionChecker - * @param distributionSetManagement - * @param dsMetadataPopupLayout - */ + + private Long selectedDistSetId; + + /** + * + * @param i18n + * @param permissionChecker + * @param distributionSetManagement + * @param dsMetadataPopupLayout + */ public void init(final I18N i18n, final SpPermissionChecker permissionChecker, - final DistributionSetManagement distributionSetManagement, - final DsMetadataPopupLayout dsMetadataPopupLayout, - final EntityFactory entityFactory) { + final DistributionSetManagement distributionSetManagement, + final DsMetadataPopupLayout dsMetadataPopupLayout, final EntityFactory entityFactory) { this.i18n = i18n; this.permissionChecker = permissionChecker; this.distributionSetManagement = distributionSetManagement; @@ -80,7 +78,6 @@ public class DistributionSetMetadatadetailslayout extends Table{ createDSMetadataTable(); addCustomGeneratedColumns(); } - /** * Populate software module metadata. @@ -90,35 +87,15 @@ public class DistributionSetMetadatadetailslayout extends Table{ public void populateDSMetadata(final DistributionSet distributionSet) { removeAllItems(); if (null == distributionSet) { - return; + return; } selectedDistSetId = distributionSet.getId(); - final List dsMetadataList = distributionSet.getMetadata(); + final List dsMetadataList = distributionSetManagement + .findDistributionSetMetadataByDistributionSetId(selectedDistSetId); if (null != dsMetadataList && !dsMetadataList.isEmpty()) { dsMetadataList.forEach(dsMetadata -> setDSMetadataProperties(dsMetadata)); } - - } - - /** - * Create metadata . - * - * @param metadataKeyName - */ - public void createMetadata(final String metadataKeyName){ - final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource(); - final Item item = metadataContainer.addItem(metadataKeyName); - item.getItemProperty(METADATA_KEY).setValue(metadataKeyName); - } - - /** - * Delete metadata. - * - * @param metadataKeyName - */ - public void deleteMetadata(final String metadataKeyName){ - final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource(); - metadataContainer.removeItem(metadataKeyName); + } private void createDSMetadataTable() { @@ -131,9 +108,9 @@ public class DistributionSetMetadatadetailslayout extends Table{ setContainerDataSource(getDistSetContainer()); setColumnHeaderMode(ColumnHeaderMode.EXPLICIT); addDSMetadataTableHeader(); - setSizeFull(); - //same as height of other tabs in details tabsheet - setHeight(116,Unit.PIXELS); + setSizeFull(); + // same as height of other tabs in details tabsheet + setHeight(116, Unit.PIXELS); } private IndexedContainer getDistSetContainer() { @@ -141,7 +118,7 @@ public class DistributionSetMetadatadetailslayout extends Table{ container.addContainerProperty(METADATA_KEY, String.class, ""); setColumnExpandRatio(METADATA_KEY, 0.7f); setColumnAlignment(METADATA_KEY, Align.LEFT); - + if (permissionChecker.hasUpdateDistributionPermission()) { container.addContainerProperty(VIEW, Label.class, ""); setColumnExpandRatio(VIEW, 0.2F); @@ -154,39 +131,36 @@ public class DistributionSetMetadatadetailslayout extends Table{ setColumnHeader(METADATA_KEY, i18n.get("header.key")); } - - private void setDSMetadataProperties(final DistributionSetMetadata dsMetadata){ + private void setDSMetadataProperties(final DistributionSetMetadata dsMetadata) { final Item item = getContainerDataSource().addItem(dsMetadata.getKey()); item.getItemProperty(METADATA_KEY).setValue(dsMetadata.getKey()); - + } - - private void addCustomGeneratedColumns() { - addGeneratedColumn(METADATA_KEY, - (source, itemId, columnId) -> customMetadataDetailButton((String) itemId)); + + private void addCustomGeneratedColumns() { + addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId)); } private Button customMetadataDetailButton(final String metadataKey) { - final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, "View " - + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class); + final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, + "View " + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class); viewIcon.setData(metadataKey); viewIcon.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link" + " " + "text-style"); viewIcon.addClickListener(event -> showMetadataDetails(selectedDistSetId, metadataKey)); return viewIcon; } - + private static String getDetailLinkId(final String name) { - return new StringBuilder(SPUIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name) - .toString(); + return new StringBuilder(SPUIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name).toString(); } - - private void showMetadataDetails(final Long selectedDistSetId , final String metadataKey) { - DistributionSet distSet = distributionSetManagement.findDistributionSetById(selectedDistSetId); - + + private void showMetadataDetails(final Long selectedDistSetId, final String metadataKey) { + final DistributionSet distSet = distributionSetManagement.findDistributionSetById(selectedDistSetId); + /* display the window */ UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(distSet, - entityFactory.generateDistributionSetMetadata(distSet, metadataKey, "") )); + entityFactory.generateDistributionSetMetadata(distSet, metadataKey, ""))); } - + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java index 854347c11..355080636 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java @@ -80,7 +80,7 @@ public class SoftwareModuleMetadatadetailslayout extends Table { return; } selectedSWModuleId = swModule.getId(); - final List swMetadataList = swModule.getMetadata(); + final List swMetadataList = softwareManagement.findSoftwareModuleMetadataBySoftwareModuleId(selectedSWModuleId); if (null != swMetadataList && !swMetadataList.isEmpty()) { swMetadataList.forEach(swMetadata -> setSWMetadataProperties(swMetadata)); } @@ -160,7 +160,7 @@ public class SoftwareModuleMetadatadetailslayout extends Table { } private void showMetadataDetails(final Long selectedSWModuleId, final String metadataKey) { - SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId); + final SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId); /* display the window */ UI.getCurrent().addWindow( swMetadataPopupLayout.getWindow(swmodule, diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java index 03a86c44d..32deef7a8 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java @@ -17,7 +17,6 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; @@ -29,7 +28,6 @@ import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable; import org.eclipse.hawkbit.ui.common.tagdetails.DistributionTagToken; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder; -import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent; import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent; import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleAssignmentDiscardEvent; import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState; @@ -68,7 +66,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet private static final String SOFT_MODULE = "softwareModule"; private static final String UNASSIGN_SOFT_MODULE = "unassignSoftModule"; - + @Autowired private ManageDistUIState manageDistUIState; @@ -83,37 +81,20 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet @Autowired private transient DistributionSetManagement distributionSetManagement; - + @Autowired private DsMetadataPopupLayout dsMetadataPopupLayout; - + @Autowired private EntityFactory entityFactory; private SoftwareModuleDetailsTable softwareModuleTable; - + private DistributionSetMetadatadetailslayout dsMetadataTable; private VerticalLayout tagsLayout; - + private final Map assignedSWModule = new HashMap<>(); - - - @EventBusListenerMethod(scope = EventScope.SESSION) - void onEvent(final MetadataEvent event) { - UI.getCurrent() - .access(() -> { - DistributionSetMetadata dsMetadata = event.getDistributionSetMetadata(); - if (dsMetadata != null && isDistributionSetSelected(dsMetadata.getDistributionSet())) { - if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_DISTRIBUTION_SET_METADATA) { - dsMetadataTable.createMetadata(event.getDistributionSetMetadata().getKey()); - } else if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA) { - dsMetadataTable.deleteMetadata(event.getDistributionSetMetadata().getKey()); - } - } - }); - } - /** * softwareLayout Initialize the component. @@ -124,8 +105,8 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet softwareModuleTable.init(getI18n(), true, getPermissionChecker(), distributionSetManagement, getEventBus(), manageDistUIState); dsMetadataTable = new DistributionSetMetadatadetailslayout(); - dsMetadataTable.init(getI18n(), getPermissionChecker(),distributionSetManagement, - dsMetadataPopupLayout,entityFactory); + dsMetadataTable.init(getI18n(), getPermissionChecker(), distributionSetManagement, dsMetadataPopupLayout, + entityFactory); super.init(); } @@ -141,7 +122,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet populateTags(); populateMetadataDetails(); } - + private void populateModule() { softwareModuleTable.populateModule(getSelectedBaseEntity()); showUnsavedAssignment(); @@ -271,12 +252,12 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet updateDistributionSetDetailsLayout(null, null); } } - + @Override - protected void populateMetadataDetails(){ + protected void populateMetadataDetails() { dsMetadataTable.populateDSMetadata(getSelectedBaseEntity()); - } - + } + private void updateDistributionSetDetailsLayout(final String type, final Boolean isMigrationRequired) { final VerticalLayout detailsTabLayout = getDetailsLayout(); detailsTabLayout.removeAllComponents(); @@ -403,26 +384,26 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet protected Boolean isMetadataIconToBeDisplayed() { return true; } - + @Override protected String getShowMetadataButtonId() { - DistributionSetIdName lastselectedDistDS = manageDistUIState.getLastSelectedDistribution().isPresent() ? manageDistUIState - .getLastSelectedDistribution().get() : null; + final DistributionSetIdName lastselectedDistDS = manageDistUIState.getLastSelectedDistribution().isPresent() + ? manageDistUIState.getLastSelectedDistribution().get() : null; return SPUIComponentIdProvider.DS_TABLE_MANAGE_METADATA_ID + "." + lastselectedDistDS.getName() + "." + lastselectedDistDS.getVersion(); } - - private boolean isDistributionSetSelected(DistributionSet ds) { - DistributionSetIdName lastselectedDistDS = manageDistUIState.getLastSelectedDistribution().isPresent() ? manageDistUIState - .getLastSelectedDistribution().get() : null; + + private boolean isDistributionSetSelected(final DistributionSet ds) { + final DistributionSetIdName lastselectedDistDS = manageDistUIState.getLastSelectedDistribution().isPresent() + ? manageDistUIState.getLastSelectedDistribution().get() : null; return ds != null && lastselectedDistDS != null && lastselectedDistDS.getName().equals(ds.getName()) && lastselectedDistDS.getVersion().endsWith(ds.getVersion()); } - @Override - protected void showMetadata(ClickEvent event) { - DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(getSelectedBaseEntityId()); - UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds,null)); + protected void showMetadata(final ClickEvent event) { + final DistributionSet ds = distributionSetManagement + .findDistributionSetByIdWithDetails(getSelectedBaseEntityId()); + UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds, null)); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DsMetadataPopupLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DsMetadataPopupLayout.java index 2041944d4..0d433d910 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DsMetadataPopupLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DsMetadataPopupLayout.java @@ -16,8 +16,6 @@ import org.eclipse.hawkbit.repository.SpPermissionChecker; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.ui.common.AbstractMetadataPopupLayout; -import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent; -import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent.MetadataUIEvent; import org.springframework.beans.factory.annotation.Autowired; import com.vaadin.spring.annotation.SpringComponent; @@ -42,19 +40,19 @@ public class DsMetadataPopupLayout extends AbstractMetadataPopupLayout getMetadataList() { return getSelectedEntity().getMetadata(); } - + /** * Update metadata for DistributionSet. */ @Override - protected void deleteMetadata(DistributionSet entity, String key, String value) { - DistributionSetMetadata dsMetaData = entityFactory.generateDistributionSetMetadata(entity, key, value); + protected void deleteMetadata(final DistributionSet entity, final String key, final String value) { + final DistributionSetMetadata dsMetaData = entityFactory.generateDistributionSetMetadata(entity, key, value); distributionSetManagement.deleteDistributionSetMetadata(entity, key); - eventBus.publish(this, new MetadataEvent(MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA, dsMetaData)); } - + @Override protected boolean hasCreatePermission() { return permChecker.hasCreateDistributionPermission(); } - + @Override protected boolean hasUpdatePermission() { return permChecker.hasUpdateDistributionPermission(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java index f82bc5c01..2436de9e5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.ui.distributions.event; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; + /** * * Metadata Events. @@ -18,21 +19,21 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; public class MetadataEvent { public enum MetadataUIEvent { - CREATE_DISTRIBUTION_SET_METADATA, DELETE_DISTRIBUTION_SET_METADATA, DELETE_SOFTWARE_MODULE_METADATA, CREATE_SOFTWARE_MODULE_METADATA; + DELETE_SOFTWARE_MODULE_METADATA, CREATE_SOFTWARE_MODULE_METADATA; } - private MetadataUIEvent metadataUIEvent; + private final MetadataUIEvent metadataUIEvent; private DistributionSetMetadata distributionSetMetadata; private SoftwareModuleMetadata softwareModuleMetadata; - public MetadataEvent(MetadataUIEvent metadataUIEvent, final DistributionSetMetadata distributionSetMetadata) { + public MetadataEvent(final MetadataUIEvent metadataUIEvent, final DistributionSetMetadata distributionSetMetadata) { this.metadataUIEvent = metadataUIEvent; this.distributionSetMetadata = distributionSetMetadata; } - public MetadataEvent(MetadataUIEvent metadataUIEvent, final SoftwareModuleMetadata softwareModuleMetadata) { + public MetadataEvent(final MetadataUIEvent metadataUIEvent, final SoftwareModuleMetadata softwareModuleMetadata) { this.metadataUIEvent = metadataUIEvent; this.softwareModuleMetadata = softwareModuleMetadata; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java index d83f7b4c8..a4b8c6a86 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java @@ -37,6 +37,7 @@ import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; +import org.eclipse.hawkbit.ui.utils.SpringContextHelper; import org.eclipse.hawkbit.ui.utils.UINotification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -84,10 +85,6 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent { @Autowired private transient EntityFactory entityFactory; - - @Autowired - private transient DistributionSetTable distributionSetTable; - private TextField distNameTextField; private TextField distVersionTextField; private TextArea descTextArea; @@ -239,9 +236,10 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent { notificationMessage.displaySuccess(i18n.get("message.new.dist.save.success", new Object[] { newDist.getName(), newDist.getVersion() })); - + final Set s = new HashSet<>(); - s.add(new DistributionSetIdName(newDist.getId(),newDist.getName(),newDist.getVersion())); + s.add(new DistributionSetIdName(newDist.getId(), newDist.getName(), newDist.getVersion())); + final DistributionSetTable distributionSetTable = SpringContextHelper.getBean(DistributionSetTable.class); distributionSetTable.setValue(s); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java index e59820e9c..b61cc103c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java @@ -11,7 +11,6 @@ package org.eclipse.hawkbit.ui.management.dstable; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.ui.common.DistributionSetIdName; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractNamedVersionedEntityTableDetailsLayout; import org.eclipse.hawkbit.ui.common.detailslayout.DistributionSetMetadatadetailslayout; @@ -19,7 +18,6 @@ import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable; import org.eclipse.hawkbit.ui.common.tagdetails.DistributionTagToken; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.distributions.dstable.DsMetadataPopupLayout; -import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent; import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent; import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; @@ -53,48 +51,32 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail @Autowired private DistributionTagToken distributionTagToken; - + @Autowired - private transient DistributionSetManagement distributionSetManagement; - + private transient DistributionSetManagement distributionSetManagement; + @Autowired private DsMetadataPopupLayout dsMetadataPopupLayout; - + @Autowired private EntityFactory entityFactory; private SoftwareModuleDetailsTable softwareModuleTable; private DistributionSetMetadatadetailslayout dsMetadataTable; - + @Override protected void init() { softwareModuleTable = new SoftwareModuleDetailsTable(); softwareModuleTable.init(getI18n(), false, getPermissionChecker(), null, null, null); - + dsMetadataTable = new DistributionSetMetadatadetailslayout(); - dsMetadataTable.init(getI18n(), getPermissionChecker(),distributionSetManagement, - dsMetadataPopupLayout,entityFactory); - + dsMetadataTable.init(getI18n(), getPermissionChecker(), distributionSetManagement, dsMetadataPopupLayout, + entityFactory); + super.init(); } - @EventBusListenerMethod(scope = EventScope.SESSION) - void onEvent(final MetadataEvent event) { - UI.getCurrent() - .access(() -> { - DistributionSetMetadata dsMetadata = event.getDistributionSetMetadata(); - if (dsMetadata != null && isDistributionSetSelected(dsMetadata.getDistributionSet())) { - if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_DISTRIBUTION_SET_METADATA) { - dsMetadataTable.createMetadata(event.getDistributionSetMetadata().getKey()); - } else if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA) { - dsMetadataTable.deleteMetadata(event.getDistributionSetMetadata().getKey()); - } - } - }); - } - - @EventBusListenerMethod(scope = EventScope.SESSION) void onEvent(final DistributionTableEvent distributionTableEvent) { onBaseEntityEvent(distributionTableEvent); @@ -156,12 +138,11 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail populateMetadataDetails(); } - - + @Override - protected void populateMetadataDetails(){ + protected void populateMetadataDetails() { dsMetadataTable.populateDSMetadata(getSelectedBaseEntity()); - } + } private void populateDetails(final DistributionSet ds) { if (ds != null) { @@ -206,30 +187,32 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail protected String getDetailsHeaderCaptionId() { return SPUIComponentIdProvider.DISTRIBUTION_DETAILS_HEADER_LABEL_ID; } - + @Override protected Boolean isMetadataIconToBeDisplayed() { return true; } - + @Override protected String getShowMetadataButtonId() { - DistributionSetIdName lastselectedDistDS = managementUIState.getLastSelectedDistribution().isPresent() ? managementUIState - .getLastSelectedDistribution().get() : null; + final DistributionSetIdName lastselectedDistDS = managementUIState.getLastSelectedDistribution().isPresent() + ? managementUIState.getLastSelectedDistribution().get() : null; return SPUIComponentIdProvider.DS_TABLE_MANAGE_METADATA_ID + "." + lastselectedDistDS.getName() + "." + lastselectedDistDS.getVersion(); } - private boolean isDistributionSetSelected(DistributionSet ds) { - DistributionSetIdName lastselectedManageDS = managementUIState.getLastSelectedDistribution().isPresent() ? managementUIState - .getLastSelectedDistribution().get() : null; - return ds!=null && lastselectedManageDS != null && lastselectedManageDS.getName().equals(ds.getName()) + + private boolean isDistributionSetSelected(final DistributionSet ds) { + final DistributionSetIdName lastselectedManageDS = managementUIState.getLastSelectedDistribution().isPresent() + ? managementUIState.getLastSelectedDistribution().get() : null; + return ds != null && lastselectedManageDS != null && lastselectedManageDS.getName().equals(ds.getName()) && lastselectedManageDS.getVersion().endsWith(ds.getVersion()); } @Override - protected void showMetadata(ClickEvent event) { - DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(getSelectedBaseEntityId()); - UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds,null)); + protected void showMetadata(final ClickEvent event) { + final DistributionSet ds = distributionSetManagement + .findDistributionSetByIdWithDetails(getSelectedBaseEntityId()); + UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds, null)); } - + }