Started to split the actual model.

Signed-off-by: Kai Zimmermann <kai.zimmermann@bosch-si.com>
This commit is contained in:
Kai Zimmermann
2016-05-20 17:25:38 +02:00
parent 3e5330a5e6
commit e3041aa9ae
154 changed files with 6730 additions and 4950 deletions

View File

@@ -20,6 +20,7 @@ import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent;
import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent; import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent;
import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.repository.jpa.TargetRepository; import org.eclipse.hawkbit.repository.jpa.TargetRepository;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
@@ -147,7 +148,7 @@ public class EntityChangeEventListener {
} }
private static boolean isTargetInfoNew(final Object targetInfo) { private static boolean isTargetInfoNew(final Object targetInfo) {
return ((TargetInfo) targetInfo).isNew(); return ((JpaTargetInfo) targetInfo).isNew();
} }
} }

View File

@@ -31,8 +31,6 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
/** /**
* Service layer for all operations of the DDI API (with access permissions only * Service layer for all operations of the DDI API (with access permissions only
@@ -248,7 +246,6 @@ public interface ControllerManagement {
* *
*/ */
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
TargetInfo updateLastTargetQuery(@NotNull TargetInfo target, @NotNull URI address); TargetInfo updateLastTargetQuery(@NotNull TargetInfo target, @NotNull URI address);
/** /**
@@ -271,4 +268,11 @@ public interface ControllerManagement {
TargetInfo updateTargetStatus(@NotNull TargetInfo targetInfo, TargetUpdateStatus status, Long lastTargetQuery, TargetInfo updateTargetStatus(@NotNull TargetInfo targetInfo, TargetUpdateStatus status, Long lastTargetQuery,
URI address); URI address);
/**
* Generates an empty {@link ActionStatus} without persisting it.
*
* @return {@link ActionStatus} object
*/
ActionStatus generateActionStatus();
} }

View File

@@ -31,7 +31,6 @@ import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
/** /**
@@ -179,7 +178,7 @@ public interface DeploymentManagement {
* @return the count value of found actions associated to the target * @return the count value of found actions associated to the target
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Long countActionsByTarget(@NotNull Specification<Action> spec, @NotNull Target target); Long countActionsByTarget(@NotNull String rsqlParam, @NotNull Target target);
/** /**
* counts all actions associated to a specific target. * counts all actions associated to a specific target.
@@ -281,9 +280,9 @@ public interface DeploymentManagement {
* @return a slice of actions assigned to the specific target and the * @return a slice of actions assigned to the specific target and the
* specification * specification
*/ */
// TODO fix this
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<Action> findActionsByTarget(@NotNull Specification<Action> specifiction, @NotNull Target target, Slice<Action> findActionsByTarget(@NotNull String rsqlParam, @NotNull Target target, @NotNull Pageable pageable);
@NotNull Pageable pageable);
/** /**
* Retrieves all {@link Action}s of a specific target ordered by action ID. * Retrieves all {@link Action}s of a specific target ordered by action ID.
@@ -440,4 +439,10 @@ public interface DeploymentManagement {
+ SpringEvalExpressions.IS_SYSTEM_CODE) + SpringEvalExpressions.IS_SYSTEM_CODE)
Action startScheduledAction(@NotNull Action action); Action startScheduledAction(@NotNull Action action);
/**
* Generates an empty {@link Action} without persisting it.
*
* @return {@link Action} object
*/
Action generateAction();
} }

View File

@@ -59,9 +59,10 @@ public class DistributionSetAssignmentResult extends AssignmentResult<Target> {
return actions; return actions;
} }
@SuppressWarnings("unchecked")
@Override @Override
public List<Target> getAssignedEntity() { public List<Target> getAssignedEntity() {
return targetManagement.findTargetByControllerID(assignedTargets); return (List<Target>) targetManagement.findTargetByControllerID(assignedTargets);
} }
} }

View File

@@ -21,14 +21,14 @@ import org.eclipse.hawkbit.repository.exception.DistributionSetCreationFailedMis
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
import org.eclipse.hawkbit.repository.jpa.model.DistributionSetTypeElement;
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.DistributionSetTypeElement;
import org.eclipse.hawkbit.repository.model.DsMetadataCompositeKey;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Tag;
@@ -36,7 +36,6 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -274,18 +273,7 @@ public interface DistributionSetManagement {
* @return the found {@link DistributionSet}s * @return the found {@link DistributionSet}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Iterable<DistributionSet> findDistributionSetList(Collection<Long> dist); List<DistributionSet> findDistributionSetsAll(Collection<Long> dist);
/**
* Retrieves {@link DistributionSet} List including details information,
* i.e. @link BaseSoftwareModule}s and {@link DistributionSetTag}s.
*
* @param distributionIdSet
* List of {@link DistributionSet} IDs to be found
* @return the found {@link DistributionSet}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
List<DistributionSet> findDistributionSetListWithDetails(Collection<Long> distributionIdSet);
/** /**
* finds all meta data by the given distribution set id. * finds all meta data by the given distribution set id.
@@ -315,7 +303,7 @@ public interface DistributionSetManagement {
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId, Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId,
@NotNull Specification<DistributionSetMetadata> spec, @NotNull Pageable pageable); @NotNull String rsqlParam, @NotNull Pageable pageable);
// TODO discuss: use enum instead of the true,false,null switch ? // TODO discuss: use enum instead of the true,false,null switch ?
/** /**
@@ -357,8 +345,8 @@ public interface DistributionSetManagement {
* @return all found {@link DistributionSet}s * @return all found {@link DistributionSet}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<DistributionSet> findDistributionSetsAll(@NotNull Specification<DistributionSet> spec, Page<DistributionSet> findDistributionSetsAll(@NotNull String rsqlParam, @NotNull Pageable pageReq,
@NotNull Pageable pageReq, Boolean deleted); Boolean deleted);
/** /**
* method retrieves all {@link DistributionSet}s from the repository in the * method retrieves all {@link DistributionSet}s from the repository in the
@@ -442,8 +430,7 @@ public interface DistributionSetManagement {
* @return the found {@link SoftwareModuleType}s * @return the found {@link SoftwareModuleType}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<DistributionSetType> findDistributionSetTypesAll(@NotNull Specification<DistributionSetType> spec, Page<DistributionSetType> findDistributionSetTypesAll(@NotNull String rsqlParam, @NotNull Pageable pageable);
@NotNull Pageable pageable);
/** /**
* finds a single distribution set meta data by its id. * finds a single distribution set meta data by its id.
@@ -580,4 +567,17 @@ public interface DistributionSetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
DistributionSetType updateDistributionSetType(@NotNull DistributionSetType dsType); DistributionSetType updateDistributionSetType(@NotNull DistributionSetType dsType);
/**
* Generates an empty {@link DistributionSetType} without persisting it.
*
* @return {@link DistributionSetType} object
*/
DistributionSetType generateDistributionSetType();
/**
* Generates an empty {@link DistributionSet} without persisting it.
*
* @return {@link DistributionSet} object
*/
DistributionSet generateDistributionSet();
} }

View File

@@ -84,8 +84,8 @@ public interface RolloutGroupManagement {
* @return a page of found {@link RolloutGroup}s * @return a page of found {@link RolloutGroup}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ)
Page<RolloutGroup> findRolloutGroupsAll(@NotNull Rollout rollout, Page<RolloutGroup> findRolloutGroupsAll(@NotNull Rollout rollout, @NotNull String rsqlParam,
@NotNull Specification<RolloutGroup> specification, @NotNull Pageable page); @NotNull Pageable page);
/** /**
* Retrieves a page of {@link RolloutGroup}s filtered by a given * Retrieves a page of {@link RolloutGroup}s filtered by a given
@@ -128,8 +128,8 @@ public interface RolloutGroupManagement {
* @return Page<Target> list of targets of a rollout group * @return Page<Target> list of targets of a rollout group
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ)
Page<Target> findRolloutGroupTargets(@NotNull RolloutGroup rolloutGroup, Page<Target> findRolloutGroupTargets(@NotNull RolloutGroup rolloutGroup, @NotNull String rsqlParam,
@NotNull Specification<Target> specification, @NotNull Pageable page); @NotNull Pageable page);
/** /**
* Get count of targets in different status in rollout group. * Get count of targets in different status in rollout group.
@@ -141,4 +141,10 @@ public interface RolloutGroupManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ)
RolloutGroup findRolloutGroupWithDetailedStatus(@NotNull Long rolloutGroupId); RolloutGroup findRolloutGroupWithDetailedStatus(@NotNull Long rolloutGroupId);
/**
* Generates an empty {@link RolloutGroup} without persisting it.
*
* @return {@link RolloutGroup} object
*/
RolloutGroup generateRolloutGroup();
} }

View File

@@ -13,16 +13,15 @@ import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.eventbus.event.RolloutGroupCreatedEvent; import org.eclipse.hawkbit.eventbus.event.RolloutGroupCreatedEvent;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout.RolloutStatus;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup.RolloutGroupConditions;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup.RolloutGroupStatus;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupConditions;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
/** /**
@@ -179,8 +178,7 @@ public interface RolloutManagement {
* @return a page of found rollouts * @return a page of found rollouts
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ)
Page<Rollout> findAllWithDetailedStatusByPredicate(@NotNull Specification<Rollout> specification, Page<Rollout> findAllWithDetailedStatusByPredicate(@NotNull String rsqlParam, @NotNull Pageable page);
@NotNull Pageable page);
/** /**
* Finds rollouts by given text in name or description. * Finds rollouts by given text in name or description.
@@ -335,4 +333,11 @@ public interface RolloutManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
Rollout updateRollout(@NotNull Rollout rollout); Rollout updateRollout(@NotNull Rollout rollout);
/**
* Generates an empty {@link Rollout} without persisting it.
*
* @return {@link Rollout} object
*/
Rollout generateRollout();
} }

View File

@@ -17,17 +17,16 @@ import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey;
import org.eclipse.hawkbit.repository.model.CustomSoftwareModule; import org.eclipse.hawkbit.repository.model.CustomSoftwareModule;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.SwMetadataCompositeKey;
import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
/** /**
@@ -290,7 +289,7 @@ public interface SoftwareManagement {
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(@NotNull Long softwareModuleId, Page<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(@NotNull Long softwareModuleId,
@NotNull Specification<SoftwareModuleMetadata> spec, @NotNull Pageable pageable); @NotNull String rsqlParam, @NotNull Pageable pageable);
/** /**
* Filter {@link SoftwareModule}s with given * Filter {@link SoftwareModule}s with given
@@ -347,8 +346,7 @@ public interface SoftwareManagement {
* @return the found {@link SoftwareModule}s * @return the found {@link SoftwareModule}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<SoftwareModule> findSoftwareModulesByPredicate(@NotNull Specification<SoftwareModule> spec, Page<SoftwareModule> findSoftwareModulesByPredicate(@NotNull String rsqlParam, @NotNull Pageable pageable);
@NotNull Pageable pageable);
/** /**
* retrieves the {@link SoftwareModule}s by their {@link SoftwareModuleType} * retrieves the {@link SoftwareModule}s by their {@link SoftwareModuleType}
@@ -411,8 +409,7 @@ public interface SoftwareManagement {
* @return the found {@link SoftwareModuleType}s * @return the found {@link SoftwareModuleType}s
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<SoftwareModuleType> findSoftwareModuleTypesByPredicate(@NotNull Specification<SoftwareModuleType> spec, Page<SoftwareModuleType> findSoftwareModuleTypesByPredicate(@NotNull String rsqlParam, @NotNull Pageable pageable);
@NotNull Pageable pageable);
/** /**
* Retrieves software module including details ( * Retrieves software module including details (
@@ -468,4 +465,17 @@ public interface SoftwareManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
SoftwareModuleType updateSoftwareModuleType(@NotNull SoftwareModuleType sm); SoftwareModuleType updateSoftwareModuleType(@NotNull SoftwareModuleType sm);
/**
* Generates an empty {@link SoftwareModuleType} without persisting it.
*
* @return {@link SoftwareModuleType} object
*/
SoftwareModuleType generateSoftwareModuleType();
/**
* Generates an empty {@link SoftwareModule} without persisting it.
*
* @return {@link SoftwareModule} object
*/
SoftwareModule generateSoftwareModule();
} }

View File

@@ -23,7 +23,6 @@ import org.eclipse.hawkbit.repository.model.TargetTag;
import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
/** /**
@@ -90,7 +89,7 @@ public interface TagManagement {
* if given object has already an ID. * if given object has already an ID.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
List<TargetTag> createTargetTags(@NotNull Iterable<TargetTag> targetTags); List<TargetTag> createTargetTags(@NotNull Collection<TargetTag> targetTags);
/** /**
* Deletes {@link DistributionSetTag} by given * Deletes {@link DistributionSetTag} by given
@@ -138,8 +137,7 @@ public interface TagManagement {
* @return the found {@link DistributionSetTag}s, never {@code null} * @return the found {@link DistributionSetTag}s, never {@code null}
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<DistributionSetTag> findAllDistributionSetTags(@NotNull Specification<DistributionSetTag> spec, Page<DistributionSetTag> findAllDistributionSetTags(@NotNull String rsqlParam, @NotNull Pageable pageable);
@NotNull Pageable pageable);
/** /**
* @return all {@link TargetTag}s * @return all {@link TargetTag}s
@@ -168,7 +166,7 @@ public interface TagManagement {
* @return the found {@link Target}s, never {@code null} * @return the found {@link Target}s, never {@code null}
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<TargetTag> findAllTargetTags(@NotNull Specification<TargetTag> spec, @NotNull Pageable pageable); Page<TargetTag> findAllTargetTags(@NotNull String rsqlParam, @NotNull Pageable pageable);
/** /**
* Find {@link DistributionSet} based on given name. * Find {@link DistributionSet} based on given name.
@@ -233,4 +231,18 @@ public interface TagManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetTag updateTargetTag(@NotNull TargetTag targetTag); TargetTag updateTargetTag(@NotNull TargetTag targetTag);
/**
* Generates an empty {@link TargetTag} without persisting it.
*
* @return {@link TargetTag} object
*/
TargetTag generateTargetTag();
/**
* Generates an empty {@link DistributionSetTag} without persisting it.
*
* @return {@link DistributionSetTag} object
*/
DistributionSetTag generateDistributionSetTag();
} }

View File

@@ -30,7 +30,6 @@ import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
/** /**
@@ -290,8 +289,8 @@ public interface TargetManagement {
* @return the found {@link Target}s, never {@code null} * @return the found {@link Target}s, never {@code null}
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
Page<Target> findTargetByAssignedDistributionSet(@NotNull Long distributionSetID, Page<Target> findTargetByAssignedDistributionSet(@NotNull Long distributionSetID, @NotNull String rsqlParam,
@NotNull Specification<Target> spec, @NotNull Pageable pageReq); @NotNull Pageable pageReq);
/** /**
* Find {@link Target} based on given ID returns found Target without * Find {@link Target} based on given ID returns found Target without
@@ -390,8 +389,8 @@ public interface TargetManagement {
* @return the found {@link Target}s, never {@code null} * @return the found {@link Target}s, never {@code null}
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
Page<Target> findTargetByInstalledDistributionSet(@NotNull Long distributionSetId, Page<Target> findTargetByInstalledDistributionSet(@NotNull Long distributionSetId, @NotNull String rsqlParam,
@NotNull Specification<Target> spec, @NotNull Pageable pageable); @NotNull Pageable pageable);
/** /**
* Retrieves the {@link Target} which have a certain * Retrieves the {@link Target} which have a certain
@@ -418,18 +417,6 @@ public interface TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<Target> findTargetsAll(@NotNull Pageable pageable); Slice<Target> findTargetsAll(@NotNull Pageable pageable);
/**
* Retrieves all targets based on the given specification.
*
* @param spec
* the specification for the query
* @param pageable
* pagination parameter
* @return the found {@link Target}s, never {@code null}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Page<Target> findTargetsAll(@NotNull Specification<Target> spec, @NotNull Pageable pageable);
/** /**
* Retrieves all targets without details, i.e. NO {@link Target#getTags()} * Retrieves all targets without details, i.e. NO {@link Target#getTags()}
* and {@link Target#getActions()} possible based on * and {@link Target#getActions()} possible based on
@@ -442,7 +429,7 @@ public interface TargetManagement {
* @return the found {@link Target}s, never {@code null} * @return the found {@link Target}s, never {@code null}
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice<Target> findTargetsAll(@NotNull String targetFilterQuery, @NotNull Pageable pageable); Page<Target> findTargetsAll(@NotNull String targetFilterQuery, @NotNull Pageable pageable);
/** /**
* Retrieves all targets without details, i.e. NO {@link Target#getTags()} * Retrieves all targets without details, i.e. NO {@link Target#getTags()}
@@ -599,6 +586,16 @@ public interface TargetManagement {
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_CONTROLLER) + SpringEvalExpressions.IS_CONTROLLER)
List<Target> updateTargets(@NotNull Iterable<Target> targets); List<Target> updateTargets(@NotNull Collection<Target> targets);
/**
* Generates an empty {@link Target} without persisting it.
*
* @param controllerID
* of the {@link Target}
*
* @return {@link Target} object
*/
Target generateTarget(@NotEmpty String controllerID);
} }

View File

@@ -142,5 +142,4 @@ public interface TenantConfigurationManagement {
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_SYSTEM_CODE) + SpringEvalExpressions.IS_SYSTEM_CODE)
<T> T getGlobalConfigurationValue(TenantConfigurationKey configurationKey, Class<T> propertyType); <T> T getGlobalConfigurationValue(TenantConfigurationKey configurationKey, Class<T> propertyType);
} }

View File

@@ -11,6 +11,12 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -37,7 +43,7 @@ import org.springframework.transaction.annotation.Transactional;
* *
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface ActionRepository extends BaseEntityRepository<Action, Long>, JpaSpecificationExecutor<Action> { public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>, JpaSpecificationExecutor<JpaAction> {
/** /**
* Retrieves an Action with all lazy attributes. * Retrieves an Action with all lazy attributes.
* *
@@ -46,7 +52,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* @return the found {@link Action} * @return the found {@link Action}
*/ */
@EntityGraph(value = "Action.all", type = EntityGraphType.LOAD) @EntityGraph(value = "Action.all", type = EntityGraphType.LOAD)
Action findById(Long actionId); JpaAction findById(Long actionId);
/** /**
* Retrieves all {@link Action}s which are referring the given * Retrieves all {@link Action}s which are referring the given
@@ -58,7 +64,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* the {@link DistributionSet} on which will be filtered * the {@link DistributionSet} on which will be filtered
* @return the found {@link Action}s * @return the found {@link Action}s
*/ */
Page<Action> findByDistributionSet(final Pageable pageable, final DistributionSet ds); Page<Action> findByDistributionSet(final Pageable pageable, final JpaDistributionSet ds);
/** /**
* Retrieves all {@link Action}s which are referring the given * Retrieves all {@link Action}s which are referring the given
@@ -70,7 +76,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* the target to find assigned actions * the target to find assigned actions
* @return the found {@link Action}s * @return the found {@link Action}s
*/ */
Slice<Action> findByTarget(Pageable pageable, Target target); Slice<Action> findByTarget(Pageable pageable, JpaTarget target);
/** /**
* Retrieves all {@link Action}s which are active and referring the given * Retrieves all {@link Action}s which are active and referring the given
@@ -86,7 +92,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* @return the found {@link Action}s * @return the found {@link Action}s
*/ */
@EntityGraph(value = "Action.ds", type = EntityGraphType.LOAD) @EntityGraph(value = "Action.ds", type = EntityGraphType.LOAD)
List<Action> findByTargetAndActiveOrderByIdAsc(final Target target, boolean active); List<Action> findByTargetAndActiveOrderByIdAsc(final JpaTarget target, boolean active);
/** /**
* Retrieves latest {@link UpdateAction} for given target and * Retrieves latest {@link UpdateAction} for given target and
@@ -99,9 +105,9 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* @return action if there is one with assigned target and module is part of * @return action if there is one with assigned target and module is part of
* assigned {@link DistributionSet}. * assigned {@link DistributionSet}.
*/ */
@Query("Select a from Action a join a.distributionSet ds join ds.modules modul where a.target.controllerId = :target and modul = :module order by a.id desc") @Query("Select a from JpaAction a join a.distributionSet ds join ds.modules modul where a.target.controllerId = :target and modul = :module order by a.id desc")
List<Action> findActionByTargetAndSoftwareModule(@Param("target") final String targetId, List<Action> findActionByTargetAndSoftwareModule(@Param("target") final String targetId,
@Param("module") SoftwareModule module); @Param("module") JpaSoftwareModule module);
/** /**
* Retrieves all {@link UpdateAction}s which are referring the given * Retrieves all {@link UpdateAction}s which are referring the given
@@ -115,9 +121,9 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* the {@link DistributionSet} on which will be filtered * the {@link DistributionSet} on which will be filtered
* @return the found {@link UpdateAction}s * @return the found {@link UpdateAction}s
*/ */
@Query("Select a from Action a where a.target = :target and a.distributionSet = :ds order by a.id") @Query("Select a from JpaAction a where a.target = :target and a.distributionSet = :ds order by a.id")
Page<Action> findByTargetAndDistributionSet(final Pageable pageable, @Param("target") final Target target, Page<Action> findByTargetAndDistributionSet(final Pageable pageable, @Param("target") final JpaTarget target,
@Param("ds") DistributionSet ds); @Param("ds") JpaDistributionSet ds);
/** /**
* Retrieves all {@link Action}s of a specific target, without pagination * Retrieves all {@link Action}s of a specific target, without pagination
@@ -127,8 +133,8 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* to search for * to search for
* @return a list of actions according to the searched target * @return a list of actions according to the searched target
*/ */
@Query("Select a from Action a where a.target = :target order by a.id") @Query("Select a from JpaAction a where a.target = :target order by a.id")
List<Action> findByTarget(@Param("target") final Target target); List<Action> findByTarget(@Param("target") final JpaTarget target);
/** /**
* Retrieves all {@link Action}s of a specific target and given active flag * Retrieves all {@link Action}s of a specific target and given active flag
@@ -143,8 +149,8 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* {@code false} for inactive * {@code false} for inactive
* @return a paged list of actions ordered by action ID * @return a paged list of actions ordered by action ID
*/ */
@Query("Select a from Action a where a.target = :target and a.active= :active order by a.id") @Query("Select a from JpaAction a where a.target = :target and a.active= :active order by a.id")
Page<Action> findByActiveAndTarget(Pageable pageable, @Param("target") Target target, Page<Action> findByActiveAndTarget(Pageable pageable, @Param("target") JpaTarget target,
@Param("active") boolean active); @Param("active") boolean active);
/** /**
@@ -160,8 +166,8 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* @return a list of actions ordered by action ID * @return a list of actions ordered by action ID
*/ */
@EntityGraph(value = "Action.ds", type = EntityGraphType.LOAD) @EntityGraph(value = "Action.ds", type = EntityGraphType.LOAD)
@Query("Select a from Action a where a.target = :target and a.active= :active order by a.id") @Query("Select a from JpaAction a where a.target = :target and a.active= :active order by a.id")
List<Action> findByActiveAndTarget(@Param("target") Target target, @Param("active") boolean active); List<Action> findByActiveAndTarget(@Param("target") JpaTarget target, @Param("active") boolean active);
/** /**
* Updates all {@link Action} to inactive for all targets with given ID. * Updates all {@link Action} to inactive for all targets with given ID.
@@ -174,8 +180,8 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
*/ */
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Query("UPDATE Action a SET a.active = false WHERE a IN :keySet AND a.target IN :targetsIds") @Query("UPDATE JpaAction a SET a.active = false WHERE a IN :keySet AND a.target IN :targetsIds")
void setToInactive(@Param("keySet") List<Action> keySet, @Param("targetsIds") List<Long> targetsIds); void setToInactive(@Param("keySet") List<JpaAction> keySet, @Param("targetsIds") List<Long> targetsIds);
/** /**
* Switches the status of actions from one specific status into another, * Switches the status of actions from one specific status into another,
@@ -193,7 +199,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
*/ */
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Query("UPDATE Action a SET a.status = :statusToSet WHERE a.target IN :targetsIds AND a.active = :active AND a.status = :currentStatus AND a.distributionSet.requiredMigrationStep = false") @Query("UPDATE JpaAction a SET a.status = :statusToSet WHERE a.target IN :targetsIds AND a.active = :active AND a.status = :currentStatus AND a.distributionSet.requiredMigrationStep = false")
void switchStatus(@Param("statusToSet") Action.Status statusToSet, @Param("targetsIds") List<Long> targetIds, void switchStatus(@Param("statusToSet") Action.Status statusToSet, @Param("targetsIds") List<Long> targetIds,
@Param("active") boolean active, @Param("currentStatus") Action.Status currentStatus); @Param("active") boolean active, @Param("currentStatus") Action.Status currentStatus);
@@ -213,8 +219,8 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
*/ */
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Query("UPDATE Action a SET a.status = :statusToSet WHERE a.rollout = :rollout AND a.active = :active AND a.status = :currentStatus") @Query("UPDATE JpaAction a SET a.status = :statusToSet WHERE a.rollout = :rollout AND a.active = :active AND a.status = :currentStatus")
void switchStatus(@Param("statusToSet") Action.Status statusToSet, @Param("rollout") Rollout rollout, void switchStatus(@Param("statusToSet") Action.Status statusToSet, @Param("rollout") JpaRollout rollout,
@Param("active") boolean active, @Param("currentStatus") Action.Status currentStatus); @Param("active") boolean active, @Param("currentStatus") Action.Status currentStatus);
/** /**
@@ -228,8 +234,8 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* the status which the actions should not have * the status which the actions should not have
* @return the found list of {@link Action}s * @return the found list of {@link Action}s
*/ */
@Query("SELECT a FROM Action a WHERE a.active = true AND a.distributionSet.requiredMigrationStep = false AND a.target IN ?1 AND a.status != ?2") @Query("SELECT a FROM JpaAction a WHERE a.active = true AND a.distributionSet.requiredMigrationStep = false AND a.target IN ?1 AND a.status != ?2")
List<Action> findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetRequiredMigrationStep( List<JpaAction> findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetRequiredMigrationStep(
Collection<Long> targetIds, Action.Status notStatus); Collection<Long> targetIds, Action.Status notStatus);
/** /**
@@ -239,15 +245,15 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* the target to count the {@link Action}s * the target to count the {@link Action}s
* @return the count of actions referring to the given target * @return the count of actions referring to the given target
*/ */
Long countByTarget(Target target); Long countByTarget(JpaTarget target);
@Override @Override
@CacheEvict(value = "feedbackReceivedOverTime", allEntries = true) @CacheEvict(value = "feedbackReceivedOverTime", allEntries = true)
<S extends Action> List<S> save(Iterable<S> entities); <S extends JpaAction> List<S> save(Iterable<S> entities);
@Override @Override
@CacheEvict(value = "feedbackReceivedOverTime", allEntries = true) @CacheEvict(value = "feedbackReceivedOverTime", allEntries = true)
<S extends Action> S save(S entity); <S extends JpaAction> S save(S entity);
/** /**
* Counts all {@link Action}s referring to the given DistributionSet. * Counts all {@link Action}s referring to the given DistributionSet.
@@ -256,7 +262,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* DistributionSet to count the {@link Action}s from * DistributionSet to count the {@link Action}s from
* @return the count of actions referring to the given distributionSet * @return the count of actions referring to the given distributionSet
*/ */
Long countByDistributionSet(DistributionSet distributionSet); Long countByDistributionSet(JpaDistributionSet distributionSet);
/** /**
* Counts all {@link Action}s referring to the given rollout. * Counts all {@link Action}s referring to the given rollout.
@@ -265,7 +271,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* the rollout to count the {@link Action}s from * the rollout to count the {@link Action}s from
* @return the count of actions referring to the given rollout * @return the count of actions referring to the given rollout
*/ */
Long countByRollout(Rollout rollout); Long countByRollout(JpaRollout rollout);
/** /**
* Counts all actions referring to a given rollout and rolloutgroup which * Counts all actions referring to a given rollout and rolloutgroup which
@@ -286,8 +292,8 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* @return the count of actions referring the rollout and rolloutgroup and * @return the count of actions referring the rollout and rolloutgroup and
* are not in given states * are not in given states
*/ */
Long countByRolloutAndRolloutGroupAndStatusNotAndStatusNotAndStatusNot(Rollout rollout, RolloutGroup rolloutGroup, Long countByRolloutAndRolloutGroupAndStatusNotAndStatusNotAndStatusNot(JpaRollout rollout,
Status notStatus1, Status notStatus2, Status notStatus3); JpaRolloutGroup rolloutGroup, Status notStatus1, Status notStatus2, Status notStatus3);
/** /**
* Counts all actions referring to a given rollout and rolloutgroup. * Counts all actions referring to a given rollout and rolloutgroup.
@@ -298,7 +304,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* the rolloutgroup the actions belong to * the rolloutgroup the actions belong to
* @return the count of actions referring to a rollout and rolloutgroup * @return the count of actions referring to a rollout and rolloutgroup
*/ */
Long countByRolloutAndRolloutGroup(Rollout rollout, RolloutGroup rolloutGroup); Long countByRolloutAndRolloutGroup(JpaRollout rollout, JpaRolloutGroup rolloutGroup);
/** /**
* Counts all actions referring to a given rollout, rolloutgroup and status. * Counts all actions referring to a given rollout, rolloutgroup and status.
@@ -329,7 +335,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* @return the actions referring a specific rollout and a specific parent * @return the actions referring a specific rollout and a specific parent
* rolloutgroup in a specific status * rolloutgroup in a specific status
*/ */
List<Action> findByRolloutAndRolloutGroupParentAndStatus(Rollout rollout, RolloutGroup rolloutGroupParent, List<Action> findByRolloutAndRolloutGroupParentAndStatus(JpaRollout rollout, JpaRolloutGroup rolloutGroupParent,
Status actionStatus); Status actionStatus);
/** /**
@@ -341,7 +347,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* the status of the actions * the status of the actions
* @return the actions referring a specific rollout an in a specific status * @return the actions referring a specific rollout an in a specific status
*/ */
List<Action> findByRolloutAndStatus(Rollout rollout, Status actionStatus); List<Action> findByRolloutAndStatus(JpaRollout rollout, Status actionStatus);
/** /**
* Get list of objects which has details of status and count of targets in * Get list of objects which has details of status and count of targets in
@@ -351,7 +357,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* id of {@link Rollout} * id of {@link Rollout}
* @return list of objects with status and target count * @return list of objects with status and target count
*/ */
@Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus( a.rollout.id, a.status , COUNT(a.target)) FROM Action a WHERE a.rollout.id IN ?1 GROUP BY a.rollout.id,a.status") @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus( a.rollout.id, a.status , COUNT(a.target)) FROM JpaAction a WHERE a.rollout.id IN ?1 GROUP BY a.rollout.id,a.status")
List<TotalTargetCountActionStatus> getStatusCountByRolloutId(List<Long> rolloutId); List<TotalTargetCountActionStatus> getStatusCountByRolloutId(List<Long> rolloutId);
/** /**
@@ -362,7 +368,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* id of {@link Rollout} * id of {@link Rollout}
* @return list of objects with status and target count * @return list of objects with status and target count
*/ */
@Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus( a.rollout.id, a.status , COUNT(a.target)) FROM Action a WHERE a.rollout.id = ?1 GROUP BY a.rollout.id,a.status") @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus( a.rollout.id, a.status , COUNT(a.target)) FROM JpaAction a WHERE a.rollout.id = ?1 GROUP BY a.rollout.id,a.status")
List<TotalTargetCountActionStatus> getStatusCountByRolloutId(Long rolloutId); List<TotalTargetCountActionStatus> getStatusCountByRolloutId(Long rolloutId);
/** /**
@@ -373,7 +379,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* id of {@link RolloutGroup} * id of {@link RolloutGroup}
* @return list of objects with status and target count * @return list of objects with status and target count
*/ */
@Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus(a.rolloutGroup.id, a.status , COUNT(a.target)) FROM Action a WHERE a.rolloutGroup.id = ?1 GROUP BY a.rolloutGroup.id, a.status") @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus(a.rolloutGroup.id, a.status , COUNT(a.target)) FROM JpaAction a WHERE a.rolloutGroup.id = ?1 GROUP BY a.rolloutGroup.id, a.status")
List<TotalTargetCountActionStatus> getStatusCountByRolloutGroupId(Long rolloutGroupId); List<TotalTargetCountActionStatus> getStatusCountByRolloutGroupId(Long rolloutGroupId);
/** /**
@@ -384,7 +390,7 @@ public interface ActionRepository extends BaseEntityRepository<Action, Long>, Jp
* list of id of {@link RolloutGroup} * list of id of {@link RolloutGroup}
* @return list of objects with status and target count * @return list of objects with status and target count
*/ */
@Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus(a.rolloutGroup.id, a.status , COUNT(a.target)) FROM Action a WHERE a.rolloutGroup.id IN ?1 GROUP BY a.rolloutGroup.id, a.status") @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus(a.rolloutGroup.id, a.status , COUNT(a.target)) FROM JpaAction a WHERE a.rolloutGroup.id IN ?1 GROUP BY a.rolloutGroup.id, a.status")
List<TotalTargetCountActionStatus> getStatusCountByRolloutGroupId(List<Long> rolloutGroupId); List<TotalTargetCountActionStatus> getStatusCountByRolloutGroupId(List<Long> rolloutGroupId);
} }

View File

@@ -8,6 +8,8 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
@@ -25,7 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface ActionStatusRepository public interface ActionStatusRepository
extends BaseEntityRepository<ActionStatus, Long>, JpaSpecificationExecutor<ActionStatus> { extends BaseEntityRepository<JpaActionStatus, Long>, JpaSpecificationExecutor<JpaActionStatus> {
/** /**
* Counts {@link ActionStatus} entries of given {@link Action} in * Counts {@link ActionStatus} entries of given {@link Action} in
@@ -35,7 +37,7 @@ public interface ActionStatusRepository
* to count status entries * to count status entries
* @return number of actions in repository * @return number of actions in repository
*/ */
Long countByAction(Action action); Long countByAction(JpaAction action);
/** /**
* Counts {@link ActionStatus} entries of given {@link Action} with given * Counts {@link ActionStatus} entries of given {@link Action} with given
@@ -47,7 +49,7 @@ public interface ActionStatusRepository
* to filter for * to filter for
* @return number of actions in repository * @return number of actions in repository
*/ */
Long countByActionAndStatus(Action action, Status status); Long countByActionAndStatus(JpaAction action, Status status);
/** /**
* Retrieves all {@link ActionStatus} entries from repository of given * Retrieves all {@link ActionStatus} entries from repository of given
@@ -59,7 +61,7 @@ public interface ActionStatusRepository
* of the status entries * of the status entries
* @return pages list of {@link ActionStatus} entries * @return pages list of {@link ActionStatus} entries
*/ */
Page<ActionStatus> findByAction(Pageable pageReq, Action action); Page<ActionStatus> findByAction(Pageable pageReq, JpaAction action);
/** /**
* Finds all status updates for the defined action and target including * Finds all status updates for the defined action and target including
@@ -74,6 +76,6 @@ public interface ActionStatusRepository
* @return Page with found targets * @return Page with found targets
*/ */
@EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD) @EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD)
Page<ActionStatus> getByAction(Pageable pageReq, Action action); Page<ActionStatus> getByAction(Pageable pageReq, JpaAction action);
} }

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa;
import java.io.Serializable; import java.io.Serializable;
import org.eclipse.hawkbit.repository.jpa.model.JpaTenantAwareBaseEntity;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.repository.NoRepositoryBean; import org.springframework.data.repository.NoRepositoryBean;
@@ -27,7 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@NoRepositoryBean @NoRepositoryBean
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface BaseEntityRepository<T extends TenantAwareBaseEntity, I extends Serializable> public interface BaseEntityRepository<T extends JpaTenantAwareBaseEntity, I extends Serializable>
extends PagingAndSortingRepository<T, I> { extends PagingAndSortingRepository<T, I> {
/** /**

View File

@@ -15,10 +15,11 @@ import javax.persistence.EntityManager;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
/** /**
@@ -48,10 +49,10 @@ public final class DeploymentHelper {
* *
* @return updated target * @return updated target
*/ */
static Target updateTargetInfo(@NotNull final Target target, @NotNull final TargetUpdateStatus status, static JpaTarget updateTargetInfo(@NotNull final JpaTarget target, @NotNull final TargetUpdateStatus status,
final boolean setInstalledDate, final TargetInfoRepository targetInfoRepository, final boolean setInstalledDate, final TargetInfoRepository targetInfoRepository,
final EntityManager entityManager) { final EntityManager entityManager) {
final TargetInfo ts = target.getTargetInfo(); final JpaTargetInfo ts = (JpaTargetInfo) target.getTargetInfo();
ts.setUpdateStatus(status); ts.setUpdateStatus(status);
if (setInstalledDate) { if (setInstalledDate) {
@@ -77,7 +78,7 @@ public final class DeploymentHelper {
* @param targetInfoRepository * @param targetInfoRepository
* for the operation * for the operation
*/ */
static void successCancellation(final Action action, final ActionRepository actionRepository, static void successCancellation(final JpaAction action, final ActionRepository actionRepository,
final TargetManagement targetManagement, final TargetInfoRepository targetInfoRepository, final TargetManagement targetManagement, final TargetInfoRepository targetInfoRepository,
final EntityManager entityManager) { final EntityManager entityManager) {
@@ -85,7 +86,7 @@ public final class DeploymentHelper {
action.setActive(false); action.setActive(false);
action.setStatus(Status.CANCELED); action.setStatus(Status.CANCELED);
final Target target = action.getTarget(); final JpaTarget target = (JpaTarget) action.getTarget();
final List<Action> nextActiveActions = actionRepository.findByTargetAndActiveOrderByIdAsc(target, true).stream() final List<Action> nextActiveActions = actionRepository.findByTargetAndActiveOrderByIdAsc(target, true).stream()
.filter(a -> !a.getId().equals(action.getId())).collect(Collectors.toList()); .filter(a -> !a.getId().equals(action.getId())).collect(Collectors.toList());

View File

@@ -8,8 +8,9 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DsMetadataCompositeKey;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
@@ -17,13 +18,10 @@ import org.springframework.transaction.annotation.Transactional;
/** /**
* {@link DistributionSetMetadata} repository. * {@link DistributionSetMetadata} repository.
*
*
*
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface DistributionSetMetadataRepository public interface DistributionSetMetadataRepository
extends PagingAndSortingRepository<DistributionSetMetadata, DsMetadataCompositeKey>, extends PagingAndSortingRepository<JpaDistributionSetMetadata, DsMetadataCompositeKey>,
JpaSpecificationExecutor<DistributionSetMetadata> { JpaSpecificationExecutor<JpaDistributionSetMetadata> {
} }

View File

@@ -11,10 +11,12 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Tag;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -30,7 +32,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface DistributionSetRepository public interface DistributionSetRepository
extends BaseEntityRepository<DistributionSet, Long>, JpaSpecificationExecutor<DistributionSet> { extends BaseEntityRepository<JpaDistributionSet, Long>, JpaSpecificationExecutor<JpaDistributionSet> {
/** /**
* Finds {@link DistributionSet}s by assigned {@link Tag}. * Finds {@link DistributionSet}s by assigned {@link Tag}.
@@ -39,8 +41,8 @@ public interface DistributionSetRepository
* to be found * to be found
* @return list of found {@link DistributionSet}s * @return list of found {@link DistributionSet}s
*/ */
@Query(value = "Select Distinct ds from DistributionSet ds join ds.tags dst where dst = :tag") @Query(value = "Select Distinct ds from JpaDistributionSet ds join ds.tags dst where dst = :tag")
List<DistributionSet> findByTag(@Param("tag") final DistributionSetTag tag); List<JpaDistributionSet> findByTag(@Param("tag") final JpaDistributionSetTag tag);
/** /**
* deletes the {@link DistributionSet}s with the given IDs. * deletes the {@link DistributionSet}s with the given IDs.
@@ -50,9 +52,12 @@ public interface DistributionSetRepository
*/ */
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Query("update DistributionSet d set d.deleted = 1 where d.id in :ids") @Query("update JpaDistributionSet d set d.deleted = 1 where d.id in :ids")
void deleteDistributionSet(@Param("ids") Long... ids); void deleteDistributionSet(@Param("ids") Long... ids);
@Override
List<JpaDistributionSet> findAll(Iterable<Long> ids);
/** /**
* deletes {@link DistributionSet}s by the given IDs. * deletes {@link DistributionSet}s by the given IDs.
* *
@@ -63,7 +68,7 @@ public interface DistributionSetRepository
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
// Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477
@Query("DELETE FROM DistributionSet d WHERE d.id IN ?1") @Query("DELETE FROM JpaDistributionSet d WHERE d.id IN ?1")
int deleteByIdIn(Collection<Long> ids); int deleteByIdIn(Collection<Long> ids);
/** /**
@@ -74,7 +79,7 @@ public interface DistributionSetRepository
* to search for * to search for
* @return {@link List} of found {@link DistributionSet}s * @return {@link List} of found {@link DistributionSet}s
*/ */
List<DistributionSet> findByModules(SoftwareModule module); List<DistributionSet> findByModules(JpaSoftwareModule module);
/** /**
* Finds {@link DistributionSet}s based on given ID if they are not assigned * Finds {@link DistributionSet}s based on given ID if they are not assigned
@@ -84,7 +89,7 @@ public interface DistributionSetRepository
* to search for * to search for
* @return * @return
*/ */
@Query("select ac.distributionSet.id from Action ac where ac.distributionSet.id in :ids") @Query("select ac.distributionSet.id from JpaAction ac where ac.distributionSet.id in :ids")
List<Long> findAssignedDistributionSetsById(@Param("ids") Long... ids); List<Long> findAssignedDistributionSetsById(@Param("ids") Long... ids);
/** /**
@@ -98,7 +103,7 @@ public interface DistributionSetRepository
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable) * @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
*/ */
@Override @Override
<S extends DistributionSet> List<S> save(Iterable<S> entities); <S extends JpaDistributionSet> List<S> save(Iterable<S> entities);
/** /**
* Finds the distribution set for a specific action. * Finds the distribution set for a specific action.
@@ -107,8 +112,8 @@ public interface DistributionSetRepository
* the action associated with the distribution set to find * the action associated with the distribution set to find
* @return the distribution set associated with the given action * @return the distribution set associated with the given action
*/ */
@Query("select DISTINCT d from DistributionSet d join fetch d.modules m join d.actions a where a = :action") @Query("select DISTINCT d from JpaDistributionSet d join fetch d.modules m join d.actions a where a = :action")
DistributionSet findByAction(@Param("action") Action action); JpaDistributionSet findByAction(@Param("action") JpaAction action);
/** /**
* Counts {@link DistributionSet} instances of given type in the repository. * Counts {@link DistributionSet} instances of given type in the repository.
@@ -117,7 +122,7 @@ public interface DistributionSetRepository
* to search for * to search for
* @return number of found {@link DistributionSet}s * @return number of found {@link DistributionSet}s
*/ */
long countByType(DistributionSetType type); long countByType(JpaDistributionSetType type);
/** /**
* Counts {@link DistributionSet} with given * Counts {@link DistributionSet} with given

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
@@ -24,7 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface DistributionSetTagRepository public interface DistributionSetTagRepository
extends BaseEntityRepository<DistributionSetTag, Long>, JpaSpecificationExecutor<DistributionSetTag> { extends BaseEntityRepository<JpaDistributionSetTag, Long>, JpaSpecificationExecutor<JpaDistributionSetTag> {
/** /**
* deletes the {@link DistributionSet} with the given name. * deletes the {@link DistributionSet} with the given name.
* *
@@ -43,7 +44,7 @@ public interface DistributionSetTagRepository
* to filter on * to filter on
* @return the {@link DistributionSetTag} if found, otherwise null * @return the {@link DistributionSetTag} if found, otherwise null
*/ */
DistributionSetTag findByNameEquals(final String tagName); JpaDistributionSetTag findByNameEquals(final String tagName);
/** /**
* Returns all instances of the type. * Returns all instances of the type.
@@ -51,8 +52,8 @@ public interface DistributionSetTagRepository
* @return all entities * @return all entities
*/ */
@Override @Override
List<DistributionSetTag> findAll(); List<JpaDistributionSetTag> findAll();
@Override @Override
<S extends DistributionSetTag> List<S> save(Iterable<S> entities); <S extends JpaDistributionSetTag> List<S> save(Iterable<S> entities);
} }

View File

@@ -8,8 +8,9 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -23,7 +24,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface DistributionSetTypeRepository public interface DistributionSetTypeRepository
extends BaseEntityRepository<DistributionSetType, Long>, JpaSpecificationExecutor<DistributionSetType> { extends BaseEntityRepository<JpaDistributionSetType, Long>, JpaSpecificationExecutor<JpaDistributionSetType> {
/** /**
* *
@@ -34,7 +35,7 @@ public interface DistributionSetTypeRepository
* <code>false</code> if undeleted ones * <code>false</code> if undeleted ones
* @return list of found {@link DistributionSetType}s * @return list of found {@link DistributionSetType}s
*/ */
Page<DistributionSetType> findByDeleted(Pageable pageable, boolean isDeleted); Page<JpaDistributionSetType> findByDeleted(Pageable pageable, boolean isDeleted);
/** /**
* @param isDeleted * @param isDeleted
@@ -54,5 +55,5 @@ public interface DistributionSetTypeRepository
* @return the number of {@link DistributionSetType}s in the repository * @return the number of {@link DistributionSetType}s in the repository
* assigned to the given software module type * assigned to the given software module type
*/ */
Long countByElementsSmType(SoftwareModuleType softwareModuleType); Long countByElementsSmType(JpaSoftwareModuleType softwareModuleType);
} }

View File

@@ -14,7 +14,7 @@ import java.util.List;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.Query; import javax.persistence.Query;
import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
@@ -40,7 +40,7 @@ public class EclipseLinkTargetInfoRepository implements TargetInfoRepository {
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void setTargetUpdateStatus(final TargetUpdateStatus status, final List<Long> targets) { public void setTargetUpdateStatus(final TargetUpdateStatus status, final List<Long> targets) {
final Query query = entityManager.createQuery( final Query query = entityManager.createQuery(
"update TargetInfo ti set ti.updateStatus = :status where ti.targetId in :targets and ti.updateStatus != :status"); "update JpaTargetInfo ti set ti.updateStatus = :status where ti.targetId in :targets and ti.updateStatus != :status");
query.setParameter("targets", targets); query.setParameter("targets", targets);
query.setParameter("status", status); query.setParameter("status", status);
@@ -50,7 +50,7 @@ public class EclipseLinkTargetInfoRepository implements TargetInfoRepository {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@CacheEvict(value = { "targetStatus", "distributionUsageInstalled", "targetsLastPoll" }, allEntries = true) @CacheEvict(value = { "targetStatus", "distributionUsageInstalled", "targetsLastPoll" }, allEntries = true)
public <S extends TargetInfo> S save(final S entity) { public <S extends JpaTargetInfo> S save(final S entity) {
if (entity.isNew()) { if (entity.isNew()) {
entityManager.persist(entity); entityManager.persist(entity);
@@ -66,7 +66,7 @@ public class EclipseLinkTargetInfoRepository implements TargetInfoRepository {
@CacheEvict(value = { "targetStatus", "distributionUsageInstalled", "targetsLastPoll" }, allEntries = true) @CacheEvict(value = { "targetStatus", "distributionUsageInstalled", "targetsLastPoll" }, allEntries = true)
public void deleteByTargetIdIn(final Collection<Long> targetIDs) { public void deleteByTargetIdIn(final Collection<Long> targetIDs) {
final javax.persistence.Query query = entityManager final javax.persistence.Query query = entityManager
.createQuery("DELETE FROM TargetInfo ti where ti.targetId IN :target"); .createQuery("DELETE FROM JpaTargetInfo ti where ti.targetId IN :target");
query.setParameter("target", targetIDs); query.setParameter("target", targetIDs);
} }

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import org.eclipse.hawkbit.repository.jpa.model.JpaExternalArtifactProvider;
import org.eclipse.hawkbit.repository.model.ExternalArtifactProvider; import org.eclipse.hawkbit.repository.model.ExternalArtifactProvider;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -17,6 +18,6 @@ import org.springframework.transaction.annotation.Transactional;
* *
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface ExternalArtifactProviderRepository extends BaseEntityRepository<ExternalArtifactProvider, Long> { public interface ExternalArtifactProviderRepository extends BaseEntityRepository<JpaExternalArtifactProvider, Long> {
} }

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import org.eclipse.hawkbit.repository.jpa.model.JpaExternalArtifact;
import org.eclipse.hawkbit.repository.model.ExternalArtifact; import org.eclipse.hawkbit.repository.model.ExternalArtifact;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@@ -19,7 +20,7 @@ import org.springframework.transaction.annotation.Transactional;
* *
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface ExternalArtifactRepository extends BaseEntityRepository<ExternalArtifact, Long> { public interface ExternalArtifactRepository extends BaseEntityRepository<JpaExternalArtifact, Long> {
/** /**
* Searches for external artifact for a base software module. * Searches for external artifact for a base software module.
@@ -31,6 +32,6 @@ public interface ExternalArtifactRepository extends BaseEntityRepository<Externa
* *
* @return Page<ExternalArtifact> * @return Page<ExternalArtifact>
*/ */
Page<ExternalArtifact> findBySoftwareModuleId(Pageable pageReq, final Long swId); Page<JpaExternalArtifact> findBySoftwareModuleId(Pageable pageReq, final Long swId);
} }

View File

@@ -24,12 +24,16 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.GridFSDBFileNotFoundException; import org.eclipse.hawkbit.repository.exception.GridFSDBFileNotFoundException;
import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException; import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException;
import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException; import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException;
import org.eclipse.hawkbit.repository.jpa.model.JpaExternalArtifact;
import org.eclipse.hawkbit.repository.jpa.model.JpaExternalArtifactProvider;
import org.eclipse.hawkbit.repository.jpa.model.JpaLocalArtifact;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.ExternalArtifact; import org.eclipse.hawkbit.repository.model.ExternalArtifact;
import org.eclipse.hawkbit.repository.model.ExternalArtifactProvider; import org.eclipse.hawkbit.repository.model.ExternalArtifactProvider;
import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.specifications.SoftwareModuleSpecification;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -88,7 +92,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
final String urlSuffix, final Long moduleId) { final String urlSuffix, final Long moduleId) {
final SoftwareModule module = getModuleAndThrowExceptionIfThatFails(moduleId); final SoftwareModule module = getModuleAndThrowExceptionIfThatFails(moduleId);
return externalArtifactRepository.save(new ExternalArtifact(externalRepository, urlSuffix, module)); return externalArtifactRepository.save(new JpaExternalArtifact(externalRepository, urlSuffix, module));
} }
@Override @Override
@@ -97,7 +101,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
public ExternalArtifactProvider createExternalArtifactProvider(final String name, final String description, public ExternalArtifactProvider createExternalArtifactProvider(final String name, final String description,
final String basePath, final String defaultUrlSuffix) { final String basePath, final String defaultUrlSuffix) {
return externalArtifactProviderRepository return externalArtifactProviderRepository
.save(new ExternalArtifactProvider(name, description, basePath, defaultUrlSuffix)); .save(new JpaExternalArtifactProvider(name, description, basePath, defaultUrlSuffix));
} }
@Override @Override
@@ -142,7 +146,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
} }
existing.getSoftwareModule().removeArtifact(existing); existing.getSoftwareModule().removeArtifact(existing);
softwareModuleRepository.save(existing.getSoftwareModule()); softwareModuleRepository.save((JpaSoftwareModule) existing.getSoftwareModule());
externalArtifactRepository.delete(id); externalArtifactRepository.delete(id);
} }
@@ -156,7 +160,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
boolean artifactIsOnlyUsedByOneSoftwareModule = true; boolean artifactIsOnlyUsedByOneSoftwareModule = true;
for (final LocalArtifact lArtifact : localArtifactRepository for (final LocalArtifact lArtifact : localArtifactRepository
.findByGridFsFileName(existing.getGridFsFileName())) { .findByGridFsFileName(((JpaLocalArtifact) existing).getGridFsFileName())) {
if (!lArtifact.getSoftwareModule().isDeleted() if (!lArtifact.getSoftwareModule().isDeleted()
&& Long.compare(lArtifact.getSoftwareModule().getId(), existing.getSoftwareModule().getId()) != 0) { && Long.compare(lArtifact.getSoftwareModule().getId(), existing.getSoftwareModule().getId()) != 0) {
artifactIsOnlyUsedByOneSoftwareModule = false; artifactIsOnlyUsedByOneSoftwareModule = false;
@@ -166,8 +170,8 @@ public class JpaArtifactManagement implements ArtifactManagement {
if (artifactIsOnlyUsedByOneSoftwareModule) { if (artifactIsOnlyUsedByOneSoftwareModule) {
try { try {
LOG.debug("deleting artifact from repository {}", existing.getGridFsFileName()); LOG.debug("deleting artifact from repository {}", ((JpaLocalArtifact) existing).getGridFsFileName());
artifactRepository.deleteBySha1(existing.getGridFsFileName()); artifactRepository.deleteBySha1(((JpaLocalArtifact) existing).getGridFsFileName());
} catch (final ArtifactStoreException e) { } catch (final ArtifactStoreException e) {
throw new ArtifactDeleteFailedException(e); throw new ArtifactDeleteFailedException(e);
} }
@@ -178,7 +182,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void deleteLocalArtifact(final Long id) { public void deleteLocalArtifact(final Long id) {
final LocalArtifact existing = localArtifactRepository.findOne(id); final JpaLocalArtifact existing = localArtifactRepository.findOne(id);
if (null == existing) { if (null == existing) {
return; return;
@@ -187,7 +191,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
deleteLocalArtifact(existing); deleteLocalArtifact(existing);
existing.getSoftwareModule().removeArtifact(existing); existing.getSoftwareModule().removeArtifact(existing);
softwareModuleRepository.save(existing.getSoftwareModule()); softwareModuleRepository.save((JpaSoftwareModule) existing.getSoftwareModule());
localArtifactRepository.delete(id); localArtifactRepository.delete(id);
} }
@@ -219,7 +223,7 @@ public class JpaArtifactManagement implements ArtifactManagement {
@Override @Override
public SoftwareModule findSoftwareModuleById(final Long id) { public SoftwareModule findSoftwareModuleById(final Long id) {
final Specification<SoftwareModule> spec = SoftwareModuleSpecification.byId(id); final Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.byId(id);
return softwareModuleRepository.findOne(spec); return softwareModuleRepository.findOne(spec);
} }
@@ -246,9 +250,10 @@ public class JpaArtifactManagement implements ArtifactManagement {
@Override @Override
public DbArtifact loadLocalArtifactBinary(final LocalArtifact artifact) { public DbArtifact loadLocalArtifactBinary(final LocalArtifact artifact) {
final DbArtifact result = artifactRepository.getArtifactBySha1(artifact.getGridFsFileName()); final DbArtifact result = artifactRepository
.getArtifactBySha1(((JpaLocalArtifact) artifact).getGridFsFileName());
if (result == null) { if (result == null) {
throw new GridFSDBFileNotFoundException(artifact.getGridFsFileName()); throw new GridFSDBFileNotFoundException(((JpaLocalArtifact) artifact).getGridFsFileName());
} }
return result; return result;
@@ -256,9 +261,9 @@ public class JpaArtifactManagement implements ArtifactManagement {
private LocalArtifact storeArtifactMetadata(final SoftwareModule softwareModule, final String providedFilename, private LocalArtifact storeArtifactMetadata(final SoftwareModule softwareModule, final String providedFilename,
final DbArtifact result, final LocalArtifact existing) { final DbArtifact result, final LocalArtifact existing) {
LocalArtifact artifact = existing; JpaLocalArtifact artifact = (JpaLocalArtifact) existing;
if (existing == null) { if (existing == null) {
artifact = new LocalArtifact(result.getHashes().getSha1(), providedFilename, softwareModule); artifact = new JpaLocalArtifact(result.getHashes().getSha1(), providedFilename, softwareModule);
} }
artifact.setMd5Hash(result.getHashes().getMd5()); artifact.setMd5Hash(result.getHashes().getMd5());
artifact.setSha1Hash(result.getHashes().getSha1()); artifact.setSha1Hash(result.getHashes().getSha1());

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -24,19 +25,25 @@ import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException; import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException;
import org.eclipse.hawkbit.repository.exception.ToManyStatusEntriesException; import org.eclipse.hawkbit.repository.exception.ToManyStatusEntriesException;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus_;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.ActionStatus_;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.Target_;
import org.eclipse.hawkbit.repository.model.TenantConfiguration; import org.eclipse.hawkbit.repository.model.TenantConfiguration;
import org.eclipse.hawkbit.repository.specifications.ActionSpecifications;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -46,6 +53,7 @@ import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -116,7 +124,8 @@ public class JpaControllerManagement implements ControllerManagement {
@Override @Override
public Action getActionForDownloadByTargetAndSoftwareModule(final String controllerId, public Action getActionForDownloadByTargetAndSoftwareModule(final String controllerId,
final SoftwareModule module) { final SoftwareModule module) {
final List<Action> action = actionRepository.findActionByTargetAndSoftwareModule(controllerId, module); final List<Action> action = actionRepository.findActionByTargetAndSoftwareModule(controllerId,
(JpaSoftwareModule) module);
if (action.isEmpty() || action.get(0).isCancelingOrCanceled()) { if (action.isEmpty() || action.get(0).isCancelingOrCanceled()) {
throw new EntityNotFoundException( throw new EntityNotFoundException(
@@ -137,12 +146,12 @@ public class JpaControllerManagement implements ControllerManagement {
@Override @Override
public List<Action> findActionByTargetAndActive(final Target target) { public List<Action> findActionByTargetAndActive(final Target target) {
return actionRepository.findByTargetAndActiveOrderByIdAsc(target, true); return actionRepository.findByTargetAndActiveOrderByIdAsc((JpaTarget) target, true);
} }
@Override @Override
public List<SoftwareModule> findSoftwareModulesByDistributionSet(final DistributionSet distributionSet) { public List<SoftwareModule> findSoftwareModulesByDistributionSet(final DistributionSet distributionSet) {
return softwareModuleRepository.findByAssignedTo(distributionSet); return new ArrayList<>(softwareModuleRepository.findByAssignedTo((JpaDistributionSet) distributionSet));
} }
@Override @Override
@@ -154,13 +163,13 @@ public class JpaControllerManagement implements ControllerManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public Target findOrRegisterTargetIfItDoesNotexist(final String controllerId, final URI address) { public Target findOrRegisterTargetIfItDoesNotexist(final String controllerId, final URI address) {
final Specification<Target> spec = (targetRoot, query, cb) -> cb.equal(targetRoot.get(Target_.controllerId), final Specification<JpaTarget> spec = (targetRoot, query, cb) -> cb
controllerId); .equal(targetRoot.get(JpaTarget_.controllerId), controllerId);
Target target = targetRepository.findOne(spec); JpaTarget target = targetRepository.findOne(spec);
if (target == null) { if (target == null) {
target = new Target(controllerId); target = new JpaTarget(controllerId);
target.setDescription("Plug and Play target: " + controllerId); target.setDescription("Plug and Play target: " + controllerId);
target.setName(controllerId); target.setName(controllerId);
return targetManagement.createTarget(target, TargetUpdateStatus.REGISTERED, System.currentTimeMillis(), return targetManagement.createTarget(target, TargetUpdateStatus.REGISTERED, System.currentTimeMillis(),
@@ -175,7 +184,7 @@ public class JpaControllerManagement implements ControllerManagement {
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public TargetInfo updateTargetStatus(final TargetInfo targetInfo, final TargetUpdateStatus status, public TargetInfo updateTargetStatus(final TargetInfo targetInfo, final TargetUpdateStatus status,
final Long lastTargetQuery, final URI address) { final Long lastTargetQuery, final URI address) {
final TargetInfo mtargetInfo = entityManager.merge(targetInfo); final JpaTargetInfo mtargetInfo = (JpaTargetInfo) entityManager.merge(targetInfo);
if (status != null) { if (status != null) {
mtargetInfo.setUpdateStatus(status); mtargetInfo.setUpdateStatus(status);
} }
@@ -192,7 +201,7 @@ public class JpaControllerManagement implements ControllerManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public Action addCancelActionStatus(final ActionStatus actionStatus) { public Action addCancelActionStatus(final ActionStatus actionStatus) {
final Action action = actionStatus.getAction(); final JpaAction action = (JpaAction) actionStatus.getAction();
checkForToManyStatusEntries(action); checkForToManyStatusEntries(action);
action.setStatus(actionStatus.getStatus()); action.setStatus(actionStatus.getStatus());
@@ -217,7 +226,7 @@ public class JpaControllerManagement implements ControllerManagement {
default: default:
} }
actionRepository.save(action); actionRepository.save(action);
actionStatusRepository.save(actionStatus); actionStatusRepository.save((JpaActionStatus) actionStatus);
return action; return action;
} }
@@ -226,14 +235,14 @@ public class JpaControllerManagement implements ControllerManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public Action addUpdateActionStatus(@NotNull final ActionStatus actionStatus) { public Action addUpdateActionStatus(@NotNull final ActionStatus actionStatus) {
final Action action = actionStatus.getAction(); final JpaAction action = (JpaAction) actionStatus.getAction();
if (!action.isActive()) { if (!action.isActive()) {
LOG.debug("Update of actionStatus {} for action {} not possible since action not active anymore.", LOG.debug("Update of actionStatus {} for action {} not possible since action not active anymore.",
actionStatus.getId(), action.getId()); actionStatus.getId(), action.getId());
return action; return action;
} }
return handleAddUpdateActionStatus(actionStatus, action); return handleAddUpdateActionStatus((JpaActionStatus) actionStatus, action);
} }
/** /**
@@ -243,11 +252,11 @@ public class JpaControllerManagement implements ControllerManagement {
* @param action * @param action
* @return * @return
*/ */
private Action handleAddUpdateActionStatus(final ActionStatus actionStatus, final Action action) { private Action handleAddUpdateActionStatus(final JpaActionStatus actionStatus, final JpaAction action) {
LOG.debug("addUpdateActionStatus for action {}", action.getId()); LOG.debug("addUpdateActionStatus for action {}", action.getId());
final Action mergedAction = entityManager.merge(action); final JpaAction mergedAction = entityManager.merge(action);
Target mergedTarget = mergedAction.getTarget(); JpaTarget mergedTarget = (JpaTarget) mergedAction.getTarget();
// check for a potential DOS attack // check for a potential DOS attack
checkForToManyStatusEntries(action); checkForToManyStatusEntries(action);
@@ -284,7 +293,7 @@ public class JpaControllerManagement implements ControllerManagement {
targetManagement.updateTarget(mergedTarget); targetManagement.updateTarget(mergedTarget);
} }
private void checkForToManyStatusEntries(final Action action) { private void checkForToManyStatusEntries(final JpaAction action) {
if (securityProperties.getDos().getMaxStatusEntriesPerAction() > 0) { if (securityProperties.getDos().getMaxStatusEntriesPerAction() > 0) {
final Long statusCount = actionStatusRepository.countByAction(action); final Long statusCount = actionStatusRepository.countByAction(action);
@@ -299,11 +308,11 @@ public class JpaControllerManagement implements ControllerManagement {
} }
} }
private void handleFinishedAndStoreInTargetStatus(final Target target, final Action action) { private void handleFinishedAndStoreInTargetStatus(final JpaTarget target, final JpaAction action) {
action.setActive(false); action.setActive(false);
action.setStatus(Status.FINISHED); action.setStatus(Status.FINISHED);
final TargetInfo targetInfo = target.getTargetInfo(); final JpaTargetInfo targetInfo = (JpaTargetInfo) target.getTargetInfo();
final DistributionSet ds = entityManager.merge(action.getDistributionSet()); final JpaDistributionSet ds = (JpaDistributionSet) entityManager.merge(action.getDistributionSet());
targetInfo.setInstalledDistributionSet(ds); targetInfo.setInstalledDistributionSet(ds);
if (target.getAssignedDistributionSet() != null && targetInfo.getInstalledDistributionSet() != null && target if (target.getAssignedDistributionSet() != null && targetInfo.getInstalledDistributionSet() != null && target
.getAssignedDistributionSet().getId().equals(targetInfo.getInstalledDistributionSet().getId())) { .getAssignedDistributionSet().getId().equals(targetInfo.getInstalledDistributionSet().getId())) {
@@ -321,15 +330,16 @@ public class JpaControllerManagement implements ControllerManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public Target updateControllerAttributes(final String controllerId, final Map<String, String> data) { public Target updateControllerAttributes(final String controllerId, final Map<String, String> data) {
final Target target = targetRepository.findByControllerId(controllerId); final JpaTarget target = targetRepository.findByControllerId(controllerId);
if (target == null) { if (target == null) {
throw new EntityNotFoundException(controllerId); throw new EntityNotFoundException(controllerId);
} }
target.getTargetInfo().getControllerAttributes().putAll(data); final JpaTargetInfo targetInfo = (JpaTargetInfo) target.getTargetInfo();
targetInfo.getControllerAttributes().putAll(data);
if (target.getTargetInfo().getControllerAttributes().size() > securityProperties.getDos() if (targetInfo.getControllerAttributes().size() > securityProperties.getDos()
.getMaxAttributeEntriesPerTarget()) { .getMaxAttributeEntriesPerTarget()) {
LOG_DOS.info("Target tries to insert more than the allowed number of entries ({}). DOS attack anticipated!", LOG_DOS.info("Target tries to insert more than the allowed number of entries ({}). DOS attack anticipated!",
securityProperties.getDos().getMaxAttributeEntriesPerTarget()); securityProperties.getDos().getMaxAttributeEntriesPerTarget());
@@ -337,8 +347,8 @@ public class JpaControllerManagement implements ControllerManagement {
String.valueOf(securityProperties.getDos().getMaxAttributeEntriesPerTarget())); String.valueOf(securityProperties.getDos().getMaxAttributeEntriesPerTarget()));
} }
target.getTargetInfo().setLastTargetQuery(System.currentTimeMillis()); targetInfo.setLastTargetQuery(System.currentTimeMillis());
target.getTargetInfo().setRequestControllerAttributes(false); targetInfo.setRequestControllerAttributes(false);
return targetRepository.save(target); return targetRepository.save(target);
} }
@@ -346,7 +356,7 @@ public class JpaControllerManagement implements ControllerManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public Action registerRetrieved(final Action action, final String message) { public Action registerRetrieved(final Action action, final String message) {
return handleRegisterRetrieved(action, message); return handleRegisterRetrieved((JpaAction) action, message);
} }
/** /**
@@ -360,7 +370,7 @@ public class JpaControllerManagement implements ControllerManagement {
* @return the updated action in case the status has been changed to * @return the updated action in case the status has been changed to
* {@link Status#RETRIEVED} * {@link Status#RETRIEVED}
*/ */
private Action handleRegisterRetrieved(final Action action, final String message) { private Action handleRegisterRetrieved(final JpaAction action, final String message) {
// do a manual query with CriteriaBuilder to avoid unnecessary field // do a manual query with CriteriaBuilder to avoid unnecessary field
// queries and an extra // queries and an extra
// count query made by spring-data when using pageable requests, we // count query made by spring-data when using pageable requests, we
@@ -369,11 +379,11 @@ public class JpaControllerManagement implements ControllerManagement {
// or not. // or not.
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Object[]> queryActionStatus = cb.createQuery(Object[].class); final CriteriaQuery<Object[]> queryActionStatus = cb.createQuery(Object[].class);
final Root<ActionStatus> actionStatusRoot = queryActionStatus.from(ActionStatus.class); final Root<JpaActionStatus> actionStatusRoot = queryActionStatus.from(JpaActionStatus.class);
final CriteriaQuery<Object[]> query = queryActionStatus final CriteriaQuery<Object[]> query = queryActionStatus
.multiselect(actionStatusRoot.get(ActionStatus_.id), actionStatusRoot.get(ActionStatus_.status)) .multiselect(actionStatusRoot.get(JpaActionStatus_.id), actionStatusRoot.get(JpaActionStatus_.status))
.where(cb.equal(actionStatusRoot.get(ActionStatus_.action), action)) .where(cb.equal(actionStatusRoot.get(JpaActionStatus_.action), action))
.orderBy(cb.desc(actionStatusRoot.get(ActionStatus_.id))); .orderBy(cb.desc(actionStatusRoot.get(JpaActionStatus_.id)));
final List<Object[]> resultList = entityManager.createQuery(query).setFirstResult(0).setMaxResults(1) final List<Object[]> resultList = entityManager.createQuery(query).setFirstResult(0).setMaxResults(1)
.getResultList(); .getResultList();
@@ -387,14 +397,14 @@ public class JpaControllerManagement implements ControllerManagement {
if (resultList.isEmpty() || resultList.get(0)[1] != Status.RETRIEVED) { if (resultList.isEmpty() || resultList.get(0)[1] != Status.RETRIEVED) {
// document that the status has been retrieved // document that the status has been retrieved
actionStatusRepository actionStatusRepository
.save(new ActionStatus(action, Status.RETRIEVED, System.currentTimeMillis(), message)); .save(new JpaActionStatus(action, Status.RETRIEVED, System.currentTimeMillis(), message));
// don't change the action status itself in case the action is in // don't change the action status itself in case the action is in
// canceling state otherwise // canceling state otherwise
// we modify the action status and the controller won't get the // we modify the action status and the controller won't get the
// cancel job anymore. // cancel job anymore.
if (!action.isCancelingOrCanceled()) { if (!action.isCancelingOrCanceled()) {
final Action actionMerge = entityManager.merge(action); final JpaAction actionMerge = entityManager.merge(action);
actionMerge.setStatus(Status.RETRIEVED); actionMerge.setStatus(Status.RETRIEVED);
return actionRepository.save(actionMerge); return actionRepository.save(actionMerge);
} }
@@ -406,7 +416,7 @@ public class JpaControllerManagement implements ControllerManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void addInformationalActionStatus(final ActionStatus statusMessage) { public void addInformationalActionStatus(final ActionStatus statusMessage) {
actionStatusRepository.save(statusMessage); actionStatusRepository.save((JpaActionStatus) statusMessage);
} }
@Override @Override
@@ -421,4 +431,10 @@ public class JpaControllerManagement implements ControllerManagement {
public TargetInfo updateLastTargetQuery(final TargetInfo target, final URI address) { public TargetInfo updateLastTargetQuery(final TargetInfo target, final URI address) {
return updateTargetStatus(target, null, System.currentTimeMillis(), address); return updateTargetStatus(target, null, System.currentTimeMillis(), address);
} }
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public ActionStatus generateActionStatus() {
return new JpaActionStatus();
}
} }

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -32,6 +33,7 @@ import org.eclipse.hawkbit.eventbus.event.CancelTargetAssignmentEvent;
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent; import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent; import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent;
import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.repository.ActionFields;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.DistributionSetAssignmentResult; import org.eclipse.hawkbit.repository.DistributionSetAssignmentResult;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
@@ -39,24 +41,32 @@ import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.ForceQuitActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.ForceQuitActionNotAllowedException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.ActionWithStatusCount; import org.eclipse.hawkbit.repository.model.ActionWithStatusCount;
import org.eclipse.hawkbit.repository.model.Action_;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.DistributionSet_;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.Rollout_;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -64,12 +74,14 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.AuditorAware;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -126,7 +138,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
public DistributionSetAssignmentResult assignDistributionSet(final DistributionSet pset, public DistributionSetAssignmentResult assignDistributionSet(final DistributionSet pset,
final List<Target> targets) { final List<Target> targets) {
return assignDistributionSetByTargetId(pset, return assignDistributionSetByTargetId((JpaDistributionSet) pset,
targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList()), targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList()),
ActionType.FORCED, Action.NO_FORCE_TIME); ActionType.FORCED, Action.NO_FORCE_TIME);
@@ -159,7 +171,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
@CacheEvict(value = { "distributionUsageAssigned" }, allEntries = true) @CacheEvict(value = { "distributionUsageAssigned" }, allEntries = true)
public DistributionSetAssignmentResult assignDistributionSet(final Long dsID, public DistributionSetAssignmentResult assignDistributionSet(final Long dsID,
final Collection<TargetWithActionType> targets) { final Collection<TargetWithActionType> targets) {
final DistributionSet set = distributoinSetRepository.findOne(dsID); final JpaDistributionSet set = distributoinSetRepository.findOne(dsID);
if (set == null) { if (set == null) {
throw new EntityNotFoundException( throw new EntityNotFoundException(
String.format("no %s with id %d found", DistributionSet.class.getSimpleName(), dsID)); String.format("no %s with id %d found", DistributionSet.class.getSimpleName(), dsID));
@@ -174,13 +186,13 @@ public class JpaDeploymentManagement implements DeploymentManagement {
@CacheEvict(value = { "distributionUsageAssigned" }, allEntries = true) @CacheEvict(value = { "distributionUsageAssigned" }, allEntries = true)
public DistributionSetAssignmentResult assignDistributionSet(final Long dsID, public DistributionSetAssignmentResult assignDistributionSet(final Long dsID,
final Collection<TargetWithActionType> targets, final Rollout rollout, final RolloutGroup rolloutGroup) { final Collection<TargetWithActionType> targets, final Rollout rollout, final RolloutGroup rolloutGroup) {
final DistributionSet set = distributoinSetRepository.findOne(dsID); final JpaDistributionSet set = distributoinSetRepository.findOne(dsID);
if (set == null) { if (set == null) {
throw new EntityNotFoundException( throw new EntityNotFoundException(
String.format("no %s with id %d found", DistributionSet.class.getSimpleName(), dsID)); String.format("no %s with id %d found", DistributionSet.class.getSimpleName(), dsID));
} }
return assignDistributionSetToTargets(set, targets, rollout, rolloutGroup); return assignDistributionSetToTargets(set, targets, (JpaRollout) rollout, (JpaRolloutGroup) rolloutGroup);
} }
/** /**
@@ -201,9 +213,9 @@ public class JpaDeploymentManagement implements DeploymentManagement {
* {@link SoftwareModuleType} are not assigned as define by the * {@link SoftwareModuleType} are not assigned as define by the
* {@link DistributionSetType}. * {@link DistributionSetType}.
*/ */
private DistributionSetAssignmentResult assignDistributionSetToTargets(@NotNull final DistributionSet set, private DistributionSetAssignmentResult assignDistributionSetToTargets(@NotNull final JpaDistributionSet set,
final Collection<TargetWithActionType> targetsWithActionType, final Rollout rollout, final Collection<TargetWithActionType> targetsWithActionType, final JpaRollout rollout,
final RolloutGroup rolloutGroup) { final JpaRolloutGroup rolloutGroup) {
if (!set.isComplete()) { if (!set.isComplete()) {
throw new IncompleteDistributionSetException( throw new IncompleteDistributionSetException(
@@ -223,7 +235,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
// maximum 1000 elements, so we need to split the entries here and // maximum 1000 elements, so we need to split the entries here and
// execute multiple statements we take the target only into account if // execute multiple statements we take the target only into account if
// the requested operation is no duplicate of a previous one // the requested operation is no duplicate of a previous one
final List<Target> targets = Lists.partition(controllerIDs, Constants.MAX_ENTRIES_IN_STATEMENT).stream() final List<JpaTarget> targets = Lists.partition(controllerIDs, Constants.MAX_ENTRIES_IN_STATEMENT).stream()
.map(ids -> targetRepository .map(ids -> targetRepository
.findAll(TargetSpecifications.hasControllerIdAndAssignedDistributionSetIdNot(ids, set.getId()))) .findAll(TargetSpecifications.hasControllerIdAndAssignedDistributionSetIdNot(ids, set.getId())))
.flatMap(t -> t.stream()).collect(Collectors.toList()); .flatMap(t -> t.stream()).collect(Collectors.toList());
@@ -262,7 +274,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
targetIds.forEach(tIds -> targetRepository.setAssignedDistributionSet(set, System.currentTimeMillis(), targetIds.forEach(tIds -> targetRepository.setAssignedDistributionSet(set, System.currentTimeMillis(),
currentUser, tIds)); currentUser, tIds));
targetIds.forEach(tIds -> targetInfoRepository.setTargetUpdateStatus(TargetUpdateStatus.PENDING, tIds)); targetIds.forEach(tIds -> targetInfoRepository.setTargetUpdateStatus(TargetUpdateStatus.PENDING, tIds));
final Map<String, Action> targetIdsToActions = actionRepository final Map<String, JpaAction> targetIdsToActions = actionRepository
.save(targets.stream().map(t -> createTargetAction(targetsWithActionMap, t, set, rollout, rolloutGroup)) .save(targets.stream().map(t -> createTargetAction(targetsWithActionMap, t, set, rollout, rolloutGroup))
.collect(Collectors.toList())) .collect(Collectors.toList()))
.stream().collect(Collectors.toMap(a -> a.getTarget().getControllerId(), Function.identity())); .stream().collect(Collectors.toMap(a -> a.getTarget().getControllerId(), Function.identity()));
@@ -272,7 +284,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
// of the action itself and with this action status we have a nicer // of the action itself and with this action status we have a nicer
// action history. // action history.
targetIdsToActions.values().forEach(action -> { targetIdsToActions.values().forEach(action -> {
final ActionStatus actionStatus = new ActionStatus(); final JpaActionStatus actionStatus = new JpaActionStatus();
actionStatus.setAction(action); actionStatus.setAction(action);
actionStatus.setOccurredAt(action.getCreatedAt()); actionStatus.setOccurredAt(action.getCreatedAt());
actionStatus.setStatus(Status.RUNNING); actionStatus.setStatus(Status.RUNNING);
@@ -289,7 +301,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
LOG.debug("assignDistribution({}) finished {}", set, result); LOG.debug("assignDistribution({}) finished {}", set, result);
final List<SoftwareModule> softwareModules = softwareModuleRepository.findByAssignedTo(set); final List<JpaSoftwareModule> softwareModules = softwareModuleRepository.findByAssignedTo(set);
// detaching as it is not necessary to persist the set itself // detaching as it is not necessary to persist the set itself
entityManager.detach(set); entityManager.detach(set);
@@ -299,16 +311,17 @@ public class JpaDeploymentManagement implements DeploymentManagement {
return result; return result;
} }
private void sendDistributionSetAssignmentEvent(final List<Target> targets, final Set<Long> targetIdsCancellList, private void sendDistributionSetAssignmentEvent(final List<JpaTarget> targets, final Set<Long> targetIdsCancellList,
final Map<String, Action> targetIdsToActions, final List<SoftwareModule> softwareModules) { final Map<String, JpaAction> targetIdsToActions, final List<JpaSoftwareModule> softwareModules) {
targets.stream().filter(t -> !!!targetIdsCancellList.contains(t.getId())) targets.stream().filter(t -> !!!targetIdsCancellList.contains(t.getId()))
.forEach(t -> assignDistributionSetEvent(t, targetIdsToActions.get(t.getControllerId()).getId(), .forEach(t -> assignDistributionSetEvent(t, targetIdsToActions.get(t.getControllerId()).getId(),
softwareModules)); softwareModules));
} }
private static Action createTargetAction(final Map<String, TargetWithActionType> targetsWithActionMap, private static JpaAction createTargetAction(final Map<String, TargetWithActionType> targetsWithActionMap,
final Target target, final DistributionSet set, final Rollout rollout, final RolloutGroup rolloutGroup) { final JpaTarget target, final JpaDistributionSet set, final JpaRollout rollout,
final Action actionForTarget = new Action(); final JpaRolloutGroup rolloutGroup) {
final JpaAction actionForTarget = new JpaAction();
final TargetWithActionType targetWithActionType = targetsWithActionMap.get(target.getControllerId()); final TargetWithActionType targetWithActionType = targetsWithActionMap.get(target.getControllerId());
actionForTarget.setActionType(targetWithActionType.getActionType()); actionForTarget.setActionType(targetWithActionType.getActionType());
actionForTarget.setForcedTime(targetWithActionType.getForceTime()); actionForTarget.setForcedTime(targetWithActionType.getForceTime());
@@ -332,9 +345,12 @@ public class JpaDeploymentManagement implements DeploymentManagement {
* @param softwareModules * @param softwareModules
* the software modules which have been assigned * the software modules which have been assigned
*/ */
private void assignDistributionSetEvent(final Target target, final Long actionId, private void assignDistributionSetEvent(final JpaTarget target, final Long actionId,
final List<SoftwareModule> softwareModules) { final List<JpaSoftwareModule> modules) {
target.getTargetInfo().setUpdateStatus(TargetUpdateStatus.PENDING); ((JpaTargetInfo) target.getTargetInfo()).setUpdateStatus(TargetUpdateStatus.PENDING);
@SuppressWarnings({ "unchecked", "rawtypes" })
final Collection<SoftwareModule> softwareModules = (Collection) modules;
afterCommit.afterCommit(() -> { afterCommit.afterCommit(() -> {
eventBus.post(new TargetInfoUpdateEvent(target.getTargetInfo())); eventBus.post(new TargetInfoUpdateEvent(target.getTargetInfo()));
eventBus.post(new TargetAssignDistributionSetEvent(target.getOptLockRevision(), target.getTenant(), eventBus.post(new TargetAssignDistributionSetEvent(target.getOptLockRevision(), target.getTenant(),
@@ -357,14 +373,14 @@ public class JpaDeploymentManagement implements DeploymentManagement {
// Figure out if there are potential target/action combinations that // Figure out if there are potential target/action combinations that
// need to be considered // need to be considered
// for cancelation // for cancelation
final List<Action> activeActions = actionRepository final List<JpaAction> activeActions = actionRepository
.findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetRequiredMigrationStep(targetsIds, .findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetRequiredMigrationStep(targetsIds,
Action.Status.CANCELING); Action.Status.CANCELING);
activeActions.forEach(action -> { activeActions.forEach(action -> {
action.setStatus(Status.CANCELING); action.setStatus(Status.CANCELING);
// document that the status has been retrieved // document that the status has been retrieved
actionStatusRepository.save(new ActionStatus(action, Status.CANCELING, System.currentTimeMillis(), actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELING, System.currentTimeMillis(),
"manual cancelation requested")); "manual cancelation requested"));
cancelAssignDistributionSetEvent(action.getTarget(), action.getId()); cancelAssignDistributionSetEvent(action.getTarget(), action.getId());
@@ -378,7 +394,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
} }
private DistributionSetAssignmentResult assignDistributionSetByTargetId(@NotNull final DistributionSet set, private DistributionSetAssignmentResult assignDistributionSetByTargetId(@NotNull final JpaDistributionSet set,
@NotEmpty final List<String> tIDs, final ActionType actionType, final long forcedTime) { @NotEmpty final List<String> tIDs, final ActionType actionType, final long forcedTime) {
return assignDistributionSetToTargets(set, tIDs.stream() return assignDistributionSetToTargets(set, tIDs.stream()
@@ -394,14 +410,14 @@ public class JpaDeploymentManagement implements DeploymentManagement {
if (action.isCancelingOrCanceled()) { if (action.isCancelingOrCanceled()) {
throw new CancelActionNotAllowedException("Actions in canceling or canceled state cannot be canceled"); throw new CancelActionNotAllowedException("Actions in canceling or canceled state cannot be canceled");
} }
final Action myAction = entityManager.merge(action); final JpaAction myAction = (JpaAction) entityManager.merge(action);
if (myAction.isActive()) { if (myAction.isActive()) {
LOG.debug("action ({}) was still active. Change to {}.", action, Status.CANCELING); LOG.debug("action ({}) was still active. Change to {}.", action, Status.CANCELING);
myAction.setStatus(Status.CANCELING); myAction.setStatus(Status.CANCELING);
// document that the status has been retrieved // document that the status has been retrieved
actionStatusRepository.save(new ActionStatus(myAction, Status.CANCELING, System.currentTimeMillis(), actionStatusRepository.save(new JpaActionStatus(myAction, Status.CANCELING, System.currentTimeMillis(),
"manual cancelation requested")); "manual cancelation requested"));
final Action saveAction = actionRepository.save(myAction); final Action saveAction = actionRepository.save(myAction);
cancelAssignDistributionSetEvent(target, myAction.getId()); cancelAssignDistributionSetEvent(target, myAction.getId());
@@ -431,7 +447,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)
public Action forceQuitAction(final Action action) { public Action forceQuitAction(final Action action) {
final Action mergedAction = entityManager.merge(action); final JpaAction mergedAction = (JpaAction) entityManager.merge(action);
if (!mergedAction.isCancelingOrCanceled()) { if (!mergedAction.isCancelingOrCanceled()) {
throw new ForceQuitActionNotAllowedException( throw new ForceQuitActionNotAllowedException(
@@ -446,7 +462,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
LOG.warn("action ({}) was still activ and has been force quite.", action); LOG.warn("action ({}) was still activ and has been force quite.", action);
// document that the status has been retrieved // document that the status has been retrieved
actionStatusRepository.save(new ActionStatus(mergedAction, Status.CANCELED, System.currentTimeMillis(), actionStatusRepository.save(new JpaActionStatus(mergedAction, Status.CANCELED, System.currentTimeMillis(),
"A force quit has been performed.")); "A force quit has been performed."));
DeploymentHelper.successCancellation(mergedAction, actionRepository, targetManagement, targetInfoRepository, DeploymentHelper.successCancellation(mergedAction, actionRepository, targetManagement, targetInfoRepository,
@@ -468,7 +484,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
final List<Long> targetIds = targets.stream().map(t -> t.getId()).collect(Collectors.toList()); final List<Long> targetIds = targets.stream().map(t -> t.getId()).collect(Collectors.toList());
actionRepository.switchStatus(Action.Status.CANCELED, targetIds, false, Action.Status.SCHEDULED); actionRepository.switchStatus(Action.Status.CANCELED, targetIds, false, Action.Status.SCHEDULED);
targets.forEach(target -> { targets.forEach(target -> {
final Action action = new Action(); final JpaAction action = new JpaAction();
action.setTarget(target); action.setTarget(target);
action.setActive(false); action.setActive(false);
action.setDistributionSet(distributionSet); action.setDistributionSet(distributionSet);
@@ -486,8 +502,8 @@ public class JpaDeploymentManagement implements DeploymentManagement {
@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)
public Action startScheduledAction(final Action action) { public Action startScheduledAction(final Action action) {
final Action mergedAction = entityManager.merge(action); final JpaAction mergedAction = (JpaAction) entityManager.merge(action);
final Target mergedTarget = entityManager.merge(action.getTarget()); final JpaTarget mergedTarget = (JpaTarget) entityManager.merge(action.getTarget());
// check if we need to override running update actions // check if we need to override running update actions
final Set<Long> overrideObsoleteUpdateActions = overrideObsoleteUpdateActions( final Set<Long> overrideObsoleteUpdateActions = overrideObsoleteUpdateActions(
@@ -509,14 +525,14 @@ public class JpaDeploymentManagement implements DeploymentManagement {
mergedAction.setStatus(Status.RUNNING); mergedAction.setStatus(Status.RUNNING);
final Action savedAction = actionRepository.save(mergedAction); final Action savedAction = actionRepository.save(mergedAction);
final ActionStatus actionStatus = new ActionStatus(); final JpaActionStatus actionStatus = new JpaActionStatus();
actionStatus.setAction(action); actionStatus.setAction(action);
actionStatus.setOccurredAt(action.getCreatedAt()); actionStatus.setOccurredAt(action.getCreatedAt());
actionStatus.setStatus(Status.RUNNING); actionStatus.setStatus(Status.RUNNING);
actionStatusRepository.save(actionStatus); actionStatusRepository.save(actionStatus);
mergedTarget.setAssignedDistributionSet(action.getDistributionSet()); mergedTarget.setAssignedDistributionSet(action.getDistributionSet());
final TargetInfo targetInfo = mergedTarget.getTargetInfo(); final JpaTargetInfo targetInfo = (JpaTargetInfo) mergedTarget.getTargetInfo();
targetInfo.setUpdateStatus(TargetUpdateStatus.PENDING); targetInfo.setUpdateStatus(TargetUpdateStatus.PENDING);
targetRepository.save(mergedTarget); targetRepository.save(mergedTarget);
targetInfoRepository.save(targetInfo); targetInfoRepository.save(targetInfo);
@@ -524,11 +540,11 @@ public class JpaDeploymentManagement implements DeploymentManagement {
// in case we canceled an action before for this target, then don't fire // in case we canceled an action before for this target, then don't fire
// assignment event // assignment event
if (!overrideObsoleteUpdateActions.contains(savedAction.getId())) { if (!overrideObsoleteUpdateActions.contains(savedAction.getId())) {
final List<SoftwareModule> softwareModules = softwareModuleRepository final List<JpaSoftwareModule> softwareModules = softwareModuleRepository
.findByAssignedTo(action.getDistributionSet()); .findByAssignedTo((JpaDistributionSet) action.getDistributionSet());
// send distribution set assignment event // send distribution set assignment event
assignDistributionSetEvent(mergedAction.getTarget(), mergedAction.getId(), softwareModules); assignDistributionSetEvent((JpaTarget) mergedAction.getTarget(), mergedAction.getId(), softwareModules);
} }
return savedAction; return savedAction;
} }
@@ -545,84 +561,93 @@ public class JpaDeploymentManagement implements DeploymentManagement {
@Override @Override
public Slice<Action> findActionsByTarget(final Pageable pageable, final Target target) { public Slice<Action> findActionsByTarget(final Pageable pageable, final Target target) {
return actionRepository.findByTarget(pageable, target); return actionRepository.findByTarget(pageable, (JpaTarget) target);
} }
@Override @Override
public List<Action> findActionsByTarget(final Target target) { public List<Action> findActionsByTarget(final Target target) {
return actionRepository.findByTarget(target); return actionRepository.findByTarget((JpaTarget) target);
} }
@Override @Override
public List<ActionWithStatusCount> findActionsWithStatusCountByTargetOrderByIdDesc(final Target target) { public List<ActionWithStatusCount> findActionsWithStatusCountByTargetOrderByIdDesc(final Target target) {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<ActionWithStatusCount> query = cb.createQuery(ActionWithStatusCount.class); final CriteriaQuery<ActionWithStatusCount> query = cb.createQuery(ActionWithStatusCount.class);
final Root<Action> actionRoot = query.from(Action.class); final Root<JpaAction> actionRoot = query.from(JpaAction.class);
final ListJoin<Action, ActionStatus> actionStatusJoin = actionRoot.join(Action_.actionStatus, JoinType.LEFT); final ListJoin<JpaAction, JpaActionStatus> actionStatusJoin = actionRoot.join(JpaAction_.actionStatus,
final Join<Action, DistributionSet> actionDsJoin = actionRoot.join(Action_.distributionSet); JoinType.LEFT);
final Join<Action, Rollout> actionRolloutJoin = actionRoot.join(Action_.rollout, JoinType.LEFT); final Join<JpaAction, JpaDistributionSet> actionDsJoin = actionRoot.join(JpaAction_.distributionSet);
final Join<JpaAction, JpaRollout> actionRolloutJoin = actionRoot.join(JpaAction_.rollout, JoinType.LEFT);
final CriteriaQuery<ActionWithStatusCount> multiselect = query.distinct(true).multiselect( final CriteriaQuery<ActionWithStatusCount> multiselect = query.distinct(true).multiselect(
actionRoot.get(Action_.id), actionRoot.get(Action_.actionType), actionRoot.get(Action_.active), actionRoot.get(JpaAction_.id), actionRoot.get(JpaAction_.actionType), actionRoot.get(JpaAction_.active),
actionRoot.get(Action_.forcedTime), actionRoot.get(Action_.status), actionRoot.get(Action_.createdAt), actionRoot.get(JpaAction_.forcedTime), actionRoot.get(JpaAction_.status),
actionRoot.get(Action_.lastModifiedAt), actionDsJoin.get(DistributionSet_.id), actionRoot.get(JpaAction_.createdAt), actionRoot.get(JpaAction_.lastModifiedAt),
actionDsJoin.get(DistributionSet_.name), actionDsJoin.get(DistributionSet_.version), actionDsJoin.get(JpaDistributionSet_.id), actionDsJoin.get(JpaDistributionSet_.name),
cb.count(actionStatusJoin), actionRolloutJoin.get(Rollout_.name)); actionDsJoin.get(JpaDistributionSet_.version), cb.count(actionStatusJoin),
multiselect.where(cb.equal(actionRoot.get(Action_.target), target)); actionRolloutJoin.get(JpaRollout_.name));
multiselect.orderBy(cb.desc(actionRoot.get(Action_.id))); multiselect.where(cb.equal(actionRoot.get(JpaAction_.target), target));
multiselect.groupBy(actionRoot.get(Action_.id)); multiselect.orderBy(cb.desc(actionRoot.get(JpaAction_.id)));
multiselect.groupBy(actionRoot.get(JpaAction_.id));
return entityManager.createQuery(multiselect).getResultList(); return entityManager.createQuery(multiselect).getResultList();
} }
@Override @Override
public Slice<Action> findActionsByTarget(final Specification<Action> specifiction, final Target target, public Page<Action> findActionsByTarget(final String rsqlParam, final Target target, final Pageable pageable) {
final Pageable pageable) { final Specification<JpaAction> specification = RSQLUtility.parse(rsqlParam, ActionFields.class);
return actionRepository.findAll((Specification<Action>) (root, query, cb) -> cb return convertAcPage(actionRepository.findAll((Specification<JpaAction>) (root, query, cb) -> cb
.and(specifiction.toPredicate(root, query, cb), cb.equal(root.get(Action_.target), target)), pageable); .and(specification.toPredicate(root, query, cb), cb.equal(root.get(JpaAction_.target), target)),
pageable));
}
private static Page<Action> convertAcPage(final Page<JpaAction> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
@Override @Override
public Slice<Action> findActionsByTarget(final Target foundTarget, final Pageable pageable) { public Slice<Action> findActionsByTarget(final Target foundTarget, final Pageable pageable) {
return actionRepository.findByTarget(pageable, foundTarget); return actionRepository.findByTarget(pageable, (JpaTarget) foundTarget);
} }
@Override @Override
public Page<Action> findActiveActionsByTarget(final Pageable pageable, final Target target) { public Page<Action> findActiveActionsByTarget(final Pageable pageable, final Target target) {
return actionRepository.findByActiveAndTarget(pageable, target, true); return actionRepository.findByActiveAndTarget(pageable, (JpaTarget) target, true);
} }
@Override @Override
public List<Action> findActiveActionsByTarget(final Target target) { public List<Action> findActiveActionsByTarget(final Target target) {
return actionRepository.findByActiveAndTarget(target, true); return actionRepository.findByActiveAndTarget((JpaTarget) target, true);
} }
@Override @Override
public List<Action> findInActiveActionsByTarget(final Target target) { public List<Action> findInActiveActionsByTarget(final Target target) {
return actionRepository.findByActiveAndTarget(target, false); return actionRepository.findByActiveAndTarget((JpaTarget) target, false);
} }
@Override @Override
public Page<Action> findInActiveActionsByTarget(final Pageable pageable, final Target target) { public Page<Action> findInActiveActionsByTarget(final Pageable pageable, final Target target) {
return actionRepository.findByActiveAndTarget(pageable, target, false); return actionRepository.findByActiveAndTarget(pageable, (JpaTarget) target, false);
} }
@Override @Override
public Long countActionsByTarget(final Target target) { public Long countActionsByTarget(final Target target) {
return actionRepository.countByTarget(target); return actionRepository.countByTarget((JpaTarget) target);
} }
@Override @Override
public Long countActionsByTarget(final Specification<Action> spec, final Target target) { public Long countActionsByTarget(final String rsqlParam, final Target target) {
final Specification<JpaAction> spec = RSQLUtility.parse(rsqlParam, ActionFields.class);
return actionRepository.count((root, query, cb) -> cb.and(spec.toPredicate(root, query, cb), return actionRepository.count((root, query, cb) -> cb.and(spec.toPredicate(root, query, cb),
cb.equal(root.get(Action_.target), target))); cb.equal(root.get(JpaAction_.target), target)));
} }
@Override @Override
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public Action forceTargetAction(final Long actionId) { public Action forceTargetAction(final Long actionId) {
final Action action = actionRepository.findOne(actionId); final JpaAction action = actionRepository.findOne(actionId);
if (action != null && !action.isForced()) { if (action != null && !action.isForced()) {
action.setActionType(ActionType.FORCED); action.setActionType(ActionType.FORCED);
return actionRepository.save(action); return actionRepository.save(action);
@@ -634,20 +659,27 @@ public class JpaDeploymentManagement implements DeploymentManagement {
public Page<ActionStatus> findActionStatusByAction(final Pageable pageReq, final Action action, public Page<ActionStatus> findActionStatusByAction(final Pageable pageReq, final Action action,
final boolean withMessages) { final boolean withMessages) {
if (withMessages) { if (withMessages) {
return actionStatusRepository.getByAction(pageReq, action); return actionStatusRepository.getByAction(pageReq, (JpaAction) action);
} else { } else {
return actionStatusRepository.findByAction(pageReq, action); return actionStatusRepository.findByAction(pageReq, (JpaAction) action);
} }
} }
@Override @Override
public List<Action> findActionsByRolloutGroupParentAndStatus(final Rollout rollout, public List<Action> findActionsByRolloutGroupParentAndStatus(final Rollout rollout,
final RolloutGroup rolloutGroupParent, final Action.Status actionStatus) { final RolloutGroup rolloutGroupParent, final Action.Status actionStatus) {
return actionRepository.findByRolloutAndRolloutGroupParentAndStatus(rollout, rolloutGroupParent, actionStatus); return actionRepository.findByRolloutAndRolloutGroupParentAndStatus((JpaRollout) rollout,
(JpaRolloutGroup) rolloutGroupParent, actionStatus);
} }
@Override @Override
public List<Action> findActionsByRolloutAndStatus(final Rollout rollout, final Action.Status actionStatus) { public List<Action> findActionsByRolloutAndStatus(final Rollout rollout, final Action.Status actionStatus) {
return actionRepository.findByRolloutAndStatus(rollout, actionStatus); return actionRepository.findByRolloutAndStatus((JpaRollout) rollout, actionStatus);
}
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public Action generateAction() {
return new JpaAction();
} }
} }

View File

@@ -24,28 +24,36 @@ import javax.persistence.EntityManager;
import org.eclipse.hawkbit.eventbus.event.DistributionSetTagAssigmentResultEvent; import org.eclipse.hawkbit.eventbus.event.DistributionSetTagAssigmentResultEvent;
import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.repository.DistributionSetFields;
import org.eclipse.hawkbit.repository.DistributionSetFilter; import org.eclipse.hawkbit.repository.DistributionSetFilter;
import org.eclipse.hawkbit.repository.DistributionSetFilter.DistributionSetFilterBuilder; import org.eclipse.hawkbit.repository.DistributionSetFilter.DistributionSetFilterBuilder;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
import org.eclipse.hawkbit.repository.DistributionSetTypeFields;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TagManagement; import org.eclipse.hawkbit.repository.TagManagement;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityLockedException; import org.eclipse.hawkbit.repository.exception.EntityLockedException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata_;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTypeSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata_;
import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.DistributionSet_;
import org.eclipse.hawkbit.repository.model.DsMetadataCompositeKey;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.specifications.DistributionSetSpecification; import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.specifications.DistributionSetTypeSpecification;
import org.eclipse.hawkbit.repository.specifications.SpecificationsBuilder;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
@@ -54,6 +62,7 @@ import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -111,12 +120,12 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public DistributionSetTagAssignmentResult toggleTagAssignment(final Collection<Long> dsIds, final String tagName) { public DistributionSetTagAssignmentResult toggleTagAssignment(final Collection<Long> dsIds, final String tagName) {
final Iterable<DistributionSet> sets = findDistributionSetListWithDetails(dsIds); final List<JpaDistributionSet> sets = findDistributionSetListWithDetails(dsIds);
final DistributionSetTag myTag = tagManagement.findDistributionSetTag(tagName); final DistributionSetTag myTag = tagManagement.findDistributionSetTag(tagName);
DistributionSetTagAssignmentResult result; DistributionSetTagAssignmentResult result;
final List<DistributionSet> toBeChangedDSs = new ArrayList<>(); final List<JpaDistributionSet> toBeChangedDSs = new ArrayList<>();
for (final DistributionSet set : sets) { for (final JpaDistributionSet set : sets) {
if (set.getTags().add(myTag)) { if (set.getTags().add(myTag)) {
toBeChangedDSs.add(set); toBeChangedDSs.add(set);
} }
@@ -124,17 +133,17 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
// un-assignment case // un-assignment case
if (toBeChangedDSs.isEmpty()) { if (toBeChangedDSs.isEmpty()) {
for (final DistributionSet set : sets) { for (final JpaDistributionSet set : sets) {
if (set.getTags().remove(myTag)) { if (set.getTags().remove(myTag)) {
toBeChangedDSs.add(set); toBeChangedDSs.add(set);
} }
} }
result = new DistributionSetTagAssignmentResult(dsIds.size() - toBeChangedDSs.size(), 0, result = new DistributionSetTagAssignmentResult(dsIds.size() - toBeChangedDSs.size(), 0,
toBeChangedDSs.size(), Collections.emptyList(), distributionSetRepository.save(toBeChangedDSs), toBeChangedDSs.size(), Collections.emptyList(),
myTag); new ArrayList<>(distributionSetRepository.save(toBeChangedDSs)), myTag);
} else { } else {
result = new DistributionSetTagAssignmentResult(dsIds.size() - toBeChangedDSs.size(), toBeChangedDSs.size(), result = new DistributionSetTagAssignmentResult(dsIds.size() - toBeChangedDSs.size(), toBeChangedDSs.size(),
0, distributionSetRepository.save(toBeChangedDSs), Collections.emptyList(), myTag); 0, new ArrayList<>(distributionSetRepository.save(toBeChangedDSs)), Collections.emptyList(), myTag);
} }
final DistributionSetTagAssignmentResult resultAssignment = result; final DistributionSetTagAssignmentResult resultAssignment = result;
@@ -145,8 +154,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
return result; return result;
} }
@Override private List<JpaDistributionSet> findDistributionSetListWithDetails(final Collection<Long> distributionIdSet) {
public List<DistributionSet> findDistributionSetListWithDetails(final Collection<Long> distributionIdSet) {
return distributionSetRepository.findAll(DistributionSetSpecification.byIds(distributionIdSet)); return distributionSetRepository.findAll(DistributionSetSpecification.byIds(distributionIdSet));
} }
@@ -156,8 +164,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
public DistributionSet updateDistributionSet(final DistributionSet ds) { public DistributionSet updateDistributionSet(final DistributionSet ds) {
checkNotNull(ds.getId()); checkNotNull(ds.getId());
final DistributionSet persisted = findDistributionSetByIdWithDetails(ds.getId()); final DistributionSet persisted = findDistributionSetByIdWithDetails(ds.getId());
checkDistributionSetSoftwareModulesIsAllowedToModify(ds, persisted.getModules()); checkDistributionSetSoftwareModulesIsAllowedToModify((JpaDistributionSet) ds, persisted.getModules());
return distributionSetRepository.save(ds); return distributionSetRepository.save((JpaDistributionSet) ds);
} }
@Override @Override
@@ -196,7 +204,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
if (dSet.getType() == null) { if (dSet.getType() == null) {
dSet.setType(systemManagement.getTenantMetadata().getDefaultDsType()); dSet.setType(systemManagement.getTenantMetadata().getDefaultDsType());
} }
return distributionSetRepository.save(dSet); return distributionSetRepository.save((JpaDistributionSet) dSet);
} }
private void prepareDsSave(final DistributionSet dSet) { private void prepareDsSave(final DistributionSet dSet) {
@@ -220,18 +228,22 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
ds.setType(systemManagement.getTenantMetadata().getDefaultDsType()); ds.setType(systemManagement.getTenantMetadata().getDefaultDsType());
} }
} }
return distributionSetRepository.save(distributionSets);
@SuppressWarnings({ "unchecked", "rawtypes" })
final Collection<JpaDistributionSet> toSave = (Collection) distributionSets;
return new ArrayList<>(distributionSetRepository.save(toSave));
} }
@Override @Override
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public DistributionSet assignSoftwareModules(final DistributionSet ds, final Set<SoftwareModule> softwareModules) { public DistributionSet assignSoftwareModules(final DistributionSet ds, final Set<SoftwareModule> softwareModules) {
checkDistributionSetSoftwareModulesIsAllowedToModify(ds, softwareModules); checkDistributionSetSoftwareModulesIsAllowedToModify((JpaDistributionSet) ds, softwareModules);
for (final SoftwareModule softwareModule : softwareModules) { for (final SoftwareModule softwareModule : softwareModules) {
ds.addModule(softwareModule); ds.addModule(softwareModule);
} }
return distributionSetRepository.save(ds); return distributionSetRepository.save((JpaDistributionSet) ds);
} }
@Override @Override
@@ -241,8 +253,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
final Set<SoftwareModule> softwareModules = new HashSet<>(); final Set<SoftwareModule> softwareModules = new HashSet<>();
softwareModules.add(softwareModule); softwareModules.add(softwareModule);
ds.removeModule(softwareModule); ds.removeModule(softwareModule);
checkDistributionSetSoftwareModulesIsAllowedToModify(ds, softwareModules); checkDistributionSetSoftwareModulesIsAllowedToModify((JpaDistributionSet) ds, softwareModules);
return distributionSetRepository.save(ds); return distributionSetRepository.save((JpaDistributionSet) ds);
} }
@Override @Override
@@ -251,7 +263,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
public DistributionSetType updateDistributionSetType(final DistributionSetType dsType) { public DistributionSetType updateDistributionSetType(final DistributionSetType dsType) {
checkNotNull(dsType.getId()); checkNotNull(dsType.getId());
final DistributionSetType persisted = distributionSetTypeRepository.findOne(dsType.getId()); final JpaDistributionSetType persisted = distributionSetTypeRepository.findOne(dsType.getId());
// throw exception if user tries to update a DS type that is already in // throw exception if user tries to update a DS type that is already in
// use // use
@@ -261,25 +273,36 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
dsType.getName())); dsType.getName()));
} }
return distributionSetTypeRepository.save(dsType); return distributionSetTypeRepository.save((JpaDistributionSetType) dsType);
} }
@Override @Override
public Page<DistributionSetType> findDistributionSetTypesAll(final Specification<DistributionSetType> spec, public Page<DistributionSetType> findDistributionSetTypesAll(final String rsqlParam, final Pageable pageable) {
final Pageable pageable) { final Specification<JpaDistributionSetType> spec = RSQLUtility.parse(rsqlParam,
return distributionSetTypeRepository.findAll(spec, pageable); DistributionSetTypeFields.class);
return convertDsTPage(distributionSetTypeRepository.findAll(spec, pageable));
}
private static Page<DistributionSetType> convertDsTPage(final Page<JpaDistributionSetType> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
@Override @Override
public Page<DistributionSetType> findDistributionSetTypesAll(final Pageable pageable) { public Page<DistributionSetType> findDistributionSetTypesAll(final Pageable pageable) {
return distributionSetTypeRepository.findByDeleted(pageable, false); return convertDsTPage(distributionSetTypeRepository.findByDeleted(pageable, false));
} }
@Override @Override
public Page<DistributionSet> findDistributionSetsByFilters(final Pageable pageable, public Page<DistributionSet> findDistributionSetsByFilters(final Pageable pageable,
final DistributionSetFilter distributionSetFilter) { final DistributionSetFilter distributionSetFilter) {
final List<Specification<DistributionSet>> specList = buildDistributionSetSpecifications(distributionSetFilter); final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(
return findByCriteriaAPI(pageable, specList); distributionSetFilter);
return convertDsPage(findByCriteriaAPI(pageable, specList));
}
private static Page<DistributionSet> convertDsPage(final Page<JpaDistributionSet> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
/** /**
@@ -291,7 +314,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
*/ */
private DistributionSet findDistributionSetsByFiltersAndInstalledOrAssignedTarget( private DistributionSet findDistributionSetsByFiltersAndInstalledOrAssignedTarget(
final DistributionSetFilter distributionSetFilter) { final DistributionSetFilter distributionSetFilter) {
final List<Specification<DistributionSet>> specList = buildDistributionSetSpecifications(distributionSetFilter); final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(
distributionSetFilter);
if (specList == null || specList.isEmpty()) { if (specList == null || specList.isEmpty()) {
return null; return null;
} }
@@ -301,30 +325,33 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Override @Override
public Page<DistributionSet> findDistributionSetsAll(final Pageable pageReq, final Boolean deleted, public Page<DistributionSet> findDistributionSetsAll(final Pageable pageReq, final Boolean deleted,
final Boolean complete) { final Boolean complete) {
final List<Specification<DistributionSet>> specList = new ArrayList<>(); final List<Specification<JpaDistributionSet>> specList = new ArrayList<>();
if (deleted != null) { if (deleted != null) {
final Specification<DistributionSet> spec = DistributionSetSpecification.isDeleted(deleted); final Specification<JpaDistributionSet> spec = DistributionSetSpecification.isDeleted(deleted);
specList.add(spec); specList.add(spec);
} }
if (complete != null) { if (complete != null) {
final Specification<DistributionSet> spec = DistributionSetSpecification.isCompleted(complete); final Specification<JpaDistributionSet> spec = DistributionSetSpecification.isCompleted(complete);
specList.add(spec); specList.add(spec);
} }
return findByCriteriaAPI(pageReq, specList); return convertDsPage(findByCriteriaAPI(pageReq, specList));
} }
@Override @Override
public Page<DistributionSet> findDistributionSetsAll(final Specification<DistributionSet> spec, public Page<DistributionSet> findDistributionSetsAll(final String rsqlParam, final Pageable pageReq,
final Pageable pageReq, final Boolean deleted) { final Boolean deleted) {
final List<Specification<DistributionSet>> specList = new ArrayList<>();
final Specification<JpaDistributionSet> spec = RSQLUtility.parse(rsqlParam, DistributionSetFields.class);
final List<Specification<JpaDistributionSet>> specList = new ArrayList<>();
if (deleted != null) { if (deleted != null) {
specList.add(DistributionSetSpecification.isDeleted(deleted)); specList.add(DistributionSetSpecification.isDeleted(deleted));
} }
specList.add(spec); specList.add(spec);
return findByCriteriaAPI(pageReq, specList); return convertDsPage(findByCriteriaAPI(pageReq, specList));
} }
@Override @Override
@@ -371,23 +398,23 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Override @Override
public DistributionSet findDistributionSetByNameAndVersion(final String distributionName, final String version) { public DistributionSet findDistributionSetByNameAndVersion(final String distributionName, final String version) {
final Specification<DistributionSet> spec = DistributionSetSpecification final Specification<JpaDistributionSet> spec = DistributionSetSpecification
.equalsNameAndVersionIgnoreCase(distributionName, version); .equalsNameAndVersionIgnoreCase(distributionName, version);
return distributionSetRepository.findOne(spec); return distributionSetRepository.findOne(spec);
} }
@Override @Override
public Iterable<DistributionSet> findDistributionSetList(final Collection<Long> dist) { public List<DistributionSet> findDistributionSetsAll(final Collection<Long> dist) {
return distributionSetRepository.findAll(dist); return new ArrayList<>(distributionSetRepository.findAll(DistributionSetSpecification.byIds(dist)));
} }
@Override @Override
public Long countDistributionSetsAll() { public Long countDistributionSetsAll() {
final List<Specification<DistributionSet>> specList = new ArrayList<>(); final List<Specification<JpaDistributionSet>> specList = new LinkedList<>();
final Specification<DistributionSet> spec = DistributionSetSpecification.isDeleted(Boolean.FALSE); final Specification<JpaDistributionSet> spec = DistributionSetSpecification.isDeleted(Boolean.FALSE);
specList.add(spec); specList.add(spec);
return distributionSetRepository.count(SpecificationsBuilder.combineWithAnd(specList)); return distributionSetRepository.count(SpecificationsBuilder.combineWithAnd(specList));
@@ -421,16 +448,17 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
throw new EntityAlreadyExistsException("Given type contains an Id!"); throw new EntityAlreadyExistsException("Given type contains an Id!");
} }
return distributionSetTypeRepository.save(type); return distributionSetTypeRepository.save((JpaDistributionSetType) type);
} }
@Override @Override
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void deleteDistributionSetType(final DistributionSetType type) { public void deleteDistributionSetType(final DistributionSetType ty) {
final JpaDistributionSetType type = (JpaDistributionSetType) ty;
if (distributionSetRepository.countByType(type) > 0) { if (distributionSetRepository.countByType(type) > 0) {
final DistributionSetType toDelete = entityManager.merge(type); final JpaDistributionSetType toDelete = entityManager.merge(type);
toDelete.setDeleted(true); toDelete.setDeleted(true);
distributionSetTypeRepository.save(toDelete); distributionSetTypeRepository.save(toDelete);
} else { } else {
@@ -441,7 +469,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Override @Override
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public DistributionSetMetadata createDistributionSetMetadata(final DistributionSetMetadata metadata) { public DistributionSetMetadata createDistributionSetMetadata(final DistributionSetMetadata md) {
final JpaDistributionSetMetadata metadata = (JpaDistributionSetMetadata) md;
if (distributionSetMetadataRepository.exists(metadata.getId())) { if (distributionSetMetadataRepository.exists(metadata.getId())) {
throwMetadataKeyAlreadyExists(metadata.getId().getKey()); throwMetadataKeyAlreadyExists(metadata.getId().getKey());
} }
@@ -449,31 +479,38 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
// log written because // log written because
// modifying metadata is modifying the base distribution set itself for // modifying metadata is modifying the base distribution set itself for
// auditing purposes. // auditing purposes.
entityManager.merge(metadata.getDistributionSet()).setLastModifiedAt(0L); entityManager.merge((JpaDistributionSet) metadata.getDistributionSet()).setLastModifiedAt(0L);
return distributionSetMetadataRepository.save(metadata); return distributionSetMetadataRepository.save(metadata);
} }
@Override @Override
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public List<DistributionSetMetadata> createDistributionSetMetadata( public List<DistributionSetMetadata> createDistributionSetMetadata(final Collection<DistributionSetMetadata> md) {
final Collection<DistributionSetMetadata> metadata) {
for (final DistributionSetMetadata distributionSetMetadata : metadata) { @SuppressWarnings({ "rawtypes", "unchecked" })
final Collection<JpaDistributionSetMetadata> metadata = (Collection) md;
for (final JpaDistributionSetMetadata distributionSetMetadata : metadata) {
checkAndThrowAlreadyIfDistributionSetMetadataExists(distributionSetMetadata.getId()); checkAndThrowAlreadyIfDistributionSetMetadataExists(distributionSetMetadata.getId());
} }
metadata.forEach(m -> entityManager.merge(m.getDistributionSet()).setLastModifiedAt(-1L)); metadata.forEach(m -> entityManager.merge((JpaDistributionSet) m.getDistributionSet()).setLastModifiedAt(0L));
return (List<DistributionSetMetadata>) distributionSetMetadataRepository.save(metadata);
return new ArrayList<DistributionSetMetadata>(
(Collection<? extends DistributionSetMetadata>) distributionSetMetadataRepository.save(metadata));
} }
@Override @Override
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public DistributionSetMetadata updateDistributionSetMetadata(final DistributionSetMetadata metadata) { public DistributionSetMetadata updateDistributionSetMetadata(final DistributionSetMetadata md) {
final JpaDistributionSetMetadata metadata = (JpaDistributionSetMetadata) md;
// check if exists otherwise throw entity not found exception // check if exists otherwise throw entity not found exception
findOne(metadata.getId()); findOne(metadata.getId());
// touch it to update the lock revision because we are modifying the // touch it to update the lock revision because we are modifying the
// DS indirectly // DS indirectly
entityManager.merge(metadata.getDistributionSet()).setLastModifiedAt(0L); entityManager.merge((JpaDistributionSet) metadata.getDistributionSet()).setLastModifiedAt(0L);
return distributionSetMetadataRepository.save(metadata); return distributionSetMetadataRepository.save(metadata);
} }
@@ -488,23 +525,29 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId, public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
final Pageable pageable) { final Pageable pageable) {
return distributionSetMetadataRepository.findAll( return convertMdPage(distributionSetMetadataRepository
(Specification<DistributionSetMetadata>) (root, query, cb) -> cb.equal( .findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal(
root.get(DistributionSetMetadata_.distributionSet).get(DistributionSet_.id), distributionSetId), root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id),
pageable); distributionSetId), pageable));
} }
@Override @Override
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId, public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
final Specification<DistributionSetMetadata> spec, final Pageable pageable) { final String rsqlParam, final Pageable pageable) {
return distributionSetMetadataRepository
.findAll( final Specification<JpaDistributionSetMetadata> spec = RSQLUtility.parse(rsqlParam,
(Specification<DistributionSetMetadata>) (root, query, DistributionSetMetadataFields.class);
cb) -> cb.and(
cb.equal(root.get(DistributionSetMetadata_.distributionSet) return convertMdPage(
.get(DistributionSet_.id), distributionSetId), distributionSetMetadataRepository
spec.toPredicate(root, query, cb)), .findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.and(
pageable); cb.equal(root.get(JpaDistributionSetMetadata_.distributionSet)
.get(JpaDistributionSet_.id), distributionSetId),
spec.toPredicate(root, query, cb)), pageable));
}
private static Page<DistributionSetMetadata> convertMdPage(final Page<JpaDistributionSetMetadata> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
@Override @Override
@@ -518,19 +561,19 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Override @Override
public DistributionSet findDistributionSetByAction(final Action action) { public DistributionSet findDistributionSetByAction(final Action action) {
return distributionSetRepository.findByAction(action); return distributionSetRepository.findByAction((JpaAction) action);
} }
@Override @Override
public boolean isDistributionSetInUse(final DistributionSet distributionSet) { public boolean isDistributionSetInUse(final DistributionSet distributionSet) {
return actionRepository.countByDistributionSet(distributionSet) > 0; return actionRepository.countByDistributionSet((JpaDistributionSet) distributionSet) > 0;
} }
private static List<Specification<DistributionSet>> buildDistributionSetSpecifications( private static List<Specification<JpaDistributionSet>> buildDistributionSetSpecifications(
final DistributionSetFilter distributionSetFilter) { final DistributionSetFilter distributionSetFilter) {
final List<Specification<DistributionSet>> specList = new ArrayList<>(); final List<Specification<JpaDistributionSet>> specList = new ArrayList<>();
Specification<DistributionSet> spec; Specification<JpaDistributionSet> spec;
if (null != distributionSetFilter.getIsComplete()) { if (null != distributionSetFilter.getIsComplete()) {
spec = DistributionSetSpecification.isCompleted(distributionSetFilter.getIsComplete()); spec = DistributionSetSpecification.isCompleted(distributionSetFilter.getIsComplete());
@@ -568,7 +611,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
return specList; return specList;
} }
private void checkDistributionSetSoftwareModulesIsAllowedToModify(final DistributionSet distributionSet, private void checkDistributionSetSoftwareModulesIsAllowedToModify(final JpaDistributionSet distributionSet,
final Set<SoftwareModule> softwareModules) { final Set<SoftwareModule> softwareModules) {
if (!new HashSet<SoftwareModule>(distributionSet.getModules()).equals(softwareModules) if (!new HashSet<SoftwareModule>(distributionSet.getModules()).equals(softwareModules)
&& actionRepository.countByDistributionSet(distributionSet) > 0) { && actionRepository.countByDistributionSet(distributionSet) > 0) {
@@ -602,8 +645,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
* list of @link {@link Specification} * list of @link {@link Specification}
* @return the page with the found {@link DistributionSet} * @return the page with the found {@link DistributionSet}
*/ */
private Page<DistributionSet> findByCriteriaAPI(final Pageable pageable, private Page<JpaDistributionSet> findByCriteriaAPI(final Pageable pageable,
final List<Specification<DistributionSet>> specList) { final List<Specification<JpaDistributionSet>> specList) {
if (specList == null || specList.isEmpty()) { if (specList == null || specList.isEmpty()) {
return distributionSetRepository.findAll(pageable); return distributionSetRepository.findAll(pageable);
@@ -627,10 +670,11 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public List<DistributionSet> assignTag(final Collection<Long> dsIds, final DistributionSetTag tag) { public List<DistributionSet> assignTag(final Collection<Long> dsIds, final DistributionSetTag tag) {
final List<DistributionSet> allDs = findDistributionSetListWithDetails(dsIds); final List<JpaDistributionSet> allDs = findDistributionSetListWithDetails(dsIds);
allDs.forEach(ds -> ds.getTags().add(tag)); allDs.forEach(ds -> ds.getTags().add(tag));
final List<DistributionSet> save = distributionSetRepository.save(allDs);
final List<DistributionSet> save = new ArrayList<>(distributionSetRepository.save(allDs));
afterCommit.afterCommit(() -> { afterCommit.afterCommit(() -> {
@@ -646,19 +690,23 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public List<DistributionSet> unAssignAllDistributionSetsByTag(final DistributionSetTag tag) { public List<DistributionSet> unAssignAllDistributionSetsByTag(final DistributionSetTag tag) {
return unAssignTag(tag.getAssignedToDistributionSet(), tag);
@SuppressWarnings({ "unchecked", "rawtypes" })
final Collection<JpaDistributionSet> distributionSets = (Collection) tag.getAssignedToDistributionSet();
return new ArrayList<>(unAssignTag(distributionSets, tag));
} }
@Override @Override
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public DistributionSet unAssignTag(final Long dsId, final DistributionSetTag distributionSetTag) { public DistributionSet unAssignTag(final Long dsId, final DistributionSetTag distributionSetTag) {
final List<DistributionSet> allDs = findDistributionSetListWithDetails(Arrays.asList(dsId)); final List<JpaDistributionSet> allDs = findDistributionSetListWithDetails(Arrays.asList(dsId));
final List<DistributionSet> unAssignTag = unAssignTag(allDs, distributionSetTag); final List<JpaDistributionSet> unAssignTag = unAssignTag(allDs, distributionSetTag);
return unAssignTag.isEmpty() ? null : unAssignTag.get(0); return unAssignTag.isEmpty() ? null : unAssignTag.get(0);
} }
private List<DistributionSet> unAssignTag(final Collection<DistributionSet> distributionSets, private List<JpaDistributionSet> unAssignTag(final Collection<JpaDistributionSet> distributionSets,
final DistributionSetTag tag) { final DistributionSetTag tag) {
distributionSets.forEach(ds -> ds.getTags().remove(tag)); distributionSets.forEach(ds -> ds.getTags().remove(tag));
return distributionSetRepository.save(distributionSets); return distributionSetRepository.save(distributionSets);
@@ -685,4 +733,16 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
final DistributionSetTag tag) { final DistributionSetTag tag) {
return toggleTagAssignment(sets.stream().map(ds -> ds.getId()).collect(Collectors.toList()), tag.getName()); return toggleTagAssignment(sets.stream().map(ds -> ds.getId()).collect(Collectors.toList()), tag.getName());
} }
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public DistributionSetType generateDistributionSetType() {
return new JpaDistributionSetType();
}
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public DistributionSet generateDistributionSet() {
return new JpaDistributionSet();
}
} }

View File

@@ -34,13 +34,13 @@ import org.eclipse.hawkbit.report.model.DataReportSeriesItem;
import org.eclipse.hawkbit.report.model.InnerOuterDataReportSeries; import org.eclipse.hawkbit.report.model.InnerOuterDataReportSeries;
import org.eclipse.hawkbit.report.model.SeriesTime; import org.eclipse.hawkbit.report.model.SeriesTime;
import org.eclipse.hawkbit.repository.ReportManagement; import org.eclipse.hawkbit.repository.ReportManagement;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSet_; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.model.TargetInfo_; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.Target_;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@@ -88,13 +88,13 @@ public class JpaReportManagement implements ReportManagement {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class); final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
final Root<Target> targetRoot = query.from(Target.class); final Root<JpaTarget> targetRoot = query.from(JpaTarget.class);
final Join<Target, TargetInfo> targetInfo = targetRoot.join(Target_.targetInfo); final Join<JpaTarget, JpaTargetInfo> targetInfo = targetRoot.join(JpaTarget_.targetInfo);
final Expression<Long> countColumn = cb.count(targetInfo.get(TargetInfo_.targetId)); final Expression<Long> countColumn = cb.count(targetInfo.get(JpaTargetInfo_.targetId));
final CriteriaQuery<Object[]> multiselect = query final CriteriaQuery<Object[]> multiselect = query
.multiselect(targetInfo.get(TargetInfo_.updateStatus), countColumn) .multiselect(targetInfo.get(JpaTargetInfo_.updateStatus), countColumn)
.groupBy(targetInfo.get(TargetInfo_.updateStatus)) .groupBy(targetInfo.get(JpaTargetInfo_.updateStatus))
.orderBy(cb.desc(targetInfo.get(TargetInfo_.updateStatus))); .orderBy(cb.desc(targetInfo.get(JpaTargetInfo_.updateStatus)));
// | col1 | col2 | // | col1 | col2 |
// | U_STATUS | COUNT | // | U_STATUS | COUNT |
@@ -114,16 +114,17 @@ public class JpaReportManagement implements ReportManagement {
// top X entries distribution usage // top X entries distribution usage
final CriteriaBuilder cbTopX = entityManager.getCriteriaBuilder(); final CriteriaBuilder cbTopX = entityManager.getCriteriaBuilder();
final CriteriaQuery<Object[]> queryTopX = cbTopX.createQuery(Object[].class); final CriteriaQuery<Object[]> queryTopX = cbTopX.createQuery(Object[].class);
final Root<DistributionSet> rootTopX = queryTopX.from(DistributionSet.class); final Root<JpaDistributionSet> rootTopX = queryTopX.from(JpaDistributionSet.class);
final ListJoin<DistributionSet, Target> joinTopX = rootTopX.join(DistributionSet_.assignedToTargets, final ListJoin<JpaDistributionSet, JpaTarget> joinTopX = rootTopX.join(JpaDistributionSet_.assignedToTargets,
JoinType.LEFT); JoinType.LEFT);
final Expression<Long> countColumn = cbTopX.count(joinTopX); final Expression<Long> countColumn = cbTopX.count(joinTopX);
// top x usage query // top x usage query
final CriteriaQuery<Object[]> groupBy = queryTopX final CriteriaQuery<Object[]> groupBy = queryTopX
.multiselect(rootTopX.get(DistributionSet_.name), rootTopX.get(DistributionSet_.version), countColumn) .multiselect(rootTopX.get(JpaDistributionSet_.name), rootTopX.get(JpaDistributionSet_.version),
.where(cbTopX.equal(rootTopX.get(DistributionSet_.deleted), false)) countColumn)
.groupBy(rootTopX.get(DistributionSet_.name), rootTopX.get(DistributionSet_.version)) .where(cbTopX.equal(rootTopX.get(JpaDistributionSet_.deleted), false))
.orderBy(cbTopX.desc(countColumn), cbTopX.asc(rootTopX.get(DistributionSet_.name))); .groupBy(rootTopX.get(JpaDistributionSet_.name), rootTopX.get(JpaDistributionSet_.version))
.orderBy(cbTopX.desc(countColumn), cbTopX.asc(rootTopX.get(JpaDistributionSet_.name)));
// | col1 | col2 | col3 | // | col1 | col2 | col3 |
// | NAME | VER | COUNT | // | NAME | VER | COUNT |
final List<Object[]> resultListTop = entityManager.createQuery(groupBy).getResultList(); final List<Object[]> resultListTop = entityManager.createQuery(groupBy).getResultList();
@@ -138,16 +139,17 @@ public class JpaReportManagement implements ReportManagement {
// top X entries distribution usage // top X entries distribution usage
final CriteriaBuilder cbTopX = entityManager.getCriteriaBuilder(); final CriteriaBuilder cbTopX = entityManager.getCriteriaBuilder();
final CriteriaQuery<Object[]> queryTopX = cbTopX.createQuery(Object[].class); final CriteriaQuery<Object[]> queryTopX = cbTopX.createQuery(Object[].class);
final Root<DistributionSet> rootTopX = queryTopX.from(DistributionSet.class); final Root<JpaDistributionSet> rootTopX = queryTopX.from(JpaDistributionSet.class);
final ListJoin<DistributionSet, TargetInfo> joinTopX = rootTopX.join(DistributionSet_.installedAtTargets, final ListJoin<JpaDistributionSet, JpaTargetInfo> joinTopX = rootTopX
JoinType.LEFT); .join(JpaDistributionSet_.installedAtTargets, JoinType.LEFT);
final Expression<Long> countColumn = cbTopX.count(joinTopX); final Expression<Long> countColumn = cbTopX.count(joinTopX);
// top x usage query // top x usage query
final CriteriaQuery<Object[]> groupBy = queryTopX final CriteriaQuery<Object[]> groupBy = queryTopX
.multiselect(rootTopX.get(DistributionSet_.name), rootTopX.get(DistributionSet_.version), countColumn) .multiselect(rootTopX.get(JpaDistributionSet_.name), rootTopX.get(JpaDistributionSet_.version),
.where(cbTopX.equal(rootTopX.get(DistributionSet_.deleted), false)) countColumn)
.groupBy(rootTopX.get(DistributionSet_.name), rootTopX.get(DistributionSet_.version)) .where(cbTopX.equal(rootTopX.get(JpaDistributionSet_.deleted), false))
.orderBy(cbTopX.desc(countColumn), cbTopX.asc(rootTopX.get(DistributionSet_.name))); .groupBy(rootTopX.get(JpaDistributionSet_.name), rootTopX.get(JpaDistributionSet_.version))
.orderBy(cbTopX.desc(countColumn), cbTopX.asc(rootTopX.get(JpaDistributionSet_.name)));
// | col1 | col2 | col3 | // | col1 | col2 | col3 |
// | NAME | VER | COUNT | // | NAME | VER | COUNT |
final List<Object[]> resultListTop = entityManager.createQuery(groupBy).getResultList(); final List<Object[]> resultListTop = entityManager.createQuery(groupBy).getResultList();
@@ -213,6 +215,7 @@ public class JpaReportManagement implements ReportManagement {
final LocalDateTime from, final LocalDateTime to) { final LocalDateTime from, final LocalDateTime to) {
final Query createNativeQuery = entityManager final Query createNativeQuery = entityManager
.createNativeQuery(getFeedbackReceivedQueryTemplate(dateType, from, to)); .createNativeQuery(getFeedbackReceivedQueryTemplate(dateType, from, to));
@SuppressWarnings("unchecked")
final List<Object[]> resultList = createNativeQuery.getResultList(); final List<Object[]> resultList = createNativeQuery.getResultList();
final List<DataReportSeriesItem<T>> reportItems = resultList.stream() final List<DataReportSeriesItem<T>> reportItems = resultList.stream()
@@ -275,15 +278,15 @@ public class JpaReportManagement implements ReportManagement {
// count select statement // count select statement
final CriteriaQuery<Long> countSelect = cb.createQuery(Long.class); final CriteriaQuery<Long> countSelect = cb.createQuery(Long.class);
final Root<Target> countSelectRoot = countSelect.from(Target.class); final Root<JpaTarget> countSelectRoot = countSelect.from(JpaTarget.class);
final Join<Target, TargetInfo> targetInfoJoin = countSelectRoot.join(Target_.targetInfo); final Join<JpaTarget, JpaTargetInfo> targetInfoJoin = countSelectRoot.join(JpaTarget_.targetInfo);
countSelect.select(cb.count(countSelectRoot)); countSelect.select(cb.count(countSelectRoot));
if (start != null && end != null) { if (start != null && end != null) {
countSelect.where(cb.between(targetInfoJoin.get(TargetInfo_.lastTargetQuery), start, end)); countSelect.where(cb.between(targetInfoJoin.get(JpaTargetInfo_.lastTargetQuery), start, end));
} else if (from == null && to != null) { } else if (from == null && to != null) {
countSelect.where(cb.lessThanOrEqualTo(targetInfoJoin.get(TargetInfo_.lastTargetQuery), end)); countSelect.where(cb.lessThanOrEqualTo(targetInfoJoin.get(JpaTargetInfo_.lastTargetQuery), end));
} else { } else {
countSelect.where(cb.isNull(targetInfoJoin.get(TargetInfo_.lastTargetQuery))); countSelect.where(cb.isNull(targetInfoJoin.get(JpaTargetInfo_.lastTargetQuery)));
} }
return countSelect; return countSelect;
} }

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -20,28 +21,36 @@ import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.ListJoin; import javax.persistence.criteria.ListJoin;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import org.eclipse.hawkbit.repository.RolloutGroupFields;
import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutGroupManagement;
import org.eclipse.hawkbit.repository.TargetFields;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout.RolloutStatus;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup;
import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup_;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action_;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.RolloutGroup_;
import org.eclipse.hawkbit.repository.model.RolloutTargetGroup;
import org.eclipse.hawkbit.repository.model.RolloutTargetGroup_;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetWithActionStatus; import org.eclipse.hawkbit.repository.model.TargetWithActionStatus;
import org.eclipse.hawkbit.repository.model.Target_;
import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -72,20 +81,34 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
@Override @Override
public Page<RolloutGroup> findRolloutGroupsByRolloutId(final Long rolloutId, final Pageable page) { public Page<RolloutGroup> findRolloutGroupsByRolloutId(final Long rolloutId, final Pageable page) {
return rolloutGroupRepository.findByRolloutId(rolloutId, page); return convertPage(rolloutGroupRepository.findByRolloutId(rolloutId, page));
}
private static Page<RolloutGroup> convertPage(final Slice<JpaRolloutGroup> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
}
private static Page<Target> convertTPage(final Page<JpaTarget> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
@Override @Override
public Page<RolloutGroup> findRolloutGroupsAll(final Rollout rollout, public Page<RolloutGroup> findRolloutGroupsAll(final Rollout rollout, final String rsqlParam, final Pageable page) {
final Specification<RolloutGroup> specification, final Pageable page) {
return rolloutGroupRepository.findAll((root, query, criteriaBuilder) -> criteriaBuilder.and( final Specification<JpaRolloutGroup> specification = RSQLUtility.parse(rsqlParam, RolloutGroupFields.class);
criteriaBuilder.equal(root.get(RolloutGroup_.rollout), rollout),
specification.toPredicate(root, query, criteriaBuilder)), page); return convertPage(
rolloutGroupRepository
.findAll(
(root, query, criteriaBuilder) -> criteriaBuilder.and(
criteriaBuilder.equal(root.get(JpaRolloutGroup_.rollout), rollout),
specification.toPredicate(root, query, criteriaBuilder)),
page));
} }
@Override @Override
public Page<RolloutGroup> findAllRolloutGroupsWithDetailedStatus(final Long rolloutId, final Pageable page) { public Page<RolloutGroup> findAllRolloutGroupsWithDetailedStatus(final Long rolloutId, final Pageable page) {
final Page<RolloutGroup> rolloutGroups = rolloutGroupRepository.findByRolloutId(rolloutId, page); final Page<JpaRolloutGroup> rolloutGroups = rolloutGroupRepository.findByRolloutId(rolloutId, page);
final List<Long> rolloutGroupIds = rolloutGroups.getContent().stream().map(rollout -> rollout.getId()) final List<Long> rolloutGroupIds = rolloutGroups.getContent().stream().map(rollout -> rollout.getId())
.collect(Collectors.toList()); .collect(Collectors.toList());
final Map<Long, List<TotalTargetCountActionStatus>> allStatesForRollout = getStatusCountItemForRolloutGroup( final Map<Long, List<TotalTargetCountActionStatus>> allStatesForRollout = getStatusCountItemForRolloutGroup(
@@ -97,7 +120,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
rolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus); rolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus);
} }
return rolloutGroups; return convertPage(rolloutGroups);
} }
@Override @Override
@@ -121,13 +144,16 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
} }
@Override @Override
public Page<Target> findRolloutGroupTargets(final RolloutGroup rolloutGroup, public Page<Target> findRolloutGroupTargets(final RolloutGroup rolloutGroup, final String rsqlParam,
final Specification<Target> specification, final Pageable page) { final Pageable page) {
return targetRepository.findAll((root, query, criteriaBuilder) -> {
final ListJoin<Target, RolloutTargetGroup> rolloutTargetJoin = root.join(Target_.rolloutTargetGroup); final Specification<JpaTarget> rsqlSpecification = RSQLUtility.parse(rsqlParam, TargetFields.class);
return criteriaBuilder.and(specification.toPredicate(root, query, criteriaBuilder),
return convertTPage(targetRepository.findAll((root, query, criteriaBuilder) -> {
final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = root.join(JpaTarget_.rolloutTargetGroup);
return criteriaBuilder.and(rsqlSpecification.toPredicate(root, query, criteriaBuilder),
criteriaBuilder.equal(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup), rolloutGroup)); criteriaBuilder.equal(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup), rolloutGroup));
}, page); }, page));
} }
@Override @Override
@@ -138,7 +164,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
// stored in the #TargetRolloutGroup. // stored in the #TargetRolloutGroup.
return targetRepository.findByRolloutTargetGroupRolloutGroupId(rolloutGroup.getId(), page); return targetRepository.findByRolloutTargetGroupRolloutGroupId(rolloutGroup.getId(), page);
} }
return targetRepository.findByActionsRolloutGroup(rolloutGroup, page); return targetRepository.findByActionsRolloutGroup((JpaRolloutGroup) rolloutGroup, page);
} }
private static boolean isRolloutStatusReady(final RolloutGroup rolloutGroup) { private static boolean isRolloutStatusReady(final RolloutGroup rolloutGroup) {
@@ -154,8 +180,8 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
final CriteriaQuery<Long> countQuery = cb.createQuery(Long.class); final CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
final Root<RolloutTargetGroup> targetRoot = query.distinct(true).from(RolloutTargetGroup.class); final Root<RolloutTargetGroup> targetRoot = query.distinct(true).from(RolloutTargetGroup.class);
final Join<RolloutTargetGroup, Target> targetJoin = targetRoot.join(RolloutTargetGroup_.target); final Join<RolloutTargetGroup, JpaTarget> targetJoin = targetRoot.join(RolloutTargetGroup_.target);
final ListJoin<RolloutTargetGroup, Action> actionJoin = targetRoot.join(RolloutTargetGroup_.actions, final ListJoin<RolloutTargetGroup, JpaAction> actionJoin = targetRoot.join(RolloutTargetGroup_.actions,
JoinType.LEFT); JoinType.LEFT);
final Root<RolloutTargetGroup> countQueryFrom = countQuery.distinct(true).from(RolloutTargetGroup.class); final Root<RolloutTargetGroup> countQueryFrom = countQuery.distinct(true).from(RolloutTargetGroup.class);
@@ -165,7 +191,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
.where(cb.equal(countQueryFrom.get(RolloutTargetGroup_.rolloutGroup), rolloutGroup)); .where(cb.equal(countQueryFrom.get(RolloutTargetGroup_.rolloutGroup), rolloutGroup));
final Long totalCount = entityManager.createQuery(countQuery).getSingleResult(); final Long totalCount = entityManager.createQuery(countQuery).getSingleResult();
final CriteriaQuery<Object[]> multiselect = query.multiselect(targetJoin, actionJoin.get(Action_.status)) final CriteriaQuery<Object[]> multiselect = query.multiselect(targetJoin, actionJoin.get(JpaAction_.status))
.where(cb.equal(targetRoot.get(RolloutTargetGroup_.rolloutGroup), rolloutGroup)); .where(cb.equal(targetRoot.get(RolloutTargetGroup_.rolloutGroup), rolloutGroup));
final List<TargetWithActionStatus> targetWithActionStatus = entityManager.createQuery(multiselect) final List<TargetWithActionStatus> targetWithActionStatus = entityManager.createQuery(multiselect)
.setFirstResult(pageRequest.getOffset()).setMaxResults(pageRequest.getPageSize()).getResultList() .setFirstResult(pageRequest.getOffset()).setMaxResults(pageRequest.getPageSize()).getResultList()
@@ -173,4 +199,10 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
.collect(Collectors.toList()); .collect(Collectors.toList());
return new PageImpl<>(targetWithActionStatus, pageRequest, totalCount); return new PageImpl<>(targetWithActionStatus, pageRequest, totalCount);
} }
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public RolloutGroup generateRolloutGroup() {
return new JpaRolloutGroup();
}
} }

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -19,24 +20,28 @@ import javax.persistence.EntityManager;
import org.eclipse.hawkbit.cache.CacheWriteNotify; import org.eclipse.hawkbit.cache.CacheWriteNotify;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.RolloutFields;
import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.RolloutManagement;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout.RolloutStatus;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup.RolloutGroupConditions;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup.RolloutGroupErrorCondition;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup.RolloutGroupStatus;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup.RolloutGroupSuccessCondition;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_;
import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupConditions;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorCondition;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
import org.eclipse.hawkbit.repository.model.RolloutTargetGroup;
import org.eclipse.hawkbit.repository.model.Rollout_;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
import org.eclipse.hawkbit.rollout.condition.RolloutGroupActionEvaluator; import org.eclipse.hawkbit.rollout.condition.RolloutGroupActionEvaluator;
import org.eclipse.hawkbit.rollout.condition.RolloutGroupConditionEvaluator; import org.eclipse.hawkbit.rollout.condition.RolloutGroupConditionEvaluator;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -46,6 +51,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
@@ -132,15 +138,21 @@ public class JpaRolloutManagement implements RolloutManagement {
@Override @Override
public Page<Rollout> findAll(final Pageable page) { public Page<Rollout> findAll(final Pageable page) {
return rolloutRepository.findAll(page); return convertPage(rolloutRepository.findAll(page));
}
private static Page<Rollout> convertPage(final Slice<JpaRollout> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
@Override @Override
public Page<Rollout> findAllWithDetailedStatusByPredicate(final Specification<Rollout> specification, public Page<Rollout> findAllWithDetailedStatusByPredicate(final String rsqlParam, final Pageable page) {
final Pageable page) {
final Page<Rollout> findAll = rolloutRepository.findAll(specification, page); final Specification<JpaRollout> specification = RSQLUtility.parse(rsqlParam, RolloutFields.class);
final Page<JpaRollout> findAll = rolloutRepository.findAll(specification, page);
setRolloutStatusDetails(findAll); setRolloutStatusDetails(findAll);
return findAll; return convertPage(findAll);
} }
@Override @Override
@@ -153,7 +165,7 @@ public class JpaRolloutManagement implements RolloutManagement {
@Modifying @Modifying
public Rollout createRollout(final Rollout rollout, final int amountGroup, public Rollout createRollout(final Rollout rollout, final int amountGroup,
final RolloutGroupConditions conditions) { final RolloutGroupConditions conditions) {
final Rollout savedRollout = createRollout(rollout, amountGroup); final JpaRollout savedRollout = createRollout((JpaRollout) rollout, amountGroup);
return createRolloutGroups(amountGroup, conditions, savedRollout); return createRolloutGroups(amountGroup, conditions, savedRollout);
} }
@@ -162,7 +174,7 @@ public class JpaRolloutManagement implements RolloutManagement {
@Modifying @Modifying
public Rollout createRolloutAsync(final Rollout rollout, final int amountGroup, public Rollout createRolloutAsync(final Rollout rollout, final int amountGroup,
final RolloutGroupConditions conditions) { final RolloutGroupConditions conditions) {
final Rollout savedRollout = createRollout(rollout, amountGroup); final JpaRollout savedRollout = createRollout((JpaRollout) rollout, amountGroup);
creatingRollouts.add(savedRollout.getName()); creatingRollouts.add(savedRollout.getName());
// need to flush the entity manager here to get the ID of the rollout, // need to flush the entity manager here to get the ID of the rollout,
// because entity manager is set to FlushMode#Auto, entitymanager will // because entity manager is set to FlushMode#Auto, entitymanager will
@@ -182,7 +194,7 @@ public class JpaRolloutManagement implements RolloutManagement {
return savedRollout; return savedRollout;
} }
private Rollout createRollout(final Rollout rollout, final int amountGroup) { private JpaRollout createRollout(final JpaRollout rollout, final int amountGroup) {
verifyRolloutGroupParameter(amountGroup); verifyRolloutGroupParameter(amountGroup);
final Long totalTargets = targetManagement.countTargetByTargetFilterQuery(rollout.getTargetFilterQuery()); final Long totalTargets = targetManagement.countTargetByTargetFilterQuery(rollout.getTargetFilterQuery());
rollout.setTotalTargets(totalTargets.longValue()); rollout.setTotalTargets(totalTargets.longValue());
@@ -198,7 +210,7 @@ public class JpaRolloutManagement implements RolloutManagement {
} }
private Rollout createRolloutGroupsInNewTransaction(final int amountOfGroups, private Rollout createRolloutGroupsInNewTransaction(final int amountOfGroups,
final RolloutGroupConditions conditions, final Rollout savedRollout) { final RolloutGroupConditions conditions, final JpaRollout savedRollout) {
final DefaultTransactionDefinition def = new DefaultTransactionDefinition(); final DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("creatingRollout"); def.setName("creatingRollout");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
@@ -221,7 +233,7 @@ public class JpaRolloutManagement implements RolloutManagement {
* @return the rollout with created groups * @return the rollout with created groups
*/ */
private Rollout createRolloutGroups(final int amountOfGroups, final RolloutGroupConditions conditions, private Rollout createRolloutGroups(final int amountOfGroups, final RolloutGroupConditions conditions,
final Rollout savedRollout) { final JpaRollout savedRollout) {
int pageIndex = 0; int pageIndex = 0;
int groupIndex = 0; int groupIndex = 0;
final Long totalCount = savedRollout.getTotalTargets(); final Long totalCount = savedRollout.getTotalTargets();
@@ -237,7 +249,7 @@ public class JpaRolloutManagement implements RolloutManagement {
while (pageIndex < totalCount) { while (pageIndex < totalCount) {
groupIndex++; groupIndex++;
final String nameAndDesc = "group-" + groupIndex; final String nameAndDesc = "group-" + groupIndex;
final RolloutGroup group = new RolloutGroup(); final JpaRolloutGroup group = new JpaRolloutGroup();
group.setName(nameAndDesc); group.setName(nameAndDesc);
group.setDescription(nameAndDesc); group.setDescription(nameAndDesc);
group.setRollout(savedRollout); group.setRollout(savedRollout);
@@ -272,7 +284,7 @@ public class JpaRolloutManagement implements RolloutManagement {
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public Rollout startRollout(final Rollout rollout) { public Rollout startRollout(final Rollout rollout) {
final Rollout mergedRollout = entityManager.merge(rollout); final JpaRollout mergedRollout = entityManager.merge((JpaRollout) rollout);
checkIfRolloutCanStarted(rollout, mergedRollout); checkIfRolloutCanStarted(rollout, mergedRollout);
return doStartRollout(mergedRollout); return doStartRollout(mergedRollout);
} }
@@ -281,10 +293,10 @@ public class JpaRolloutManagement implements RolloutManagement {
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public Rollout startRolloutAsync(final Rollout rollout) { public Rollout startRolloutAsync(final Rollout rollout) {
final Rollout mergedRollout = entityManager.merge(rollout); final JpaRollout mergedRollout = entityManager.merge((JpaRollout) rollout);
checkIfRolloutCanStarted(rollout, mergedRollout); checkIfRolloutCanStarted(rollout, mergedRollout);
mergedRollout.setStatus(RolloutStatus.STARTING); mergedRollout.setStatus(RolloutStatus.STARTING);
final Rollout updatedRollout = rolloutRepository.save(mergedRollout); final JpaRollout updatedRollout = rolloutRepository.save(mergedRollout);
startingRollouts.add(updatedRollout.getName()); startingRollouts.add(updatedRollout.getName());
executor.execute(() -> { executor.execute(() -> {
try { try {
@@ -303,13 +315,13 @@ public class JpaRolloutManagement implements RolloutManagement {
} }
private Rollout doStartRollout(final Rollout rollout) { private Rollout doStartRollout(final JpaRollout rollout) {
final DistributionSet distributionSet = rollout.getDistributionSet(); final DistributionSet distributionSet = rollout.getDistributionSet();
final ActionType actionType = rollout.getActionType(); final ActionType actionType = rollout.getActionType();
final long forceTime = rollout.getForcedTime(); final long forceTime = rollout.getForcedTime();
final List<RolloutGroup> rolloutGroups = rolloutGroupRepository.findByRolloutOrderByIdAsc(rollout); final List<JpaRolloutGroup> rolloutGroups = rolloutGroupRepository.findByRolloutOrderByIdAsc(rollout);
for (int iGroup = 0; iGroup < rolloutGroups.size(); iGroup++) { for (int iGroup = 0; iGroup < rolloutGroups.size(); iGroup++) {
final RolloutGroup rolloutGroup = rolloutGroups.get(iGroup); final JpaRolloutGroup rolloutGroup = rolloutGroups.get(iGroup);
final List<Target> targetGroup = targetRepository.findByRolloutTargetGroupRolloutGroup(rolloutGroup); final List<Target> targetGroup = targetRepository.findByRolloutTargetGroupRolloutGroup(rolloutGroup);
// firstgroup can already be started // firstgroup can already be started
if (iGroup == 0) { if (iGroup == 0) {
@@ -336,7 +348,7 @@ public class JpaRolloutManagement implements RolloutManagement {
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public void pauseRollout(final Rollout rollout) { public void pauseRollout(final Rollout rollout) {
final Rollout mergedRollout = entityManager.merge(rollout); final JpaRollout mergedRollout = entityManager.merge((JpaRollout) rollout);
if (mergedRollout.getStatus() != RolloutStatus.RUNNING) { if (mergedRollout.getStatus() != RolloutStatus.RUNNING) {
throw new RolloutIllegalStateException("Rollout can only be paused in state running but current state is " throw new RolloutIllegalStateException("Rollout can only be paused in state running but current state is "
+ rollout.getStatus().name().toLowerCase()); + rollout.getStatus().name().toLowerCase());
@@ -354,7 +366,7 @@ public class JpaRolloutManagement implements RolloutManagement {
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public void resumeRollout(final Rollout rollout) { public void resumeRollout(final Rollout rollout) {
final Rollout mergedRollout = entityManager.merge(rollout); final JpaRollout mergedRollout = entityManager.merge((JpaRollout) rollout);
if (!(RolloutStatus.PAUSED.equals(mergedRollout.getStatus()))) { if (!(RolloutStatus.PAUSED.equals(mergedRollout.getStatus()))) {
throw new RolloutIllegalStateException("Rollout can only be resumed in state paused but current state is " throw new RolloutIllegalStateException("Rollout can only be resumed in state paused but current state is "
+ rollout.getStatus().name().toLowerCase()); + rollout.getStatus().name().toLowerCase());
@@ -379,13 +391,13 @@ public class JpaRolloutManagement implements RolloutManagement {
return; return;
} }
final List<Rollout> rolloutsToCheck = rolloutRepository.findByLastCheckAndStatus(lastCheck, final List<JpaRollout> rolloutsToCheck = rolloutRepository.findByLastCheckAndStatus(lastCheck,
RolloutStatus.RUNNING); RolloutStatus.RUNNING);
LOGGER.info("Found {} running rollouts to check", rolloutsToCheck.size()); LOGGER.info("Found {} running rollouts to check", rolloutsToCheck.size());
for (final Rollout rollout : rolloutsToCheck) { for (final JpaRollout rollout : rolloutsToCheck) {
LOGGER.debug("Checking rollout {}", rollout); LOGGER.debug("Checking rollout {}", rollout);
final List<RolloutGroup> rolloutGroups = rolloutGroupRepository.findByRolloutAndStatus(rollout, final List<JpaRolloutGroup> rolloutGroups = rolloutGroupRepository.findByRolloutAndStatus(rollout,
RolloutGroupStatus.RUNNING); RolloutGroupStatus.RUNNING);
if (rolloutGroups.isEmpty()) { if (rolloutGroups.isEmpty()) {
@@ -415,7 +427,7 @@ public class JpaRolloutManagement implements RolloutManagement {
* In case this happens, set the rollout to error state. * In case this happens, set the rollout to error state.
*/ */
private void verifyStuckedRollouts() { private void verifyStuckedRollouts() {
final List<Rollout> rolloutsInCreatingState = rolloutRepository.findByStatus(RolloutStatus.CREATING); final List<JpaRollout> rolloutsInCreatingState = rolloutRepository.findByStatus(RolloutStatus.CREATING);
rolloutsInCreatingState.stream().filter(rollout -> !creatingRollouts.contains(rollout.getName())) rolloutsInCreatingState.stream().filter(rollout -> !creatingRollouts.contains(rollout.getName()))
.forEach(rollout -> { .forEach(rollout -> {
LOGGER.warn( LOGGER.warn(
@@ -425,7 +437,7 @@ public class JpaRolloutManagement implements RolloutManagement {
rolloutRepository.save(rollout); rolloutRepository.save(rollout);
}); });
final List<Rollout> rolloutsInStartingState = rolloutRepository.findByStatus(RolloutStatus.STARTING); final List<JpaRollout> rolloutsInStartingState = rolloutRepository.findByStatus(RolloutStatus.STARTING);
rolloutsInStartingState.stream().filter(rollout -> !startingRollouts.contains(rollout.getName())) rolloutsInStartingState.stream().filter(rollout -> !startingRollouts.contains(rollout.getName()))
.forEach(rollout -> { .forEach(rollout -> {
LOGGER.warn( LOGGER.warn(
@@ -437,8 +449,8 @@ public class JpaRolloutManagement implements RolloutManagement {
} }
private void executeRolloutGroups(final Rollout rollout, final List<RolloutGroup> rolloutGroups) { private void executeRolloutGroups(final JpaRollout rollout, final List<JpaRolloutGroup> rolloutGroups) {
for (final RolloutGroup rolloutGroup : rolloutGroups) { for (final JpaRolloutGroup rolloutGroup : rolloutGroups) {
// error state check, do we need to stop the whole // error state check, do we need to stop the whole
// rollout because of error? // rollout because of error?
final RolloutGroupErrorCondition errorCondition = rolloutGroup.getErrorCondition(); final RolloutGroupErrorCondition errorCondition = rolloutGroup.getErrorCondition();
@@ -459,8 +471,8 @@ public class JpaRolloutManagement implements RolloutManagement {
} }
} }
private void executeLatestRolloutGroup(final Rollout rollout) { private void executeLatestRolloutGroup(final JpaRollout rollout) {
final List<RolloutGroup> latestRolloutGroup = rolloutGroupRepository final List<JpaRolloutGroup> latestRolloutGroup = rolloutGroupRepository
.findByRolloutAndStatusNotOrderByIdDesc(rollout, RolloutGroupStatus.SCHEDULED); .findByRolloutAndStatusNotOrderByIdDesc(rollout, RolloutGroupStatus.SCHEDULED);
if (latestRolloutGroup.isEmpty()) { if (latestRolloutGroup.isEmpty()) {
return; return;
@@ -478,13 +490,13 @@ public class JpaRolloutManagement implements RolloutManagement {
} }
} }
private boolean isRolloutComplete(final Rollout rollout) { private boolean isRolloutComplete(final JpaRollout rollout) {
final Long groupsActiveLeft = rolloutGroupRepository.countByRolloutAndStatusOrStatus(rollout, final Long groupsActiveLeft = rolloutGroupRepository.countByRolloutAndStatusOrStatus(rollout,
RolloutGroupStatus.RUNNING, RolloutGroupStatus.SCHEDULED); RolloutGroupStatus.RUNNING, RolloutGroupStatus.SCHEDULED);
return groupsActiveLeft == 0; return groupsActiveLeft == 0;
} }
private boolean isRolloutGroupComplete(final Rollout rollout, final RolloutGroup rolloutGroup) { private boolean isRolloutGroupComplete(final JpaRollout rollout, final JpaRolloutGroup rolloutGroup) {
final Long actionsLeftForRollout = actionRepository final Long actionsLeftForRollout = actionRepository
.countByRolloutAndRolloutGroupAndStatusNotAndStatusNotAndStatusNot(rollout, rolloutGroup, .countByRolloutAndRolloutGroupAndStatusNotAndStatusNotAndStatusNot(rollout, rolloutGroup,
Action.Status.ERROR, Action.Status.FINISHED, Action.Status.CANCELED); Action.Status.ERROR, Action.Status.FINISHED, Action.Status.CANCELED);
@@ -543,22 +555,22 @@ public class JpaRolloutManagement implements RolloutManagement {
return rolloutRepository.count(likeNameOrDescription(searchText)); return rolloutRepository.count(likeNameOrDescription(searchText));
} }
private static Specification<Rollout> likeNameOrDescription(final String searchText) { private static Specification<JpaRollout> likeNameOrDescription(final String searchText) {
return (rolloutRoot, query, criteriaBuilder) -> { return (rolloutRoot, query, criteriaBuilder) -> {
final String searchTextToLower = searchText.toLowerCase(); final String searchTextToLower = searchText.toLowerCase();
return criteriaBuilder.or( return criteriaBuilder.or(
criteriaBuilder.like(criteriaBuilder.lower(rolloutRoot.get(Rollout_.name)), searchTextToLower), criteriaBuilder.like(criteriaBuilder.lower(rolloutRoot.get(JpaRollout_.name)), searchTextToLower),
criteriaBuilder.like(criteriaBuilder.lower(rolloutRoot.get(Rollout_.description)), criteriaBuilder.like(criteriaBuilder.lower(rolloutRoot.get(JpaRollout_.description)),
searchTextToLower)); searchTextToLower));
}; };
} }
@Override @Override
public Slice<Rollout> findRolloutByFilters(final Pageable pageable, final String searchText) { public Slice<Rollout> findRolloutByFilters(final Pageable pageable, final String searchText) {
final Specification<Rollout> specs = likeNameOrDescription(searchText); final Specification<JpaRollout> specs = likeNameOrDescription(searchText);
final Slice<Rollout> findAll = criteriaNoCountDao.findAll(specs, pageable, Rollout.class); final Slice<JpaRollout> findAll = criteriaNoCountDao.findAll(specs, pageable, JpaRollout.class);
setRolloutStatusDetails(findAll); setRolloutStatusDetails(findAll);
return findAll; return convertPage(findAll);
} }
@Override @Override
@@ -579,7 +591,7 @@ public class JpaRolloutManagement implements RolloutManagement {
@Modifying @Modifying
public Rollout updateRollout(final Rollout rollout) { public Rollout updateRollout(final Rollout rollout) {
Assert.notNull(rollout.getId()); Assert.notNull(rollout.getId());
return rolloutRepository.save(rollout); return rolloutRepository.save((JpaRollout) rollout);
} }
/** /**
@@ -593,9 +605,9 @@ public class JpaRolloutManagement implements RolloutManagement {
*/ */
@Override @Override
public Page<Rollout> findAllRolloutsWithDetailedStatus(final Pageable page) { public Page<Rollout> findAllRolloutsWithDetailedStatus(final Pageable page) {
final Page<Rollout> rollouts = findAll(page); final Page<JpaRollout> rollouts = rolloutRepository.findAll(page);
setRolloutStatusDetails(rollouts); setRolloutStatusDetails(rollouts);
return rollouts; return convertPage(rollouts);
} }
@@ -615,7 +627,7 @@ public class JpaRolloutManagement implements RolloutManagement {
return resultList.stream().collect(Collectors.groupingBy(TotalTargetCountActionStatus::getId)); return resultList.stream().collect(Collectors.groupingBy(TotalTargetCountActionStatus::getId));
} }
private void setRolloutStatusDetails(final Slice<Rollout> rollouts) { private void setRolloutStatusDetails(final Slice<JpaRollout> rollouts) {
final List<Long> rolloutIds = rollouts.getContent().stream().map(rollout -> rollout.getId()) final List<Long> rolloutIds = rollouts.getContent().stream().map(rollout -> rollout.getId())
.collect(Collectors.toList()); .collect(Collectors.toList());
final Map<Long, List<TotalTargetCountActionStatus>> allStatesForRollout = getStatusCountItemForRollout( final Map<Long, List<TotalTargetCountActionStatus>> allStatesForRollout = getStatusCountItemForRollout(
@@ -648,4 +660,10 @@ public class JpaRolloutManagement implements RolloutManagement {
// calculate threshold // calculate threshold
return ((float) finished / (float) totalGroup) * 100; return ((float) finished / (float) totalGroup) * 100;
} }
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public Rollout generateRollout() {
return new JpaRollout();
}
} }

View File

@@ -13,6 +13,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -27,23 +28,32 @@ import javax.persistence.criteria.Root;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.SoftwareManagement; 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.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; 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.specifications.SoftwareModuleSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.model.CustomSoftwareModule; import org.eclipse.hawkbit.repository.model.CustomSoftwareModule;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSet_;
import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata_;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.SoftwareModule_; import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.model.SwMetadataCompositeKey;
import org.eclipse.hawkbit.repository.specifications.SoftwareModuleSpecification;
import org.eclipse.hawkbit.repository.specifications.SpecificationsBuilder;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.AuditorAware;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl; import org.springframework.data.domain.SliceImpl;
@@ -52,6 +62,7 @@ import org.springframework.data.jpa.repository.Modifying;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -100,7 +111,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
public SoftwareModule updateSoftwareModule(final SoftwareModule sm) { public SoftwareModule updateSoftwareModule(final SoftwareModule sm) {
checkNotNull(sm.getId()); checkNotNull(sm.getId());
final SoftwareModule module = softwareModuleRepository.findOne(sm.getId()); final JpaSoftwareModule module = softwareModuleRepository.findOne(sm.getId());
boolean updated = false; boolean updated = false;
if (null == sm.getDescription() || !sm.getDescription().equals(module.getDescription())) { if (null == sm.getDescription() || !sm.getDescription().equals(module.getDescription())) {
@@ -121,7 +132,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
public SoftwareModuleType updateSoftwareModuleType(final SoftwareModuleType sm) { public SoftwareModuleType updateSoftwareModuleType(final SoftwareModuleType sm) {
checkNotNull(sm.getId()); checkNotNull(sm.getId());
final SoftwareModuleType type = softwareModuleTypeRepository.findOne(sm.getId()); final JpaSoftwareModuleType type = softwareModuleTypeRepository.findOne(sm.getId());
boolean updated = false; boolean updated = false;
if (sm.getDescription() != null && !sm.getDescription().equals(type.getDescription())) { if (sm.getDescription() != null && !sm.getDescription().equals(type.getDescription())) {
@@ -142,7 +153,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
if (null != swModule.getId()) { if (null != swModule.getId()) {
throw new EntityAlreadyExistsException(); throw new EntityAlreadyExistsException();
} }
return softwareModuleRepository.save(swModule); return softwareModuleRepository.save((JpaSoftwareModule) swModule);
} }
@Override @Override
@@ -155,30 +166,40 @@ public class JpaSoftwareManagement implements SoftwareManagement {
} }
}); });
return softwareModuleRepository.save(swModules); @SuppressWarnings({ "unchecked", "rawtypes" })
final Collection<JpaSoftwareModule> jpaCast = (Collection) swModules;
return new ArrayList<>(softwareModuleRepository.save(jpaCast));
} }
@Override @Override
public Slice<SoftwareModule> findSoftwareModulesByType(final Pageable pageable, final SoftwareModuleType type) { public Slice<SoftwareModule> findSoftwareModulesByType(final Pageable pageable, final SoftwareModuleType type) {
final List<Specification<SoftwareModule>> specList = new ArrayList<>(); final List<Specification<JpaSoftwareModule>> specList = new LinkedList<>();
Specification<SoftwareModule> spec = SoftwareModuleSpecification.equalType(type); Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type);
specList.add(spec); specList.add(spec);
spec = SoftwareModuleSpecification.isDeletedFalse(); spec = SoftwareModuleSpecification.isDeletedFalse();
specList.add(spec); specList.add(spec);
return findSwModuleByCriteriaAPI(pageable, specList); return convertSmPage(findSwModuleByCriteriaAPI(pageable, specList));
}
private static Page<SoftwareModule> convertSmPage(final Slice<JpaSoftwareModule> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
}
private static Page<SoftwareModuleMetadata> convertSmMdPage(final Slice<JpaSoftwareModuleMetadata> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
@Override @Override
public Long countSoftwareModulesByType(final SoftwareModuleType type) { public Long countSoftwareModulesByType(final SoftwareModuleType type) {
final List<Specification<SoftwareModule>> specList = new ArrayList<>(); final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>();
Specification<SoftwareModule> spec = SoftwareModuleSpecification.equalType(type); Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type);
specList.add(spec); specList.add(spec);
spec = SoftwareModuleSpecification.isDeletedFalse(); spec = SoftwareModuleSpecification.isDeletedFalse();
@@ -196,24 +217,24 @@ public class JpaSoftwareManagement implements SoftwareManagement {
public SoftwareModule findSoftwareModuleByNameAndVersion(final String name, final String version, public SoftwareModule findSoftwareModuleByNameAndVersion(final String name, final String version,
final SoftwareModuleType type) { final SoftwareModuleType type) {
return softwareModuleRepository.findOneByNameAndVersionAndType(name, version, type); return softwareModuleRepository.findOneByNameAndVersionAndType(name, version, (JpaSoftwareModuleType) type);
} }
private boolean isUnassigned(final SoftwareModule bsmMerged) { private boolean isUnassigned(final JpaSoftwareModule bsmMerged) {
return distributionSetRepository.findByModules(bsmMerged).isEmpty(); return distributionSetRepository.findByModules(bsmMerged).isEmpty();
} }
private Slice<SoftwareModule> findSwModuleByCriteriaAPI(final Pageable pageable, private Slice<JpaSoftwareModule> findSwModuleByCriteriaAPI(final Pageable pageable,
final List<Specification<SoftwareModule>> specList) { final List<Specification<JpaSoftwareModule>> specList) {
return criteriaNoCountDao.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable, return criteriaNoCountDao.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable,
SoftwareModule.class); JpaSoftwareModule.class);
} }
private Long countSwModuleByCriteriaAPI(final List<Specification<SoftwareModule>> specList) { private Long countSwModuleByCriteriaAPI(final List<Specification<JpaSoftwareModule>> specList) {
return softwareModuleRepository.count(SpecificationsBuilder.combineWithAnd(specList)); return softwareModuleRepository.count(SpecificationsBuilder.combineWithAnd(specList));
} }
private void deleteGridFsArtifacts(final SoftwareModule swModule) { private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) {
for (final LocalArtifact localArtifact : swModule.getLocalArtifacts()) { for (final LocalArtifact localArtifact : swModule.getLocalArtifacts()) {
artifactManagement.deleteLocalArtifact(localArtifact); artifactManagement.deleteLocalArtifact(localArtifact);
} }
@@ -223,7 +244,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void deleteSoftwareModules(final Collection<Long> ids) { public void deleteSoftwareModules(final Collection<Long> ids) {
final List<SoftwareModule> swModulesToDelete = softwareModuleRepository.findByIdIn(ids); final List<JpaSoftwareModule> swModulesToDelete = softwareModuleRepository.findByIdIn(ids);
final Set<Long> assignedModuleIds = new HashSet<>(); final Set<Long> assignedModuleIds = new HashSet<>();
swModulesToDelete.forEach(swModule -> { swModulesToDelete.forEach(swModule -> {
@@ -253,29 +274,29 @@ public class JpaSoftwareManagement implements SoftwareManagement {
@Override @Override
public Slice<SoftwareModule> findSoftwareModulesAll(final Pageable pageable) { public Slice<SoftwareModule> findSoftwareModulesAll(final Pageable pageable) {
final List<Specification<SoftwareModule>> specList = new ArrayList<>(); final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>();
Specification<SoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse(); Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
specList.add(spec); specList.add(spec);
spec = (root, query, cb) -> { spec = (root, query, cb) -> {
if (!query.getResultType().isAssignableFrom(Long.class)) { if (!query.getResultType().isAssignableFrom(Long.class)) {
root.fetch(SoftwareModule_.type); root.fetch(JpaSoftwareModule_.type);
} }
return cb.conjunction(); return cb.conjunction();
}; };
specList.add(spec); specList.add(spec);
return findSwModuleByCriteriaAPI(pageable, specList); return convertSmPage(findSwModuleByCriteriaAPI(pageable, specList));
} }
@Override @Override
public Long countSoftwareModulesAll() { public Long countSoftwareModulesAll() {
final List<Specification<SoftwareModule>> specList = new ArrayList<>(); final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>();
final Specification<SoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse(); final Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
specList.add(spec); specList.add(spec);
return countSwModuleByCriteriaAPI(specList); return countSwModuleByCriteriaAPI(specList);
@@ -287,30 +308,38 @@ public class JpaSoftwareManagement implements SoftwareManagement {
} }
@Override @Override
public Page<SoftwareModule> findSoftwareModulesByPredicate(final Specification<SoftwareModule> spec, public Page<SoftwareModule> findSoftwareModulesByPredicate(final String rsqlParam, final Pageable pageable) {
final Pageable pageable) { final Specification<JpaSoftwareModule> spec = RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class);
return softwareModuleRepository.findAll(spec, pageable);
return convertSmPage(softwareModuleRepository.findAll(spec, pageable));
} }
@Override @Override
public Page<SoftwareModuleType> findSoftwareModuleTypesByPredicate(final Specification<SoftwareModuleType> spec, public Page<SoftwareModuleType> findSoftwareModuleTypesByPredicate(final String rsqlParam,
final Pageable pageable) { final Pageable pageable) {
return softwareModuleTypeRepository.findAll(spec, pageable);
final Specification<JpaSoftwareModuleType> spec = RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class);
return convertSmTPage(softwareModuleTypeRepository.findAll(spec, pageable));
}
private static Page<SoftwareModuleType> convertSmTPage(final Slice<JpaSoftwareModuleType> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
@Override @Override
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
public List<SoftwareModule> findSoftwareModulesById(final Collection<Long> ids) { public List<SoftwareModule> findSoftwareModulesById(final Collection<Long> ids) {
return softwareModuleRepository.findByIdIn(ids); return new ArrayList<>(softwareModuleRepository.findByIdIn(ids));
} }
@Override @Override
public Slice<SoftwareModule> findSoftwareModuleByFilters(final Pageable pageable, final String searchText, public Slice<SoftwareModule> findSoftwareModuleByFilters(final Pageable pageable, final String searchText,
final SoftwareModuleType type) { final SoftwareModuleType type) {
final List<Specification<SoftwareModule>> specList = new ArrayList<>(); final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>();
Specification<SoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse(); Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
specList.add(spec); specList.add(spec);
if (!Strings.isNullOrEmpty(searchText)) { if (!Strings.isNullOrEmpty(searchText)) {
@@ -319,50 +348,53 @@ public class JpaSoftwareManagement implements SoftwareManagement {
} }
if (null != type) { if (null != type) {
spec = SoftwareModuleSpecification.equalType(type); spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type);
specList.add(spec); specList.add(spec);
} }
spec = (root, query, cb) -> { spec = (root, query, cb) -> {
if (!query.getResultType().isAssignableFrom(Long.class)) { if (!query.getResultType().isAssignableFrom(Long.class)) {
root.fetch(SoftwareModule_.type); root.fetch(JpaSoftwareModule_.type);
} }
return cb.conjunction(); return cb.conjunction();
}; };
specList.add(spec); specList.add(spec);
return findSwModuleByCriteriaAPI(pageable, specList); return convertSmPage(findSwModuleByCriteriaAPI(pageable, specList));
} }
@Override @Override
public Slice<CustomSoftwareModule> findSoftwareModuleOrderBySetAssignmentAndModuleNameAscModuleVersionAsc( public Slice<CustomSoftwareModule> findSoftwareModuleOrderBySetAssignmentAndModuleNameAscModuleVersionAsc(
final Pageable pageable, final Long orderByDistributionId, final String searchText, final Pageable pageable, final Long orderByDistributionId, final String searchText,
final SoftwareModuleType type) { final SoftwareModuleType ty) {
final JpaSoftwareModuleType type = (JpaSoftwareModuleType) ty;
final List<CustomSoftwareModule> resultList = new ArrayList<>(); final List<CustomSoftwareModule> resultList = new ArrayList<>();
final int pageSize = pageable.getPageSize(); final int pageSize = pageable.getPageSize();
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
// get the assigned software modules // get the assigned software modules
final CriteriaQuery<SoftwareModule> assignedQuery = cb.createQuery(SoftwareModule.class); final CriteriaQuery<JpaSoftwareModule> assignedQuery = cb.createQuery(JpaSoftwareModule.class);
final Root<SoftwareModule> assignedRoot = assignedQuery.from(SoftwareModule.class); final Root<JpaSoftwareModule> assignedRoot = assignedQuery.from(JpaSoftwareModule.class);
assignedQuery.distinct(true); assignedQuery.distinct(true);
final ListJoin<SoftwareModule, DistributionSet> assignedDsJoin = assignedRoot.join(SoftwareModule_.assignedTo); final ListJoin<JpaSoftwareModule, JpaDistributionSet> assignedDsJoin = assignedRoot
.join(JpaSoftwareModule_.assignedTo);
// build the specifications and then to predicates necessary by the // build the specifications and then to predicates necessary by the
// given filters // given filters
final Predicate[] specPredicate = specificationsToPredicate(buildSpecificationList(searchText, type), final Predicate[] specPredicate = specificationsToPredicate(buildSpecificationList(searchText, type),
assignedRoot, assignedQuery, cb, assignedRoot, assignedQuery, cb,
cb.equal(assignedDsJoin.get(DistributionSet_.id), orderByDistributionId)); cb.equal(assignedDsJoin.get(JpaDistributionSet_.id), orderByDistributionId));
// if we have some predicates then add it to the where clause of the // if we have some predicates then add it to the where clause of the
// multi select // multi select
assignedQuery.where(specPredicate); assignedQuery.where(specPredicate);
assignedQuery.orderBy(cb.asc(assignedRoot.get(SoftwareModule_.name)), assignedQuery.orderBy(cb.asc(assignedRoot.get(JpaSoftwareModule_.name)),
cb.asc(assignedRoot.get(SoftwareModule_.version))); cb.asc(assignedRoot.get(JpaSoftwareModule_.version)));
// don't page the assigned query on database, we need all assigned // don't page the assigned query on database, we need all assigned
// software modules to filter // software modules to filter
// them out in the unassigned query // them out in the unassigned query
final List<SoftwareModule> assignedSoftwareModules = entityManager.createQuery(assignedQuery).getResultList(); final List<JpaSoftwareModule> assignedSoftwareModules = entityManager.createQuery(assignedQuery)
.getResultList();
// map result // map result
if (pageable.getOffset() < assignedSoftwareModules.size()) { if (pageable.getOffset() < assignedSoftwareModules.size()) {
assignedSoftwareModules assignedSoftwareModules
@@ -375,14 +407,14 @@ public class JpaSoftwareManagement implements SoftwareManagement {
} }
// get the unassigned software modules // get the unassigned software modules
final CriteriaQuery<SoftwareModule> unassignedQuery = cb.createQuery(SoftwareModule.class); final CriteriaQuery<JpaSoftwareModule> unassignedQuery = cb.createQuery(JpaSoftwareModule.class);
unassignedQuery.distinct(true); unassignedQuery.distinct(true);
final Root<SoftwareModule> unassignedRoot = unassignedQuery.from(SoftwareModule.class); final Root<JpaSoftwareModule> unassignedRoot = unassignedQuery.from(JpaSoftwareModule.class);
Predicate[] unassignedSpec; Predicate[] unassignedSpec;
if (!assignedSoftwareModules.isEmpty()) { if (!assignedSoftwareModules.isEmpty()) {
unassignedSpec = specificationsToPredicate(buildSpecificationList(searchText, type), unassignedRoot, unassignedSpec = specificationsToPredicate(buildSpecificationList(searchText, type), unassignedRoot,
unassignedQuery, cb, cb.not(unassignedRoot.get(SoftwareModule_.id) unassignedQuery, cb, cb.not(unassignedRoot.get(JpaSoftwareModule_.id)
.in(assignedSoftwareModules.stream().map(sw -> sw.getId()).collect(Collectors.toList())))); .in(assignedSoftwareModules.stream().map(sw -> sw.getId()).collect(Collectors.toList()))));
} else { } else {
unassignedSpec = specificationsToPredicate(buildSpecificationList(searchText, type), unassignedRoot, unassignedSpec = specificationsToPredicate(buildSpecificationList(searchText, type), unassignedRoot,
@@ -390,9 +422,9 @@ public class JpaSoftwareManagement implements SoftwareManagement {
} }
unassignedQuery.where(unassignedSpec); unassignedQuery.where(unassignedSpec);
unassignedQuery.orderBy(cb.asc(unassignedRoot.get(SoftwareModule_.name)), unassignedQuery.orderBy(cb.asc(unassignedRoot.get(JpaSoftwareModule_.name)),
cb.asc(unassignedRoot.get(SoftwareModule_.version))); cb.asc(unassignedRoot.get(JpaSoftwareModule_.version)));
final List<SoftwareModule> unassignedSoftwareModules = entityManager.createQuery(unassignedQuery) final List<JpaSoftwareModule> unassignedSoftwareModules = entityManager.createQuery(unassignedQuery)
.setFirstResult(Math.max(0, pageable.getOffset() - assignedSoftwareModules.size())) .setFirstResult(Math.max(0, pageable.getOffset() - assignedSoftwareModules.size()))
.setMaxResults(pageSize).getResultList(); .setMaxResults(pageSize).getResultList();
// map result // map result
@@ -401,9 +433,9 @@ public class JpaSoftwareManagement implements SoftwareManagement {
return new SliceImpl<>(resultList); return new SliceImpl<>(resultList);
} }
private static List<Specification<SoftwareModule>> buildSpecificationList(final String searchText, private static List<Specification<JpaSoftwareModule>> buildSpecificationList(final String searchText,
final SoftwareModuleType type) { final JpaSoftwareModuleType type) {
final List<Specification<SoftwareModule>> specList = new ArrayList<>(); final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>();
if (!Strings.isNullOrEmpty(searchText)) { if (!Strings.isNullOrEmpty(searchText)) {
specList.add(SoftwareModuleSpecification.likeNameOrVersion(searchText)); specList.add(SoftwareModuleSpecification.likeNameOrVersion(searchText));
} }
@@ -414,8 +446,8 @@ public class JpaSoftwareManagement implements SoftwareManagement {
return specList; return specList;
} }
private Predicate[] specificationsToPredicate(final List<Specification<SoftwareModule>> specifications, private Predicate[] specificationsToPredicate(final List<Specification<JpaSoftwareModule>> specifications,
final Root<SoftwareModule> root, final CriteriaQuery<?> query, final CriteriaBuilder cb, final Root<JpaSoftwareModule> root, final CriteriaQuery<?> query, final CriteriaBuilder cb,
final Predicate... additionalPredicates) { final Predicate... additionalPredicates) {
final List<Predicate> predicates = new ArrayList<>(); final List<Predicate> predicates = new ArrayList<>();
specifications.forEach(spec -> predicates.add(spec.toPredicate(root, query, cb))); specifications.forEach(spec -> predicates.add(spec.toPredicate(root, query, cb)));
@@ -428,9 +460,9 @@ public class JpaSoftwareManagement implements SoftwareManagement {
@Override @Override
public Long countSoftwareModuleByFilters(final String searchText, final SoftwareModuleType type) { public Long countSoftwareModuleByFilters(final String searchText, final SoftwareModuleType type) {
final List<Specification<SoftwareModule>> specList = new ArrayList<>(); final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>();
Specification<SoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse(); Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
specList.add(spec); specList.add(spec);
if (!Strings.isNullOrEmpty(searchText)) { if (!Strings.isNullOrEmpty(searchText)) {
@@ -439,7 +471,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
} }
if (null != type) { if (null != type) {
spec = SoftwareModuleSpecification.equalType(type); spec = SoftwareModuleSpecification.equalType((JpaSoftwareModuleType) type);
specList.add(spec); specList.add(spec);
} }
@@ -479,17 +511,18 @@ public class JpaSoftwareManagement implements SoftwareManagement {
throw new EntityAlreadyExistsException("Given type contains an Id!"); throw new EntityAlreadyExistsException("Given type contains an Id!");
} }
return softwareModuleTypeRepository.save(type); return softwareModuleTypeRepository.save((JpaSoftwareModuleType) type);
} }
@Override @Override
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void deleteSoftwareModuleType(final SoftwareModuleType type) { public void deleteSoftwareModuleType(final SoftwareModuleType ty) {
final JpaSoftwareModuleType type = (JpaSoftwareModuleType) ty;
if (softwareModuleRepository.countByType(type) > 0 if (softwareModuleRepository.countByType(type) > 0
|| distributionSetTypeRepository.countByElementsSmType(type) > 0) { || distributionSetTypeRepository.countByElementsSmType(type) > 0) {
final SoftwareModuleType toDelete = entityManager.merge(type); final JpaSoftwareModuleType toDelete = entityManager.merge(type);
toDelete.setDeleted(true); toDelete.setDeleted(true);
softwareModuleTypeRepository.save(toDelete); softwareModuleTypeRepository.save(toDelete);
} else { } else {
@@ -499,19 +532,22 @@ public class JpaSoftwareManagement implements SoftwareManagement {
@Override @Override
public Page<SoftwareModule> findSoftwareModuleByAssignedTo(final Pageable pageable, final DistributionSet set) { public Page<SoftwareModule> findSoftwareModuleByAssignedTo(final Pageable pageable, final DistributionSet set) {
return softwareModuleRepository.findByAssignedTo(pageable, set); return softwareModuleRepository.findByAssignedTo(pageable, (JpaDistributionSet) set);
} }
@Override @Override
public Page<SoftwareModule> findSoftwareModuleByAssignedToAndType(final Pageable pageable, public Page<SoftwareModule> findSoftwareModuleByAssignedToAndType(final Pageable pageable,
final DistributionSet set, final SoftwareModuleType type) { final DistributionSet set, final SoftwareModuleType type) {
return softwareModuleRepository.findByAssignedToAndType(pageable, set, type); return softwareModuleRepository.findByAssignedToAndType(pageable, (JpaDistributionSet) set,
(JpaSoftwareModuleType) type);
} }
@Override @Override
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public SoftwareModuleMetadata createSoftwareModuleMetadata(final SoftwareModuleMetadata metadata) { public SoftwareModuleMetadata createSoftwareModuleMetadata(final SoftwareModuleMetadata md) {
final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) md;
if (softwareModuleMetadataRepository.exists(metadata.getId())) { if (softwareModuleMetadataRepository.exists(metadata.getId())) {
throwMetadataKeyAlreadyExists(metadata.getId().getKey()); throwMetadataKeyAlreadyExists(metadata.getId().getKey());
} }
@@ -519,32 +555,36 @@ public class JpaSoftwareManagement implements SoftwareManagement {
// log written because // log written because
// modifying metadata is modifying the base software module itself for // modifying metadata is modifying the base software module itself for
// auditing purposes. // auditing purposes.
entityManager.merge(metadata.getSoftwareModule()).setLastModifiedAt(-1L); entityManager.merge((JpaSoftwareModule) metadata.getSoftwareModule()).setLastModifiedAt(-1L);
return softwareModuleMetadataRepository.save(metadata); return softwareModuleMetadataRepository.save(metadata);
} }
@Override @Override
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public List<SoftwareModuleMetadata> createSoftwareModuleMetadata( public List<SoftwareModuleMetadata> createSoftwareModuleMetadata(final Collection<SoftwareModuleMetadata> md) {
final Collection<SoftwareModuleMetadata> metadata) { @SuppressWarnings({ "unchecked", "rawtypes" })
for (final SoftwareModuleMetadata softwareModuleMetadata : metadata) { final Collection<JpaSoftwareModuleMetadata> metadata = (Collection) md;
for (final JpaSoftwareModuleMetadata softwareModuleMetadata : metadata) {
checkAndThrowAlreadyExistsIfSoftwareModuleMetadataExists(softwareModuleMetadata.getId()); checkAndThrowAlreadyExistsIfSoftwareModuleMetadataExists(softwareModuleMetadata.getId());
} }
metadata.forEach(m -> entityManager.merge(m.getSoftwareModule()).setLastModifiedAt(-1L)); metadata.forEach(m -> entityManager.merge((JpaSoftwareModule) m.getSoftwareModule()).setLastModifiedAt(-1L));
return softwareModuleMetadataRepository.save(metadata); return new ArrayList<>(softwareModuleMetadataRepository.save(metadata));
} }
@Override @Override
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public SoftwareModuleMetadata updateSoftwareModuleMetadata(final SoftwareModuleMetadata metadata) { public SoftwareModuleMetadata updateSoftwareModuleMetadata(final SoftwareModuleMetadata md) {
final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) md;
// check if exists otherwise throw entity not found exception // check if exists otherwise throw entity not found exception
findSoftwareModuleMetadata(metadata.getId()); findSoftwareModuleMetadata(metadata.getId());
// touch it to update the lock revision because we are modifying the // touch it to update the lock revision because we are modifying the
// software module // software module
// indirectly // indirectly
entityManager.merge(metadata.getSoftwareModule()).setLastModifiedAt(-1L); entityManager.merge((JpaSoftwareModule) metadata.getSoftwareModule()).setLastModifiedAt(-1L);
return softwareModuleMetadataRepository.save(metadata); return softwareModuleMetadataRepository.save(metadata);
} }
@@ -563,15 +603,18 @@ public class JpaSoftwareManagement implements SoftwareManagement {
@Override @Override
public Page<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(final Long softwareModuleId, public Page<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(final Long softwareModuleId,
final Specification<SoftwareModuleMetadata> spec, final Pageable pageable) { final String rsqlParam, final Pageable pageable) {
return softwareModuleMetadataRepository
.findAll( final Specification<JpaSoftwareModuleMetadata> spec = RSQLUtility.parse(rsqlParam,
(Specification<SoftwareModuleMetadata>) (root, query, SoftwareModuleMetadataFields.class);
cb) -> cb.and( return convertSmMdPage(
cb.equal(root.get(SoftwareModuleMetadata_.softwareModule) softwareModuleMetadataRepository
.get(SoftwareModule_.id), softwareModuleId), .findAll(
(Specification<JpaSoftwareModuleMetadata>) (root, query, cb) -> cb.and(
cb.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule)
.get(JpaSoftwareModule_.id), softwareModuleId),
spec.toPredicate(root, query, cb)), spec.toPredicate(root, query, cb)),
pageable); pageable));
} }
@Override @Override
@@ -609,4 +652,16 @@ public class JpaSoftwareManagement implements SoftwareManagement {
return types.stream().map(this::createSoftwareModuleType).collect(Collectors.toList()); return types.stream().map(this::createSoftwareModuleType).collect(Collectors.toList());
} }
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public SoftwareModuleType generateSoftwareModuleType() {
return new JpaSoftwareModuleType();
}
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public SoftwareModule generateSoftwareModule() {
return new JpaSoftwareModule();
}
} }

View File

@@ -20,6 +20,9 @@ import org.eclipse.hawkbit.report.model.SystemUsageReport;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TenantStatsManagement; import org.eclipse.hawkbit.repository.TenantStatsManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
import org.eclipse.hawkbit.repository.jpa.model.JpaTenantMetaData;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.repository.model.TenantMetaData;
@@ -167,7 +170,7 @@ public class JpaSystemManagement implements SystemManagement {
try { try {
createInitialTenant.set(tenant); createInitialTenant.set(tenant);
cacheManager.getCache("currentTenant").evict(currentTenantKeyGenerator().generate(null, null)); cacheManager.getCache("currentTenant").evict(currentTenantKeyGenerator().generate(null, null));
return tenantMetaDataRepository.save(new TenantMetaData(createStandardSoftwareDataSetup(), tenant)); return tenantMetaDataRepository.save(new JpaTenantMetaData(createStandardSoftwareDataSetup(), tenant));
} finally { } finally {
createInitialTenant.remove(); createInitialTenant.remove();
} }
@@ -253,27 +256,26 @@ public class JpaSystemManagement implements SystemManagement {
throw new EntityNotFoundException("Metadata does not exist: " + metaData.getId()); throw new EntityNotFoundException("Metadata does not exist: " + metaData.getId());
} }
return tenantMetaDataRepository.save(metaData); return tenantMetaDataRepository.save((JpaTenantMetaData) metaData);
} }
private DistributionSetType createStandardSoftwareDataSetup() { private DistributionSetType createStandardSoftwareDataSetup() {
final SoftwareModuleType eclApp = softwareModuleTypeRepository.save(new SoftwareModuleType("application", final SoftwareModuleType eclApp = softwareModuleTypeRepository.save(new JpaSoftwareModuleType("application",
"ECL Application", "Edge Controller Linux base application type", 1)); "ECL Application", "Edge Controller Linux base application type", 1));
final SoftwareModuleType eclOs = softwareModuleTypeRepository final SoftwareModuleType eclOs = softwareModuleTypeRepository.save(
.save(new SoftwareModuleType("os", "ECL OS", "Edge Controller Linux operation system image type", 1)); new JpaSoftwareModuleType("os", "ECL OS", "Edge Controller Linux operation system image type", 1));
final SoftwareModuleType eclJvm = softwareModuleTypeRepository.save( final SoftwareModuleType eclJvm = softwareModuleTypeRepository.save(
new SoftwareModuleType("runtime", "ECL JVM", "Edge Controller Linux java virtual machine type.", 1)); new JpaSoftwareModuleType("runtime", "ECL JVM", "Edge Controller Linux java virtual machine type.", 1));
distributionSetTypeRepository.save( distributionSetTypeRepository.save((JpaDistributionSetType) new JpaDistributionSetType("ecl_os", "OS only",
new DistributionSetType("ecl_os", "OS only", "Standard Edge Controller Linux distribution set type.") "Standard Edge Controller Linux distribution set type.").addMandatoryModuleType(eclOs));
.addMandatoryModuleType(eclOs));
distributionSetTypeRepository.save(new DistributionSetType("ecl_os_app", "OS with optional app", distributionSetTypeRepository.save((JpaDistributionSetType) new JpaDistributionSetType("ecl_os_app",
"Standard Edge Controller Linux distribution set type. OS only.").addMandatoryModuleType(eclOs) "OS with optional app", "Standard Edge Controller Linux distribution set type. OS only.")
.addOptionalModuleType(eclApp)); .addMandatoryModuleType(eclOs).addOptionalModuleType(eclApp));
return distributionSetTypeRepository return distributionSetTypeRepository.save(
.save(new DistributionSetType("ecl_os_app_jvm", "OS with optional app and jvm", (JpaDistributionSetType) new JpaDistributionSetType("ecl_os_app_jvm", "OS with optional app and jvm",
"Standard Edge Controller Linux distribution set type. OS with optional application.") "Standard Edge Controller Linux distribution set type. OS with optional application.")
.addMandatoryModuleType(eclOs).addOptionalModuleType(eclApp) .addMandatoryModuleType(eclOs).addOptionalModuleType(eclApp)
.addOptionalModuleType(eclJvm)); .addOptionalModuleType(eclJvm));

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@@ -21,20 +22,26 @@ import org.eclipse.hawkbit.eventbus.event.TargetTagCreatedBulkEvent;
import org.eclipse.hawkbit.eventbus.event.TargetTagDeletedEvent; import org.eclipse.hawkbit.eventbus.event.TargetTagDeletedEvent;
import org.eclipse.hawkbit.eventbus.event.TargetTagUpdateEvent; import org.eclipse.hawkbit.eventbus.event.TargetTagUpdateEvent;
import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.repository.TagFields;
import org.eclipse.hawkbit.repository.TagManagement; import org.eclipse.hawkbit.repository.TagManagement;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -86,7 +93,7 @@ public class JpaTagManagement implements TagManagement {
throw new EntityAlreadyExistsException(); throw new EntityAlreadyExistsException();
} }
final TargetTag save = targetTagRepository.save(targetTag); final TargetTag save = targetTagRepository.save((JpaTargetTag) targetTag);
afterCommit afterCommit
.afterCommit(() -> eventBus.post(new TargetTagCreatedBulkEvent(tenantAware.getCurrentTenant(), save))); .afterCommit(() -> eventBus.post(new TargetTagCreatedBulkEvent(tenantAware.getCurrentTenant(), save)));
@@ -97,13 +104,17 @@ public class JpaTagManagement implements TagManagement {
@Override @Override
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public List<TargetTag> createTargetTags(final Iterable<TargetTag> targetTags) { public List<TargetTag> createTargetTags(final Collection<TargetTag> tt) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final Collection<JpaTargetTag> targetTags = (Collection) tt;
targetTags.forEach(tag -> { targetTags.forEach(tag -> {
if (tag.getId() != null) { if (tag.getId() != null) {
throw new EntityAlreadyExistsException(); throw new EntityAlreadyExistsException();
} }
}); });
final List<TargetTag> save = targetTagRepository.save(targetTags);
final List<TargetTag> save = new ArrayList<>(targetTagRepository.save(targetTags));
afterCommit afterCommit
.afterCommit(() -> eventBus.post(new TargetTagCreatedBulkEvent(tenantAware.getCurrentTenant(), save))); .afterCommit(() -> eventBus.post(new TargetTagCreatedBulkEvent(tenantAware.getCurrentTenant(), save)));
return save; return save;
@@ -113,10 +124,10 @@ public class JpaTagManagement implements TagManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void deleteTargetTag(final String targetTagName) { public void deleteTargetTag(final String targetTagName) {
final TargetTag tag = targetTagRepository.findByNameEquals(targetTagName); final JpaTargetTag tag = targetTagRepository.findByNameEquals(targetTagName);
final List<Target> changed = new LinkedList<>(); final List<JpaTarget> changed = new LinkedList<>();
for (final Target target : targetRepository.findByTag(tag)) { for (final JpaTarget target : targetRepository.findByTag(tag)) {
target.getTags().remove(tag); target.getTags().remove(tag);
changed.add(target); changed.add(target);
} }
@@ -133,12 +144,22 @@ public class JpaTagManagement implements TagManagement {
@Override @Override
public List<TargetTag> findAllTargetTags() { public List<TargetTag> findAllTargetTags() {
return targetTagRepository.findAll(); return new ArrayList<>(targetTagRepository.findAll());
} }
@Override @Override
public Page<TargetTag> findAllTargetTags(final Specification<TargetTag> spec, final Pageable pageable) { public Page<TargetTag> findAllTargetTags(final String rsqlParam, final Pageable pageable) {
return targetTagRepository.findAll(spec, pageable);
final Specification<JpaTargetTag> spec = RSQLUtility.parse(rsqlParam, TagFields.class);
return convertTPage(targetTagRepository.findAll(spec, pageable));
}
private static Page<TargetTag> convertTPage(final Page<JpaTargetTag> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
}
private static Page<DistributionSetTag> convertDsPage(final Page<JpaDistributionSetTag> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
@Override @Override
@@ -152,7 +173,7 @@ public class JpaTagManagement implements TagManagement {
public TargetTag updateTargetTag(final TargetTag targetTag) { public TargetTag updateTargetTag(final TargetTag targetTag) {
checkNotNull(targetTag.getName()); checkNotNull(targetTag.getName());
checkNotNull(targetTag.getId()); checkNotNull(targetTag.getId());
final TargetTag save = targetTagRepository.save(targetTag); final TargetTag save = targetTagRepository.save((JpaTargetTag) targetTag);
afterCommit.afterCommit(() -> eventBus.post(new TargetTagUpdateEvent(save))); afterCommit.afterCommit(() -> eventBus.post(new TargetTagUpdateEvent(save)));
return save; return save;
} }
@@ -174,7 +195,7 @@ public class JpaTagManagement implements TagManagement {
throw new EntityAlreadyExistsException(); throw new EntityAlreadyExistsException();
} }
final DistributionSetTag save = distributionSetTagRepository.save(distributionSetTag); final DistributionSetTag save = distributionSetTagRepository.save((JpaDistributionSetTag) distributionSetTag);
afterCommit.afterCommit( afterCommit.afterCommit(
() -> eventBus.post(new DistributionSetTagCreatedBulkEvent(tenantAware.getCurrentTenant(), save))); () -> eventBus.post(new DistributionSetTagCreatedBulkEvent(tenantAware.getCurrentTenant(), save)));
@@ -184,14 +205,17 @@ public class JpaTagManagement implements TagManagement {
@Override @Override
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public List<DistributionSetTag> createDistributionSetTags( public List<DistributionSetTag> createDistributionSetTags(final Collection<DistributionSetTag> dst) {
final Collection<DistributionSetTag> distributionSetTags) {
@SuppressWarnings({ "rawtypes", "unchecked" })
final Collection<JpaDistributionSetTag> distributionSetTags = (Collection) dst;
for (final DistributionSetTag dsTag : distributionSetTags) { for (final DistributionSetTag dsTag : distributionSetTags) {
if (dsTag.getId() != null) { if (dsTag.getId() != null) {
throw new EntityAlreadyExistsException(); throw new EntityAlreadyExistsException();
} }
} }
final List<DistributionSetTag> save = distributionSetTagRepository.save(distributionSetTags); final List<DistributionSetTag> save = new ArrayList<>(distributionSetTagRepository.save(distributionSetTags));
afterCommit.afterCommit( afterCommit.afterCommit(
() -> eventBus.post(new DistributionSetTagCreatedBulkEvent(tenantAware.getCurrentTenant(), save))); () -> eventBus.post(new DistributionSetTagCreatedBulkEvent(tenantAware.getCurrentTenant(), save)));
@@ -202,10 +226,10 @@ public class JpaTagManagement implements TagManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void deleteDistributionSetTag(final String tagName) { public void deleteDistributionSetTag(final String tagName) {
final DistributionSetTag tag = distributionSetTagRepository.findByNameEquals(tagName); final JpaDistributionSetTag tag = distributionSetTagRepository.findByNameEquals(tagName);
final List<DistributionSet> changed = new LinkedList<>(); final List<JpaDistributionSet> changed = new LinkedList<>();
for (final DistributionSet set : distributionSetRepository.findByTag(tag)) { for (final JpaDistributionSet set : distributionSetRepository.findByTag(tag)) {
set.getTags().remove(tag); set.getTags().remove(tag);
changed.add(set); changed.add(set);
} }
@@ -224,7 +248,7 @@ public class JpaTagManagement implements TagManagement {
public DistributionSetTag updateDistributionSetTag(final DistributionSetTag distributionSetTag) { public DistributionSetTag updateDistributionSetTag(final DistributionSetTag distributionSetTag) {
checkNotNull(distributionSetTag.getName()); checkNotNull(distributionSetTag.getName());
checkNotNull(distributionSetTag.getId()); checkNotNull(distributionSetTag.getId());
final DistributionSetTag save = distributionSetTagRepository.save(distributionSetTag); final DistributionSetTag save = distributionSetTagRepository.save((JpaDistributionSetTag) distributionSetTag);
afterCommit.afterCommit(() -> eventBus.post(new DistributionSetTagUpdateEvent(save))); afterCommit.afterCommit(() -> eventBus.post(new DistributionSetTagUpdateEvent(save)));
return save; return save;
@@ -232,7 +256,7 @@ public class JpaTagManagement implements TagManagement {
@Override @Override
public List<DistributionSetTag> findAllDistributionSetTags() { public List<DistributionSetTag> findAllDistributionSetTags() {
return distributionSetTagRepository.findAll(); return new ArrayList<>(distributionSetTagRepository.findAll());
} }
@Override @Override
@@ -247,18 +271,31 @@ public class JpaTagManagement implements TagManagement {
@Override @Override
public Page<TargetTag> findAllTargetTags(final Pageable pageReq) { public Page<TargetTag> findAllTargetTags(final Pageable pageReq) {
return targetTagRepository.findAll(pageReq); return convertTPage(targetTagRepository.findAll(pageReq));
} }
@Override @Override
public Page<DistributionSetTag> findAllDistributionSetTags(final Pageable pageReq) { public Page<DistributionSetTag> findAllDistributionSetTags(final Pageable pageReq) {
return distributionSetTagRepository.findAll(pageReq); return convertDsPage(distributionSetTagRepository.findAll(pageReq));
} }
@Override @Override
public Page<DistributionSetTag> findAllDistributionSetTags(final Specification<DistributionSetTag> spec, public Page<DistributionSetTag> findAllDistributionSetTags(final String rsqlParam, final Pageable pageable) {
final Pageable pageable) { final Specification<JpaDistributionSetTag> spec = RSQLUtility.parse(rsqlParam, TagFields.class);
return distributionSetTagRepository.findAll(spec, pageable);
return convertDsPage(distributionSetTagRepository.findAll(spec, pageable));
}
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public TargetTag generateTargetTag() {
return new JpaTargetTag();
}
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public DistributionSetTag generateDistributionSetTag() {
return new JpaDistributionSetTag();
} }
} }

View File

@@ -13,11 +13,13 @@ import java.util.List;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.repository.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.specifications.TargetFilterQuerySpecification;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.domain.Specifications; import org.springframework.data.jpa.domain.Specifications;
@@ -50,7 +52,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
if (targetFilterQueryRepository.findByName(customTargetFilter.getName()) != null) { if (targetFilterQueryRepository.findByName(customTargetFilter.getName()) != null) {
throw new EntityAlreadyExistsException(customTargetFilter.getName()); throw new EntityAlreadyExistsException(customTargetFilter.getName());
} }
return targetFilterQueryRepository.save(customTargetFilter); return targetFilterQueryRepository.save((JpaTargetFilterQuery) customTargetFilter);
} }
@Override @Override
@@ -62,25 +64,29 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
@Override @Override
public Page<TargetFilterQuery> findAllTargetFilterQuery(final Pageable pageable) { public Page<TargetFilterQuery> findAllTargetFilterQuery(final Pageable pageable) {
return targetFilterQueryRepository.findAll(pageable); return convertPage(targetFilterQueryRepository.findAll(pageable));
}
private static Page<TargetFilterQuery> convertPage(final Page<JpaTargetFilterQuery> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
@Override @Override
public Page<TargetFilterQuery> findTargetFilterQueryByFilters(final Pageable pageable, final String name) { public Page<TargetFilterQuery> findTargetFilterQueryByFilters(final Pageable pageable, final String name) {
final List<Specification<TargetFilterQuery>> specList = new ArrayList<>(); final List<Specification<JpaTargetFilterQuery>> specList = new ArrayList<>();
if (!Strings.isNullOrEmpty(name)) { if (!Strings.isNullOrEmpty(name)) {
specList.add(TargetFilterQuerySpecification.likeName(name)); specList.add(TargetFilterQuerySpecification.likeName(name));
} }
return findTargetFilterQueryByCriteriaAPI(pageable, specList); return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList));
} }
private Page<TargetFilterQuery> findTargetFilterQueryByCriteriaAPI(final Pageable pageable, private Page<JpaTargetFilterQuery> findTargetFilterQueryByCriteriaAPI(final Pageable pageable,
final List<Specification<TargetFilterQuery>> specList) { final List<Specification<JpaTargetFilterQuery>> specList) {
if (specList == null || specList.isEmpty()) { if (specList == null || specList.isEmpty()) {
return targetFilterQueryRepository.findAll(pageable); return targetFilterQueryRepository.findAll(pageable);
} }
final Specifications<TargetFilterQuery> specs = SpecificationsBuilder.combineWithAnd(specList); final Specifications<JpaTargetFilterQuery> specs = SpecificationsBuilder.combineWithAnd(specList);
return targetFilterQueryRepository.findAll(specs, pageable); return targetFilterQueryRepository.findAll(specs, pageable);
} }
@@ -99,7 +105,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public TargetFilterQuery updateTargetFilterQuery(final TargetFilterQuery targetFilterQuery) { public TargetFilterQuery updateTargetFilterQuery(final TargetFilterQuery targetFilterQuery) {
Assert.notNull(targetFilterQuery.getId()); Assert.notNull(targetFilterQuery.getId());
return targetFilterQueryRepository.save(targetFilterQuery); return targetFilterQueryRepository.save((JpaTargetFilterQuery) targetFilterQuery);
} }
} }

View File

@@ -33,22 +33,25 @@ import org.eclipse.hawkbit.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.repository.TargetFields; import org.eclipse.hawkbit.repository.TargetFields;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.model.DistributionSet_; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.repository.model.TargetIdName; import org.eclipse.hawkbit.repository.model.TargetIdName;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetInfo_;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.Target_;
import org.eclipse.hawkbit.repository.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.specifications.TargetSpecifications;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl; import org.springframework.data.domain.SliceImpl;
@@ -58,6 +61,7 @@ import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -121,7 +125,8 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public List<Target> findTargetByControllerID(final Collection<String> controllerIDs) { public List<Target> findTargetByControllerID(final Collection<String> controllerIDs) {
return targetRepository.findAll(TargetSpecifications.byControllerIdWithStatusAndAssignedInJoin(controllerIDs)); return new ArrayList<>(targetRepository
.findAll(TargetSpecifications.byControllerIdWithStatusAndAssignedInJoin(controllerIDs)));
} }
@Override @Override
@@ -134,28 +139,27 @@ public class JpaTargetManagement implements TargetManagement {
// workarround - no join fetch allowed that is why we need specification // workarround - no join fetch allowed that is why we need specification
// instead of query for // instead of query for
// count() of Pageable // count() of Pageable
final Specification<Target> spec = (root, query, cb) -> { final Specification<JpaTarget> spec = (root, query, cb) -> {
if (!query.getResultType().isAssignableFrom(Long.class)) { if (!query.getResultType().isAssignableFrom(Long.class)) {
root.fetch(Target_.targetInfo); root.fetch(JpaTarget_.targetInfo);
} }
return cb.conjunction(); return cb.conjunction();
}; };
return criteriaNoCountDao.findAll(spec, pageable, Target.class); return convertPage(criteriaNoCountDao.findAll(spec, pageable, JpaTarget.class));
} }
@Override @Override
public Slice<Target> findTargetsAll(final TargetFilterQuery targetFilterQuery, final Pageable pageable) { public Slice<Target> findTargetsAll(final TargetFilterQuery targetFilterQuery, final Pageable pageable) {
return findTargetsAll(RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class), pageable); return findTargetsBySpec(RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class), pageable);
} }
@Override @Override
public Slice<Target> findTargetsAll(final String targetFilterQuery, final Pageable pageable) { public Page<Target> findTargetsAll(final String targetFilterQuery, final Pageable pageable) {
return findTargetsAll(RSQLUtility.parse(targetFilterQuery, TargetFields.class), pageable); return findTargetsBySpec(RSQLUtility.parse(targetFilterQuery, TargetFields.class), pageable);
} }
@Override private Page<Target> findTargetsBySpec(final Specification<JpaTarget> spec, final Pageable pageable) {
public Page<Target> findTargetsAll(final Specification<Target> spec, final Pageable pageable) { return convertPage(targetRepository.findAll(spec, pageable));
return targetRepository.findAll(spec, pageable);
} }
@Override @Override
@@ -171,16 +175,23 @@ public class JpaTargetManagement implements TargetManagement {
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public Target updateTarget(final Target target) { public Target updateTarget(final Target target) {
Assert.notNull(target.getId()); Assert.notNull(target.getId());
target.setNew(false);
return targetRepository.save(target); final JpaTarget toUpdate = (JpaTarget) target;
toUpdate.setNew(false);
return targetRepository.save(toUpdate);
} }
@Override @Override
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public List<Target> updateTargets(final Iterable<Target> targets) { public List<Target> updateTargets(final Collection<Target> targets) {
targets.forEach(target -> target.setNew(false));
return targetRepository.save(targets); @SuppressWarnings({ "unchecked", "rawtypes" })
final Collection<JpaTarget> toUpdate = (Collection) targets;
toUpdate.forEach(target -> target.setNew(false));
return new ArrayList<>(targetRepository.save(toUpdate));
} }
@Override @Override
@@ -206,11 +217,22 @@ public class JpaTargetManagement implements TargetManagement {
} }
@Override @Override
public Page<Target> findTargetByAssignedDistributionSet(final Long distributionSetID, public Page<Target> findTargetByAssignedDistributionSet(final Long distributionSetID, final String rsqlParam,
final Specification<Target> spec, final Pageable pageReq) { final Pageable pageReq) {
return targetRepository.findAll((Specification<Target>) (root, query, cb) -> cb.and(
final Specification<JpaTarget> spec = RSQLUtility.parse(rsqlParam, TargetFields.class);
return convertPage(targetRepository.findAll((Specification<JpaTarget>) (root, query, cb) -> cb.and(
TargetSpecifications.hasAssignedDistributionSet(distributionSetID).toPredicate(root, query, cb), TargetSpecifications.hasAssignedDistributionSet(distributionSetID).toPredicate(root, query, cb),
spec.toPredicate(root, query, cb)), pageReq); spec.toPredicate(root, query, cb)), pageReq));
}
private static Page<Target> convertPage(final Page<JpaTarget> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
}
private static Slice<Target> convertPage(final Slice<JpaTarget> findAll) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()));
} }
@Override @Override
@@ -219,11 +241,14 @@ public class JpaTargetManagement implements TargetManagement {
} }
@Override @Override
public Page<Target> findTargetByInstalledDistributionSet(final Long distributionSetId, public Page<Target> findTargetByInstalledDistributionSet(final Long distributionSetId, final String rsqlParam,
final Specification<Target> spec, final Pageable pageable) { final Pageable pageable) {
return targetRepository.findAll((Specification<Target>) (root, query, cb) -> cb.and(
final Specification<JpaTarget> spec = RSQLUtility.parse(rsqlParam, TargetFields.class);
return convertPage(targetRepository.findAll((Specification<JpaTarget>) (root, query, cb) -> cb.and(
TargetSpecifications.hasInstalledDistributionSet(distributionSetId).toPredicate(root, query, cb), TargetSpecifications.hasInstalledDistributionSet(distributionSetId).toPredicate(root, query, cb),
spec.toPredicate(root, query, cb)), pageable); spec.toPredicate(root, query, cb)), pageable));
} }
@Override @Override
@@ -235,7 +260,7 @@ public class JpaTargetManagement implements TargetManagement {
public Slice<Target> findTargetByFilters(final Pageable pageable, final Collection<TargetUpdateStatus> status, public Slice<Target> findTargetByFilters(final Pageable pageable, final Collection<TargetUpdateStatus> status,
final String searchText, final Long installedOrAssignedDistributionSetId, final String searchText, final Long installedOrAssignedDistributionSetId,
final Boolean selectTargetWithNoTag, final String... tagNames) { final Boolean selectTargetWithNoTag, final String... tagNames) {
final List<Specification<Target>> specList = buildSpecificationList(status, searchText, final List<Specification<JpaTarget>> specList = buildSpecificationList(status, searchText,
installedOrAssignedDistributionSetId, selectTargetWithNoTag, true, tagNames); installedOrAssignedDistributionSetId, selectTargetWithNoTag, true, tagNames);
return findByCriteriaAPI(pageable, specList); return findByCriteriaAPI(pageable, specList);
} }
@@ -244,15 +269,15 @@ public class JpaTargetManagement implements TargetManagement {
public Long countTargetByFilters(final Collection<TargetUpdateStatus> status, final String searchText, public Long countTargetByFilters(final Collection<TargetUpdateStatus> status, final String searchText,
final Long installedOrAssignedDistributionSetId, final Boolean selectTargetWithNoTag, final Long installedOrAssignedDistributionSetId, final Boolean selectTargetWithNoTag,
final String... tagNames) { final String... tagNames) {
final List<Specification<Target>> specList = buildSpecificationList(status, searchText, final List<Specification<JpaTarget>> specList = buildSpecificationList(status, searchText,
installedOrAssignedDistributionSetId, selectTargetWithNoTag, true, tagNames); installedOrAssignedDistributionSetId, selectTargetWithNoTag, true, tagNames);
return countByCriteriaAPI(specList); return countByCriteriaAPI(specList);
} }
private static List<Specification<Target>> buildSpecificationList(final Collection<TargetUpdateStatus> status, private static List<Specification<JpaTarget>> buildSpecificationList(final Collection<TargetUpdateStatus> status,
final String searchText, final Long installedOrAssignedDistributionSetId, final String searchText, final Long installedOrAssignedDistributionSetId,
final Boolean selectTargetWithNoTag, final boolean fetch, final String... tagNames) { final Boolean selectTargetWithNoTag, final boolean fetch, final String... tagNames) {
final List<Specification<Target>> specList = new ArrayList<>(); final List<Specification<JpaTarget>> specList = new ArrayList<>();
if (status != null && !status.isEmpty()) { if (status != null && !status.isEmpty()) {
specList.add(TargetSpecifications.hasTargetUpdateStatus(status, fetch)); specList.add(TargetSpecifications.hasTargetUpdateStatus(status, fetch));
} }
@@ -269,14 +294,15 @@ public class JpaTargetManagement implements TargetManagement {
return specList; return specList;
} }
private Slice<Target> findByCriteriaAPI(final Pageable pageable, final List<Specification<Target>> specList) { private Slice<Target> findByCriteriaAPI(final Pageable pageable, final List<Specification<JpaTarget>> specList) {
if (specList == null || specList.isEmpty()) { if (specList == null || specList.isEmpty()) {
return criteriaNoCountDao.findAll(pageable, Target.class); return convertPage(criteriaNoCountDao.findAll(pageable, JpaTarget.class));
} }
return criteriaNoCountDao.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable, Target.class); return convertPage(
criteriaNoCountDao.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable, JpaTarget.class));
} }
private Long countByCriteriaAPI(final List<Specification<Target>> specList) { private Long countByCriteriaAPI(final List<Specification<JpaTarget>> specList) {
if (specList == null || specList.isEmpty()) { if (specList == null || specList.isEmpty()) {
return targetRepository.count(); return targetRepository.count();
} }
@@ -298,7 +324,7 @@ public class JpaTargetManagement implements TargetManagement {
public TargetTagAssignmentResult toggleTagAssignment(final Collection<String> targetIds, final String tagName) { public TargetTagAssignmentResult toggleTagAssignment(final Collection<String> targetIds, final String tagName) {
final TargetTag tag = targetTagRepository.findByNameEquals(tagName); final TargetTag tag = targetTagRepository.findByNameEquals(tagName);
final List<Target> alreadyAssignedTargets = targetRepository.findByTagNameAndControllerIdIn(tagName, targetIds); final List<Target> alreadyAssignedTargets = targetRepository.findByTagNameAndControllerIdIn(tagName, targetIds);
final List<Target> allTargets = targetRepository final List<JpaTarget> allTargets = targetRepository
.findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(targetIds)); .findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(targetIds));
// all are already assigned -> unassign // all are already assigned -> unassign
@@ -315,7 +341,7 @@ public class JpaTargetManagement implements TargetManagement {
// some or none are assigned -> assign // some or none are assigned -> assign
allTargets.forEach(target -> target.getTags().add(tag)); allTargets.forEach(target -> target.getTags().add(tag));
final TargetTagAssignmentResult result = new TargetTagAssignmentResult(alreadyAssignedTargets.size(), final TargetTagAssignmentResult result = new TargetTagAssignmentResult(alreadyAssignedTargets.size(),
allTargets.size(), 0, targetRepository.save(allTargets), Collections.emptyList(), tag); allTargets.size(), 0, new ArrayList<>(targetRepository.save(allTargets)), Collections.emptyList(), tag);
afterCommit.afterCommit(() -> eventBus.post(new TargetTagAssigmentResultEvent(result))); afterCommit.afterCommit(() -> eventBus.post(new TargetTagAssigmentResultEvent(result)));
@@ -328,11 +354,11 @@ public class JpaTargetManagement implements TargetManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public List<Target> assignTag(final Collection<String> targetIds, final TargetTag tag) { public List<Target> assignTag(final Collection<String> targetIds, final TargetTag tag) {
final List<Target> allTargets = targetRepository final List<JpaTarget> allTargets = targetRepository
.findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(targetIds)); .findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(targetIds));
allTargets.forEach(target -> target.getTags().add(tag)); allTargets.forEach(target -> target.getTags().add(tag));
final List<Target> save = targetRepository.save(allTargets); final List<Target> save = new ArrayList<>(targetRepository.save(allTargets));
afterCommit.afterCommit(() -> { afterCommit.afterCommit(() -> {
final TargetTagAssignmentResult assigmentResult = new TargetTagAssignmentResult(0, save.size(), 0, save, final TargetTagAssignmentResult assigmentResult = new TargetTagAssignmentResult(0, save.size(), 0, save,
@@ -344,9 +370,11 @@ public class JpaTargetManagement implements TargetManagement {
} }
private List<Target> unAssignTag(final Collection<Target> targets, final TargetTag tag) { private List<Target> unAssignTag(final Collection<Target> targets, final TargetTag tag) {
targets.forEach(target -> target.getTags().remove(tag)); final Collection<JpaTarget> toUnassign = (Collection) targets;
final List<Target> save = targetRepository.save(targets); toUnassign.forEach(target -> target.getTags().remove(tag));
final List<Target> save = new ArrayList<>(targetRepository.save(toUnassign));
afterCommit.afterCommit(() -> { afterCommit.afterCommit(() -> {
final TargetTagAssignmentResult assigmentResult = new TargetTagAssignmentResult(0, 0, save.size(), final TargetTagAssignmentResult assigmentResult = new TargetTagAssignmentResult(0, 0, save.size(),
Collections.emptyList(), save, tag); Collections.emptyList(), save, tag);
@@ -366,8 +394,9 @@ public class JpaTargetManagement implements TargetManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public Target unAssignTag(final String controllerID, final TargetTag targetTag) { public Target unAssignTag(final String controllerID, final TargetTag targetTag) {
final List<Target> allTargets = targetRepository // TODO : optimize this, findone?
.findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(Arrays.asList(controllerID))); final List<Target> allTargets = new ArrayList<>(targetRepository
.findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(Arrays.asList(controllerID))));
final List<Target> unAssignTag = unAssignTag(allTargets, targetTag); final List<Target> unAssignTag = unAssignTag(allTargets, targetTag);
return unAssignTag.isEmpty() ? null : unAssignTag.get(0); return unAssignTag.isEmpty() ? null : unAssignTag.get(0);
} }
@@ -378,20 +407,20 @@ public class JpaTargetManagement implements TargetManagement {
final Collection<TargetUpdateStatus> filterByStatus, final String filterBySearchText, final Collection<TargetUpdateStatus> filterByStatus, final String filterBySearchText,
final Boolean selectTargetWithNoTag, final String... filterByTagNames) { final Boolean selectTargetWithNoTag, final String... filterByTagNames) {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Target> query = cb.createQuery(Target.class); final CriteriaQuery<JpaTarget> query = cb.createQuery(JpaTarget.class);
final Root<Target> targetRoot = query.from(Target.class); final Root<JpaTarget> targetRoot = query.from(JpaTarget.class);
// necessary joins for the select // necessary joins for the select
final Join<Target, TargetInfo> targetInfo = (Join<Target, TargetInfo>) targetRoot.fetch(Target_.targetInfo, final Join<JpaTarget, JpaTargetInfo> targetInfo = (Join<JpaTarget, JpaTargetInfo>) targetRoot
JoinType.LEFT); .fetch(JpaTarget_.targetInfo, JoinType.LEFT);
// select case expression to retrieve the case value as a column to be // select case expression to retrieve the case value as a column to be
// able to order based on // able to order based on
// this column, installed first,... // this column, installed first,...
final Expression<Object> selectCase = cb.selectCase() final Expression<Object> selectCase = cb.selectCase()
.when(cb.equal(targetInfo.get(TargetInfo_.installedDistributionSet).get(DistributionSet_.id), .when(cb.equal(targetInfo.get(JpaTargetInfo_.installedDistributionSet).get(JpaDistributionSet_.id),
orderByDistributionId), 1) orderByDistributionId), 1)
.when(cb.equal(targetRoot.get(Target_.assignedDistributionSet).get(DistributionSet_.id), .when(cb.equal(targetRoot.get(JpaTarget_.assignedDistributionSet).get(JpaDistributionSet_.id),
orderByDistributionId), 2) orderByDistributionId), 2)
.otherwise(100); .otherwise(100);
// multiselect statement order by the select case and controllerId // multiselect statement order by the select case and controllerId
@@ -409,7 +438,7 @@ public class JpaTargetManagement implements TargetManagement {
query.where(specificationsForMultiSelect); query.where(specificationsForMultiSelect);
} }
// add the order to the multi select first based on the selectCase // add the order to the multi select first based on the selectCase
query.orderBy(cb.asc(selectCase), cb.desc(targetRoot.get(Target_.id))); query.orderBy(cb.asc(selectCase), cb.desc(targetRoot.get(JpaTarget_.id)));
// the result is a Object[] due the fact that the selectCase is an extra // the result is a Object[] due the fact that the selectCase is an extra
// column, so it cannot // column, so it cannot
// be mapped directly to a Target entity because the selectCase is not a // be mapped directly to a Target entity because the selectCase is not a
@@ -419,14 +448,14 @@ public class JpaTargetManagement implements TargetManagement {
// multiselect order) of the array and // multiselect order) of the array and
// the 2nd contains the selectCase int value. // the 2nd contains the selectCase int value.
final int pageSize = pageable.getPageSize(); final int pageSize = pageable.getPageSize();
final List<Target> resultList = entityManager.createQuery(query).setFirstResult(pageable.getOffset()) final List<JpaTarget> resultList = entityManager.createQuery(query).setFirstResult(pageable.getOffset())
.setMaxResults(pageSize + 1).getResultList(); .setMaxResults(pageSize + 1).getResultList();
final boolean hasNext = resultList.size() > pageSize; final boolean hasNext = resultList.size() > pageSize;
return new SliceImpl<>(resultList, pageable, hasNext); return new SliceImpl<>(new ArrayList<>(resultList), pageable, hasNext);
} }
private static Predicate[] specificationsToPredicate(final List<Specification<Target>> specifications, private static Predicate[] specificationsToPredicate(final List<Specification<JpaTarget>> specifications,
final Root<Target> root, final CriteriaQuery<?> query, final CriteriaBuilder cb) { final Root<JpaTarget> root, final CriteriaQuery<?> query, final CriteriaBuilder cb) {
final Predicate[] predicates = new Predicate[specifications.size()]; final Predicate[] predicates = new Predicate[specifications.size()];
for (int index = 0; index < predicates.length; index++) { for (int index = 0; index < predicates.length; index++) {
predicates[index] = specifications.get(index).toPredicate(root, query, cb); predicates[index] = specifications.get(index).toPredicate(root, query, cb);
@@ -448,9 +477,9 @@ public class JpaTargetManagement implements TargetManagement {
public List<TargetIdName> findAllTargetIds() { public List<TargetIdName> findAllTargetIds() {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<TargetIdName> query = cb.createQuery(TargetIdName.class); final CriteriaQuery<TargetIdName> query = cb.createQuery(TargetIdName.class);
final Root<Target> targetRoot = query.from(Target.class); final Root<JpaTarget> targetRoot = query.from(JpaTarget.class);
return entityManager.createQuery(query.multiselect(targetRoot.get(Target_.id), return entityManager.createQuery(query.multiselect(targetRoot.get(JpaTarget_.id),
targetRoot.get(Target_.controllerId), targetRoot.get(Target_.name))).getResultList(); targetRoot.get(JpaTarget_.controllerId), targetRoot.get(JpaTarget_.name))).getResultList();
} }
@@ -461,16 +490,16 @@ public class JpaTargetManagement implements TargetManagement {
final String... filterByTagNames) { final String... filterByTagNames) {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class); final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
final Root<Target> targetRoot = query.from(Target.class); final Root<JpaTarget> targetRoot = query.from(JpaTarget.class);
List<Object[]> resultList; List<Object[]> resultList;
String sortProperty = Target_.id.getName(); String sortProperty = JpaTarget_.id.getName();
if (pageRequest.getSort() != null && pageRequest.getSort().iterator().hasNext()) { if (pageRequest.getSort() != null && pageRequest.getSort().iterator().hasNext()) {
sortProperty = pageRequest.getSort().iterator().next().getProperty(); sortProperty = pageRequest.getSort().iterator().next().getProperty();
} }
final CriteriaQuery<Object[]> multiselect = query.multiselect(targetRoot.get(Target_.id), final CriteriaQuery<Object[]> multiselect = query.multiselect(targetRoot.get(JpaTarget_.id),
targetRoot.get(Target_.controllerId), targetRoot.get(Target_.name), targetRoot.get(sortProperty)); targetRoot.get(JpaTarget_.controllerId), targetRoot.get(JpaTarget_.name), targetRoot.get(sortProperty));
final Predicate[] specificationsForMultiSelect = specificationsToPredicate( final Predicate[] specificationsForMultiSelect = specificationsToPredicate(
buildSpecificationList(filterByStatus, filterBySearchText, installedOrAssignedDistributionSetId, buildSpecificationList(filterByStatus, filterBySearchText, installedOrAssignedDistributionSetId,
@@ -493,18 +522,18 @@ public class JpaTargetManagement implements TargetManagement {
final TargetFilterQuery targetFilterQuery) { final TargetFilterQuery targetFilterQuery) {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class); final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
final Root<Target> targetRoot = query.from(Target.class); final Root<JpaTarget> targetRoot = query.from(JpaTarget.class);
String sortProperty = Target_.id.getName(); String sortProperty = JpaTarget_.id.getName();
if (pageRequest.getSort() != null && pageRequest.getSort().iterator().hasNext()) { if (pageRequest.getSort() != null && pageRequest.getSort().iterator().hasNext()) {
sortProperty = pageRequest.getSort().iterator().next().getProperty(); sortProperty = pageRequest.getSort().iterator().next().getProperty();
} }
final CriteriaQuery<Object[]> multiselect = query.multiselect(targetRoot.get(Target_.id), final CriteriaQuery<Object[]> multiselect = query.multiselect(targetRoot.get(JpaTarget_.id),
targetRoot.get(Target_.controllerId), targetRoot.get(Target_.name), targetRoot.get(sortProperty)); targetRoot.get(JpaTarget_.controllerId), targetRoot.get(JpaTarget_.name), targetRoot.get(sortProperty));
final Specification<Target> spec = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class); final Specification<JpaTarget> spec = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class);
final List<Specification<Target>> specList = new ArrayList<>(); final List<Specification<JpaTarget>> specList = new ArrayList<>();
specList.add(spec); specList.add(spec);
final Predicate[] specificationsForMultiSelect = specificationsToPredicate(specList, targetRoot, multiselect, final Predicate[] specificationsForMultiSelect = specificationsToPredicate(specList, targetRoot, multiselect,
@@ -529,16 +558,17 @@ public class JpaTargetManagement implements TargetManagement {
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@CacheEvict(value = { "targetsCreatedOverPeriod" }, allEntries = true) @CacheEvict(value = { "targetsCreatedOverPeriod" }, allEntries = true)
public Target createTarget(final Target target, final TargetUpdateStatus status, final Long lastTargetQuery, public Target createTarget(final Target t, final TargetUpdateStatus status, final Long lastTargetQuery,
final URI address) { final URI address) {
final JpaTarget target = (JpaTarget) t;
if (targetRepository.findByControllerId(target.getControllerId()) != null) { if (targetRepository.findByControllerId(target.getControllerId()) != null) {
throw new EntityAlreadyExistsException(target.getControllerId()); throw new EntityAlreadyExistsException(target.getControllerId());
} }
target.setNew(true); target.setNew(true);
final Target savedTarget = targetRepository.save(target); final JpaTarget savedTarget = targetRepository.save(target);
final TargetInfo targetInfo = savedTarget.getTargetInfo(); final JpaTargetInfo targetInfo = (JpaTargetInfo) savedTarget.getTargetInfo();
targetInfo.setUpdateStatus(status); targetInfo.setUpdateStatus(status);
if (lastTargetQuery != null) { if (lastTargetQuery != null) {
targetInfo.setLastTargetQuery(lastTargetQuery); targetInfo.setLastTargetQuery(lastTargetQuery);
@@ -596,24 +626,24 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public List<Target> findTargetsByTag(final String tagName) { public List<Target> findTargetsByTag(final String tagName) {
final TargetTag tag = targetTagRepository.findByNameEquals(tagName); final JpaTargetTag tag = targetTagRepository.findByNameEquals(tagName);
return targetRepository.findByTag(tag); return new ArrayList<>(targetRepository.findByTag(tag));
} }
@Override @Override
public Long countTargetByTargetFilterQuery(final TargetFilterQuery targetFilterQuery) { public Long countTargetByTargetFilterQuery(final TargetFilterQuery targetFilterQuery) {
final Specification<Target> specs = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class); final Specification<JpaTarget> specs = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class);
return targetRepository.count(specs); return targetRepository.count(specs);
} }
@Override @Override
public Long countTargetByTargetFilterQuery(final String targetFilterQuery) { public Long countTargetByTargetFilterQuery(final String targetFilterQuery) {
final Specification<Target> specs = RSQLUtility.parse(targetFilterQuery, TargetFields.class); final Specification<JpaTarget> specs = RSQLUtility.parse(targetFilterQuery, TargetFields.class);
return targetRepository.count(specs); return targetRepository.count(specs);
} }
private List<Object[]> getTargetIdNameResultSet(final Pageable pageRequest, final CriteriaBuilder cb, private List<Object[]> getTargetIdNameResultSet(final Pageable pageRequest, final CriteriaBuilder cb,
final Root<Target> targetRoot, final CriteriaQuery<Object[]> multiselect) { final Root<JpaTarget> targetRoot, final CriteriaQuery<Object[]> multiselect) {
List<Object[]> resultList; List<Object[]> resultList;
if (pageRequest.getSort() != null) { if (pageRequest.getSort() != null) {
final List<Order> orders = new ArrayList<>(); final List<Order> orders = new ArrayList<>();
@@ -633,4 +663,10 @@ public class JpaTargetManagement implements TargetManagement {
} }
return resultList; return resultList;
} }
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public Target generateTarget(final String controllerId) {
return new JpaTarget(controllerId);
}
} }

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.jpa.model.JpaTenantConfiguration;
import org.eclipse.hawkbit.repository.model.TenantConfiguration; import org.eclipse.hawkbit.repository.model.TenantConfiguration;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
@@ -134,16 +135,17 @@ public class JpaTenantConfigurationManagement implements EnvironmentAware, Tenan
configurationKey.validate(applicationContext, value); configurationKey.validate(applicationContext, value);
TenantConfiguration tenantConfiguration = tenantConfigurationRepository JpaTenantConfiguration tenantConfiguration = tenantConfigurationRepository
.findByKey(configurationKey.getKeyName()); .findByKey(configurationKey.getKeyName());
if (tenantConfiguration == null) { if (tenantConfiguration == null) {
tenantConfiguration = new TenantConfiguration(configurationKey.getKeyName(), value.toString()); tenantConfiguration = new JpaTenantConfiguration(configurationKey.getKeyName(), value.toString());
} else { } else {
tenantConfiguration.setValue(value.toString()); tenantConfiguration.setValue(value.toString());
} }
final TenantConfiguration updatedTenantConfiguration = tenantConfigurationRepository.save(tenantConfiguration); final JpaTenantConfiguration updatedTenantConfiguration = tenantConfigurationRepository
.save(tenantConfiguration);
final Class<T> clazzT = (Class<T>) value.getClass(); final Class<T> clazzT = (Class<T>) value.getClass();

View File

@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.eclipse.hawkbit.repository.jpa.model.JpaLocalArtifact;
import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@@ -23,7 +24,7 @@ import org.springframework.transaction.annotation.Transactional;
* *
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface LocalArtifactRepository extends BaseEntityRepository<LocalArtifact, Long> { public interface LocalArtifactRepository extends BaseEntityRepository<JpaLocalArtifact, Long> {
/** /**
* Counts artifacts size where the related software module is not * Counts artifacts size where the related software module is not
@@ -31,7 +32,7 @@ public interface LocalArtifactRepository extends BaseEntityRepository<LocalArtif
* *
* @return sum of artifacts size in bytes * @return sum of artifacts size in bytes
*/ */
@Query("SELECT SUM(la.size) FROM LocalArtifact la WHERE la.softwareModule.deleted = 0") @Query("SELECT SUM(la.size) FROM JpaLocalArtifact la WHERE la.softwareModule.deleted = 0")
Optional<Long> getSumOfUndeletedArtifactSize(); Optional<Long> getSumOfUndeletedArtifactSize();
/** /**
@@ -60,7 +61,7 @@ public interface LocalArtifactRepository extends BaseEntityRepository<LocalArtif
* to search * to search
* @return {@link LocalArtifact} the first in the result list * @return {@link LocalArtifact} the first in the result list
*/ */
LocalArtifact findFirstByGridFsFileName(String gridFsFileName); JpaLocalArtifact findFirstByGridFsFileName(String gridFsFileName);
/** /**
* Searches for a {@link LocalArtifact} based user provided filename at * Searches for a {@link LocalArtifact} based user provided filename at

View File

@@ -10,9 +10,11 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup.RolloutGroupStatus;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -26,7 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface RolloutGroupRepository public interface RolloutGroupRepository
extends BaseEntityRepository<RolloutGroup, Long>, JpaSpecificationExecutor<RolloutGroup> { extends BaseEntityRepository<JpaRolloutGroup, Long>, JpaSpecificationExecutor<JpaRolloutGroup> {
/** /**
* Retrieves all {@link RolloutGroup} referring a specific rollout in the * Retrieves all {@link RolloutGroup} referring a specific rollout in the
@@ -36,7 +38,7 @@ public interface RolloutGroupRepository
* the rollout the rolloutgroups belong to * the rollout the rolloutgroups belong to
* @return the rollout groups belonging to a rollout ordered by ID ASC. * @return the rollout groups belonging to a rollout ordered by ID ASC.
*/ */
List<RolloutGroup> findByRolloutOrderByIdAsc(final Rollout rollout); List<JpaRolloutGroup> findByRolloutOrderByIdAsc(final JpaRollout rollout);
/** /**
* Retrieves all {@link RolloutGroup} referring a specific rollout in a * Retrieves all {@link RolloutGroup} referring a specific rollout in a
@@ -48,7 +50,7 @@ public interface RolloutGroupRepository
* the status of the rollout groups * the status of the rollout groups
* @return the rollout groups belonging to a rollout in a specific status * @return the rollout groups belonging to a rollout in a specific status
*/ */
List<RolloutGroup> findByRolloutAndStatus(final Rollout rollout, final RolloutGroupStatus status); List<JpaRolloutGroup> findByRolloutAndStatus(final Rollout rollout, final RolloutGroupStatus status);
/** /**
* Counts all {@link RolloutGroup} referring a specific rollout. * Counts all {@link RolloutGroup} referring a specific rollout.
@@ -57,7 +59,7 @@ public interface RolloutGroupRepository
* the rollout the rolloutgroup belong to * the rollout the rolloutgroup belong to
* @return the count of the rollout groups for a specific rollout * @return the count of the rollout groups for a specific rollout
*/ */
Long countByRollout(final Rollout rollout); Long countByRollout(final JpaRollout rollout);
/** /**
* Counts all {@link RolloutGroup} referring a specific rollout in a * Counts all {@link RolloutGroup} referring a specific rollout in a
@@ -70,7 +72,7 @@ public interface RolloutGroupRepository
* @return the count of rollout groups belonging to a rollout in a specific * @return the count of rollout groups belonging to a rollout in a specific
* status * status
*/ */
Long countByRolloutAndStatus(Rollout rollout, RolloutGroupStatus rolloutGroupStatus); Long countByRolloutAndStatus(JpaRollout rollout, RolloutGroupStatus rolloutGroupStatus);
/** /**
* Counts all {@link RolloutGroup} referring a specific rollout in specific * Counts all {@link RolloutGroup} referring a specific rollout in specific
@@ -88,8 +90,8 @@ public interface RolloutGroupRepository
* @return the count of rollout groups belonging to a rollout in specific * @return the count of rollout groups belonging to a rollout in specific
* status * status
*/ */
@Query("SELECT COUNT(r.id) FROM RolloutGroup r WHERE r.rollout = :rollout and (r.status = :status1 or r.status = :status2)") @Query("SELECT COUNT(r.id) FROM JpaRolloutGroup r WHERE r.rollout = :rollout and (r.status = :status1 or r.status = :status2)")
Long countByRolloutAndStatusOrStatus(@Param("rollout") Rollout rollout, Long countByRolloutAndStatusOrStatus(@Param("rollout") JpaRollout rollout,
@Param("status1") RolloutGroupStatus rolloutGroupStatus1, @Param("status1") RolloutGroupStatus rolloutGroupStatus1,
@Param("status2") RolloutGroupStatus rolloutGroupStatus2); @Param("status2") RolloutGroupStatus rolloutGroupStatus2);
@@ -103,7 +105,7 @@ public interface RolloutGroupRepository
* the status of the rolloutgroups * the status of the rolloutgroups
* @return The child {@link RolloutGroup}s in a specific status * @return The child {@link RolloutGroup}s in a specific status
*/ */
List<RolloutGroup> findByParentAndStatus(RolloutGroup rolloutGroup, RolloutGroupStatus status); List<JpaRolloutGroup> findByParentAndStatus(JpaRolloutGroup rolloutGroup, RolloutGroupStatus status);
/** /**
* Retrieves all {@link RolloutGroup} for a specific rollout and status not * Retrieves all {@link RolloutGroup} for a specific rollout and status not
@@ -116,7 +118,7 @@ public interface RolloutGroupRepository
* @return rolloutgroup referring to a rollout and not having a specific * @return rolloutgroup referring to a rollout and not having a specific
* status ordered by ID DESC. * status ordered by ID DESC.
*/ */
List<RolloutGroup> findByRolloutAndStatusNotOrderByIdDesc(Rollout rollout, RolloutGroupStatus notStatus); List<JpaRolloutGroup> findByRolloutAndStatusNotOrderByIdDesc(JpaRollout rollout, RolloutGroupStatus notStatus);
/** /**
* Retrieves all {@link RolloutGroup} for a specific rollout. * Retrieves all {@link RolloutGroup} for a specific rollout.
@@ -127,6 +129,6 @@ public interface RolloutGroupRepository
* the page request to sort, limit the result * the page request to sort, limit the result
* @return a page of found {@link RolloutGroup} or {@code empty}. * @return a page of found {@link RolloutGroup} or {@code empty}.
*/ */
Page<RolloutGroup> findByRolloutId(final Long rolloutId, Pageable page); Page<JpaRolloutGroup> findByRolloutId(final Long rolloutId, Pageable page);
} }

View File

@@ -10,8 +10,9 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout.RolloutStatus;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -25,7 +26,8 @@ import org.springframework.transaction.annotation.Transactional;
* The repository interface for the {@link Rollout} model. * The repository interface for the {@link Rollout} model.
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface RolloutRepository extends BaseEntityRepository<Rollout, Long>, JpaSpecificationExecutor<Rollout> { public interface RolloutRepository
extends BaseEntityRepository<JpaRollout, Long>, JpaSpecificationExecutor<JpaRollout> {
/** /**
* Updates the {@code lastCheck} field of the {@link Rollout} for rollouts * Updates the {@code lastCheck} field of the {@link Rollout} for rollouts
@@ -42,7 +44,7 @@ public interface RolloutRepository extends BaseEntityRepository<Rollout, Long>,
*/ */
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Query("UPDATE Rollout r SET r.lastCheck = :lastCheck WHERE r.lastCheck < (:lastCheck - :delay) AND r.status=:status") @Query("UPDATE JpaRollout r SET r.lastCheck = :lastCheck WHERE r.lastCheck < (:lastCheck - :delay) AND r.status=:status")
int updateLastCheck(@Param("lastCheck") final long lastCheck, @Param("delay") final long delay, int updateLastCheck(@Param("lastCheck") final long lastCheck, @Param("delay") final long delay,
@Param("status") final RolloutStatus status); @Param("status") final RolloutStatus status);
@@ -57,7 +59,7 @@ public interface RolloutRepository extends BaseEntityRepository<Rollout, Long>,
* @return the list of {@link Rollout} for specific lastCheck time and * @return the list of {@link Rollout} for specific lastCheck time and
* status * status
*/ */
List<Rollout> findByLastCheckAndStatus(long lastCheck, RolloutStatus status); List<JpaRollout> findByLastCheckAndStatus(long lastCheck, RolloutStatus status);
/** /**
* Retrieves all {@link Rollout} for a specific {@code name} * Retrieves all {@link Rollout} for a specific {@code name}
@@ -66,7 +68,7 @@ public interface RolloutRepository extends BaseEntityRepository<Rollout, Long>,
* the rollout name * the rollout name
* @return {@link Rollout} for specific name * @return {@link Rollout} for specific name
*/ */
Page<Rollout> findByName(final Pageable pageable, String name); Page<JpaRollout> findByName(final Pageable pageable, String name);
/** /**
* Retrieves all {@link Rollout} for a specific {@code name} * Retrieves all {@link Rollout} for a specific {@code name}
@@ -75,7 +77,7 @@ public interface RolloutRepository extends BaseEntityRepository<Rollout, Long>,
* the rollout name * the rollout name
* @return {@link Rollout} for specific name * @return {@link Rollout} for specific name
*/ */
Rollout findByName(String name); JpaRollout findByName(String name);
/** /**
* Retrieves all {@link Rollout} for a specific status. * Retrieves all {@link Rollout} for a specific status.
@@ -84,5 +86,5 @@ public interface RolloutRepository extends BaseEntityRepository<Rollout, Long>,
* the status of the rollouts to retrieve * the status of the rollouts to retrieve
* @return a list of {@link Rollout} having the given status * @return a list of {@link Rollout} having the given status
*/ */
List<Rollout> findByStatus(final RolloutStatus status); List<JpaRollout> findByStatus(final RolloutStatus status);
} }

View File

@@ -8,8 +8,8 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import org.eclipse.hawkbit.repository.model.RolloutTargetGroup; import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup;
import org.eclipse.hawkbit.repository.model.RolloutTargetGroupId; import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroupId;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;

View File

@@ -10,8 +10,9 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SwMetadataCompositeKey;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -25,8 +26,8 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface SoftwareModuleMetadataRepository public interface SoftwareModuleMetadataRepository
extends PagingAndSortingRepository<SoftwareModuleMetadata, SwMetadataCompositeKey>, extends PagingAndSortingRepository<JpaSoftwareModuleMetadata, SwMetadataCompositeKey>,
JpaSpecificationExecutor<SoftwareModuleMetadata> { JpaSpecificationExecutor<JpaSoftwareModuleMetadata> {
/** /**
* Saves all given entities. * Saves all given entities.
@@ -37,7 +38,7 @@ public interface SoftwareModuleMetadataRepository
* in case the given entity is (@literal null}. * in case the given entity is (@literal null}.
*/ */
@Override @Override
<S extends SoftwareModuleMetadata> List<S> save(Iterable<S> entities); <S extends JpaSoftwareModuleMetadata> List<S> save(Iterable<S> entities);
/** /**
* finds all software module meta data of the given software module id. * finds all software module meta data of the given software module id.

View File

@@ -10,6 +10,9 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
@@ -30,7 +33,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface SoftwareModuleRepository public interface SoftwareModuleRepository
extends BaseEntityRepository<SoftwareModule, Long>, JpaSpecificationExecutor<SoftwareModule> { extends BaseEntityRepository<JpaSoftwareModule, Long>, JpaSpecificationExecutor<JpaSoftwareModule> {
/** /**
* Counts all {@link SoftwareModule}s based on the given {@link Type}. * Counts all {@link SoftwareModule}s based on the given {@link Type}.
@@ -39,7 +42,7 @@ public interface SoftwareModuleRepository
* to count for * to count for
* @return number of {@link SoftwareModule}s * @return number of {@link SoftwareModule}s
*/ */
Long countByType(SoftwareModuleType type); Long countByType(JpaSoftwareModuleType type);
/** /**
* Retrieves {@link SoftwareModule} by filtering on name AND version AND * Retrieves {@link SoftwareModule} by filtering on name AND version AND
@@ -54,7 +57,7 @@ public interface SoftwareModuleRepository
* @return the found {@link SoftwareModule} with the given name AND version * @return the found {@link SoftwareModule} with the given name AND version
* AND type * AND type
*/ */
SoftwareModule findOneByNameAndVersionAndType(String name, String version, SoftwareModuleType type); JpaSoftwareModule findOneByNameAndVersionAndType(String name, String version, JpaSoftwareModuleType type);
/** /**
* deletes the {@link SoftwareModule}s with the given IDs. * deletes the {@link SoftwareModule}s with the given IDs.
@@ -69,7 +72,7 @@ public interface SoftwareModuleRepository
*/ */
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Query("UPDATE SoftwareModule b SET b.deleted = 1, b.lastModifiedAt = :lastModifiedAt, b.lastModifiedBy = :lastModifiedBy WHERE b.id IN :ids") @Query("UPDATE JpaSoftwareModule b SET b.deleted = 1, b.lastModifiedAt = :lastModifiedAt, b.lastModifiedBy = :lastModifiedBy WHERE b.id IN :ids")
void deleteSoftwareModule(@Param("lastModifiedAt") Long modifiedAt, @Param("lastModifiedBy") String modifiedBy, void deleteSoftwareModule(@Param("lastModifiedAt") Long modifiedAt, @Param("lastModifiedBy") String modifiedBy,
@Param("ids") final Long... ids); @Param("ids") final Long... ids);
@@ -81,7 +84,7 @@ public interface SoftwareModuleRepository
* @return all {@link SoftwareModule}s that are assigned to given * @return all {@link SoftwareModule}s that are assigned to given
* {@link DistributionSet}. * {@link DistributionSet}.
*/ */
Page<SoftwareModule> findByAssignedTo(Pageable pageable, DistributionSet set); Page<SoftwareModule> findByAssignedTo(Pageable pageable, JpaDistributionSet set);
/** /**
* *
@@ -92,7 +95,7 @@ public interface SoftwareModuleRepository
* {@link DistributionSet} * {@link DistributionSet}
*/ */
@EntityGraph(value = "SoftwareModule.artifacts", type = EntityGraphType.LOAD) @EntityGraph(value = "SoftwareModule.artifacts", type = EntityGraphType.LOAD)
List<SoftwareModule> findByAssignedTo(DistributionSet set); List<JpaSoftwareModule> findByAssignedTo(JpaDistributionSet set);
/** /**
* @param pageable * @param pageable
@@ -104,7 +107,7 @@ public interface SoftwareModuleRepository
* @return all {@link SoftwareModule}s that are assigned to given * @return all {@link SoftwareModule}s that are assigned to given
* {@link DistributionSet} filtered by {@link SoftwareModuleType}. * {@link DistributionSet} filtered by {@link SoftwareModuleType}.
*/ */
Page<SoftwareModule> findByAssignedToAndType(Pageable pageable, DistributionSet set, SoftwareModuleType type); Page<SoftwareModule> findByAssignedToAndType(Pageable pageable, JpaDistributionSet set, JpaSoftwareModuleType type);
/** /**
* retrieves all software modules with a given {@link SoftwareModuleType} * retrieves all software modules with a given {@link SoftwareModuleType}
@@ -117,11 +120,11 @@ public interface SoftwareModuleRepository
* @return {@link List} of found {@link SoftwareModule}s * @return {@link List} of found {@link SoftwareModule}s
*/ */
// Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477
@Query("SELECT sm FROM SoftwareModule sm WHERE sm.id IN ?1 and sm.type = ?2") @Query("SELECT sm FROM JpaSoftwareModule sm WHERE sm.id IN ?1 and sm.type = ?2")
List<SoftwareModule> findByIdInAndType(Iterable<Long> ids, SoftwareModuleType type); List<SoftwareModule> findByIdInAndType(Iterable<Long> ids, JpaSoftwareModuleType type);
@Override @Override
<S extends SoftwareModule> List<S> save(Iterable<S> entities); <S extends JpaSoftwareModule> List<S> save(Iterable<S> entities);
/** /**
* retrieves all software modules with a given * retrieves all software modules with a given
@@ -132,6 +135,6 @@ public interface SoftwareModuleRepository
* @return {@link List} of found {@link SoftwareModule}s * @return {@link List} of found {@link SoftwareModule}s
*/ */
// Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477
@Query("SELECT sm FROM SoftwareModule sm WHERE sm.id IN ?1") @Query("SELECT sm FROM JpaSoftwareModule sm WHERE sm.id IN ?1")
List<SoftwareModule> findByIdIn(Iterable<Long> ids); List<JpaSoftwareModule> findByIdIn(Iterable<Long> ids);
} }

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@@ -21,7 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface SoftwareModuleTypeRepository public interface SoftwareModuleTypeRepository
extends BaseEntityRepository<SoftwareModuleType, Long>, JpaSpecificationExecutor<SoftwareModuleType> { extends BaseEntityRepository<JpaSoftwareModuleType, Long>, JpaSpecificationExecutor<JpaSoftwareModuleType> {
/** /**
* @param pageable * @param pageable
@@ -47,7 +48,7 @@ public interface SoftwareModuleTypeRepository
* @return all {@link SoftwareModuleType}s in the repository with given * @return all {@link SoftwareModuleType}s in the repository with given
* {@link SoftwareModuleType#getKey()} * {@link SoftwareModuleType#getKey()}
*/ */
SoftwareModuleType findByKey(String key); JpaSoftwareModuleType findByKey(String key);
/** /**
* *
@@ -56,5 +57,5 @@ public interface SoftwareModuleTypeRepository
* @return all {@link SoftwareModuleType}s in the repository with given * @return all {@link SoftwareModuleType}s in the repository with given
* {@link SoftwareModuleType#getName()} * {@link SoftwareModuleType#getName()}
*/ */
SoftwareModuleType findByName(String name); JpaSoftwareModuleType findByName(String name);
} }

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.repository.jpa; package org.eclipse.hawkbit.repository.jpa;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -21,7 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface TargetFilterQueryRepository public interface TargetFilterQueryRepository
extends BaseEntityRepository<TargetFilterQuery, Long>, JpaSpecificationExecutor<TargetFilterQuery> { extends BaseEntityRepository<JpaTargetFilterQuery, Long>, JpaSpecificationExecutor<JpaTargetFilterQuery> {
/** /**
* Find customer target filter by name * Find customer target filter by name
@@ -35,11 +36,11 @@ public interface TargetFilterQueryRepository
* Find list of all custom target filters. * Find list of all custom target filters.
*/ */
@Override @Override
Page<TargetFilterQuery> findAll(); Page<JpaTargetFilterQuery> findAll();
@Override @Override
@Modifying @Modifying
@Transactional @Transactional
<S extends TargetFilterQuery> S save(S entity); <S extends JpaTargetFilterQuery> S save(S entity);
} }

View File

@@ -13,6 +13,7 @@ import java.util.List;
import javax.persistence.Entity; import javax.persistence.Entity;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
@@ -42,7 +43,7 @@ public interface TargetInfoRepository {
*/ */
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Query("update TargetInfo ti set ti.updateStatus = :status where ti.targetId in :targets and ti.updateStatus != :status") @Query("update JpaTargetInfo ti set ti.updateStatus = :status where ti.targetId in :targets and ti.updateStatus != :status")
void setTargetUpdateStatus(@Param("status") TargetUpdateStatus status, @Param("targets") List<Long> targets); void setTargetUpdateStatus(@Param("status") TargetUpdateStatus status, @Param("targets") List<Long> targets);
/** /**
@@ -54,7 +55,7 @@ public interface TargetInfoRepository {
* @return persisted or updated {@link Entity} * @return persisted or updated {@link Entity}
*/ */
@CacheEvict(value = { "targetStatus", "distributionUsageInstalled", "targetsLastPoll" }, allEntries = true) @CacheEvict(value = { "targetStatus", "distributionUsageInstalled", "targetsLastPoll" }, allEntries = true)
<S extends TargetInfo> S save(S entity); <S extends JpaTargetInfo> S save(S entity);
/** /**
* Deletes info entries by ID. * Deletes info entries by ID.

View File

@@ -11,11 +11,13 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Tag;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.TargetWithActionStatus; import org.eclipse.hawkbit.repository.model.TargetWithActionStatus;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
@@ -35,7 +37,7 @@ import org.springframework.transaction.annotation.Transactional;
* *
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface TargetRepository extends BaseEntityRepository<Target, Long>, JpaSpecificationExecutor<Target> { public interface TargetRepository extends BaseEntityRepository<JpaTarget, Long>, JpaSpecificationExecutor<JpaTarget> {
/** /**
* Loads {@link Target} including details {@link EntityGraph} by given ID. * Loads {@link Target} including details {@link EntityGraph} by given ID.
@@ -45,7 +47,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
* @return found {@link Target} or <code>null</code> if not found. * @return found {@link Target} or <code>null</code> if not found.
*/ */
@EntityGraph(value = "Target.detail", type = EntityGraphType.LOAD) @EntityGraph(value = "Target.detail", type = EntityGraphType.LOAD)
Target findByControllerId(String controllerID); JpaTarget findByControllerId(String controllerID);
/** /**
* Finds targets by given list of {@link Target#getControllerId()}s. * Finds targets by given list of {@link Target#getControllerId()}s.
@@ -65,7 +67,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
// Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477
@Query("DELETE FROM Target t WHERE t.id IN ?1") @Query("DELETE FROM JpaTarget t WHERE t.id IN ?1")
void deleteByIdIn(final Collection<Long> targetIDs); void deleteByIdIn(final Collection<Long> targetIDs);
/** /**
@@ -75,8 +77,8 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
* to be found * to be found
* @return list of found targets * @return list of found targets
*/ */
@Query(value = "SELECT DISTINCT t FROM Target t JOIN t.tags tt WHERE tt = :tag") @Query(value = "SELECT DISTINCT t FROM JpaTarget t JOIN t.tags tt WHERE tt = :tag")
List<Target> findByTag(@Param("tag") final TargetTag tag); List<JpaTarget> findByTag(@Param("tag") final JpaTargetTag tag);
/** /**
* Finds all {@link Target}s based on given {@link Target#getControllerId()} * Finds all {@link Target}s based on given {@link Target#getControllerId()}
@@ -88,7 +90,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
* to search for * to search for
* @return {@link List} of found {@link Target}s. * @return {@link List} of found {@link Target}s.
*/ */
@Query(value = "SELECT DISTINCT t from Target t JOIN t.tags tt WHERE tt.name = :tagname AND t.controllerId IN :targets") @Query(value = "SELECT DISTINCT t from JpaTarget t JOIN t.tags tt WHERE tt.name = :tagname AND t.controllerId IN :targets")
List<Target> findByTagNameAndControllerIdIn(@Param("tagname") final String tag, List<Target> findByTagNameAndControllerIdIn(@Param("tagname") final String tag,
@Param("targets") final Collection<String> controllerIds); @Param("targets") final Collection<String> controllerIds);
@@ -114,7 +116,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
* *
* @return found targets * @return found targets
*/ */
Page<Target> findByTargetInfoInstalledDistributionSet(final Pageable pageable, final DistributionSet set); Page<Target> findByTargetInfoInstalledDistributionSet(final Pageable pageable, final JpaDistributionSet set);
/** /**
* retrieves the {@link Target}s which has the {@link DistributionSet} * retrieves the {@link Target}s which has the {@link DistributionSet}
@@ -138,7 +140,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
* *
* @return found targets * @return found targets
*/ */
Page<Target> findByAssignedDistributionSet(final Pageable pageable, final DistributionSet set); Page<Target> findByAssignedDistributionSet(final Pageable pageable, final JpaDistributionSet set);
/** /**
* Saves all given {@link Target}s. * Saves all given {@link Target}s.
@@ -154,7 +156,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@CacheEvict(value = { "targetStatus", "distributionUsageInstalled", "targetsLastPoll" }, allEntries = true) @CacheEvict(value = { "targetStatus", "distributionUsageInstalled", "targetsLastPoll" }, allEntries = true)
<S extends Target> List<S> save(Iterable<S> entities); <S extends JpaTarget> List<S> save(Iterable<S> entities);
/** /**
* Saves a given entity. Use the returned instance for further operations as * Saves a given entity. Use the returned instance for further operations as
@@ -168,7 +170,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@CacheEvict(value = { "targetStatus", "distributionUsageInstalled", "targetsLastPoll" }, allEntries = true) @CacheEvict(value = { "targetStatus", "distributionUsageInstalled", "targetsLastPoll" }, allEntries = true)
<S extends Target> S save(S entity); <S extends JpaTarget> S save(S entity);
/** /**
* Finds all targets that have defined {@link DistributionSet} assigned. * Finds all targets that have defined {@link DistributionSet} assigned.
@@ -199,7 +201,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
* @return number of found {@link Target}s with given * @return number of found {@link Target}s with given
* {@link Target#getControllerId()}s * {@link Target#getControllerId()}s
*/ */
@Query("SELECT COUNT(t) FROM Target t WHERE t.controllerId IN ?1") @Query("SELECT COUNT(t) FROM JpaTarget t WHERE t.controllerId IN ?1")
Long countByControllerIdIn(final Collection<String> ids); Long countByControllerIdIn(final Collection<String> ids);
/** /**
@@ -228,7 +230,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
* @return found targets * @return found targets
*/ */
Page<Target> findByAssignedDistributionSetOrTargetInfoInstalledDistributionSet(final Pageable pageable, Page<Target> findByAssignedDistributionSetOrTargetInfoInstalledDistributionSet(final Pageable pageable,
final DistributionSet assigned, final DistributionSet installed); final JpaDistributionSet assigned, final JpaDistributionSet installed);
/** /**
* Finds all targets that have defined {@link DistributionSet} assigned or * Finds all targets that have defined {@link DistributionSet} assigned or
@@ -255,12 +257,12 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
* @see org.springframework.data.repository.CrudRepository#findAll() * @see org.springframework.data.repository.CrudRepository#findAll()
*/ */
@Override @Override
List<Target> findAll(); List<JpaTarget> findAll();
@Override @Override
// Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477
@Query("SELECT t FROM Target t WHERE t.id IN ?1") @Query("SELECT t FROM JpaTarget t WHERE t.id IN ?1")
List<Target> findAll(Iterable<Long> ids); List<JpaTarget> findAll(Iterable<Long> ids);
/** /**
* Sets {@link Target#getAssignedDistributionSet()}. * Sets {@link Target#getAssignedDistributionSet()}.
@@ -276,11 +278,11 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
*/ */
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Query("UPDATE Target t SET t.assignedDistributionSet = :set, t.lastModifiedAt = :lastModifiedAt, t.lastModifiedBy = :lastModifiedBy WHERE t.id IN :targets") @Query("UPDATE JpaTarget t SET t.assignedDistributionSet = :set, t.lastModifiedAt = :lastModifiedAt, t.lastModifiedBy = :lastModifiedBy WHERE t.id IN :targets")
void setAssignedDistributionSet(@Param("set") DistributionSet set, @Param("lastModifiedAt") Long modifiedAt, void setAssignedDistributionSet(@Param("set") JpaDistributionSet set, @Param("lastModifiedAt") Long modifiedAt,
@Param("lastModifiedBy") String modifiedBy, @Param("targets") Collection<Long> targets); @Param("lastModifiedBy") String modifiedBy, @Param("targets") Collection<Long> targets);
List<Target> findByRolloutTargetGroupRolloutGroup(final RolloutGroup rolloutGroup); List<Target> findByRolloutTargetGroupRolloutGroup(final JpaRolloutGroup rolloutGroup);
/** /**
* *
@@ -304,7 +306,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
* the page request parameter * the page request parameter
* @return a page of all targets related to a rollout group * @return a page of all targets related to a rollout group
*/ */
Page<Target> findByActionsRolloutGroup(RolloutGroup rolloutGroup, Pageable page); Page<Target> findByActionsRolloutGroup(JpaRolloutGroup rolloutGroup, Pageable page);
/** /**
* Find all targets with action status for a specific group. * Find all targets with action status for a specific group.
@@ -315,7 +317,7 @@ public interface TargetRepository extends BaseEntityRepository<Target, Long>, Jp
* the ID of the rollout group * the ID of the rollout group
* @return targets with action status * @return targets with action status
*/ */
@Query("select DISTINCT NEW org.eclipse.hawkbit.repository.model.TargetWithActionStatus(a.target,a.status) from Action a inner join fetch a.target t where a.rolloutGroup.id = :rolloutGroupId") @Query("select DISTINCT NEW org.eclipse.hawkbit.repository.model.TargetWithActionStatus(a.target,a.status) from JpaAction a inner join fetch a.target t where a.rolloutGroup.id = :rolloutGroupId")
Page<TargetWithActionStatus> findTargetsWithActionStatusByRolloutGroupId(final Pageable pageable, Page<TargetWithActionStatus> findTargetsWithActionStatusByRolloutGroupId(final Pageable pageable,
@Param("rolloutGroupId") Long rolloutGroupId); @Param("rolloutGroupId") Long rolloutGroupId);
} }

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
@@ -22,7 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface TargetTagRepository public interface TargetTagRepository
extends BaseEntityRepository<TargetTag, Long>, JpaSpecificationExecutor<TargetTag> { extends BaseEntityRepository<JpaTargetTag, Long>, JpaSpecificationExecutor<JpaTargetTag> {
/** /**
* deletes the {@link TargetTag}s with the given tag names. * deletes the {@link TargetTag}s with the given tag names.
@@ -42,7 +43,7 @@ public interface TargetTagRepository
* to filter on * to filter on
* @return the {@link TargetTag} if found, otherwise null * @return the {@link TargetTag} if found, otherwise null
*/ */
TargetTag findByNameEquals(final String tagName); JpaTargetTag findByNameEquals(final String tagName);
/** /**
* Returns all instances of the type. * Returns all instances of the type.
@@ -50,8 +51,8 @@ public interface TargetTagRepository
* @return all entities * @return all entities
*/ */
@Override @Override
List<TargetTag> findAll(); List<JpaTargetTag> findAll();
@Override @Override
<S extends TargetTag> List<S> save(Iterable<S> entities); <S extends JpaTargetTag> List<S> save(Iterable<S> entities);
} }

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.jpa.model.JpaTenantConfiguration;
import org.eclipse.hawkbit.repository.model.TenantConfiguration; import org.eclipse.hawkbit.repository.model.TenantConfiguration;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -19,7 +20,7 @@ import org.springframework.transaction.annotation.Transactional;
* *
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface TenantConfigurationRepository extends BaseEntityRepository<TenantConfiguration, Long> { public interface TenantConfigurationRepository extends BaseEntityRepository<JpaTenantConfiguration, Long> {
/** /**
* Finds a specific {@link TenantConfiguration} by the configuration key. * Finds a specific {@link TenantConfiguration} by the configuration key.
@@ -28,10 +29,10 @@ public interface TenantConfigurationRepository extends BaseEntityRepository<Tena
* the configuration key to find the configuration for * the configuration key to find the configuration for
* @return the found tenant configuration object otherwise {@code null} * @return the found tenant configuration object otherwise {@code null}
*/ */
TenantConfiguration findByKey(String configurationKey); JpaTenantConfiguration findByKey(String configurationKey);
@Override @Override
List<TenantConfiguration> findAll(); List<JpaTenantConfiguration> findAll();
/** /**
* Deletes a tenant configuration by tenant and key. * Deletes a tenant configuration by tenant and key.

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.jpa.model.JpaTenantMetaData;
import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.repository.model.TenantMetaData;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
@@ -20,7 +21,7 @@ import org.springframework.transaction.annotation.Transactional;
* *
*/ */
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public interface TenantMetaDataRepository extends PagingAndSortingRepository<TenantMetaData, Long> { public interface TenantMetaDataRepository extends PagingAndSortingRepository<JpaTenantMetaData, Long> {
/** /**
* Search {@link TenantMetaData} by tenant name. * Search {@link TenantMetaData} by tenant name.
@@ -42,7 +43,7 @@ public interface TenantMetaDataRepository extends PagingAndSortingRepository<Ten
Long countByTenantIgnoreCase(String tenant); Long countByTenantIgnoreCase(String tenant);
@Override @Override
List<TenantMetaData> findAll(); List<JpaTenantMetaData> findAll();
/** /**
* @param tenant * @param tenant

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serializable; import java.io.Serializable;
@@ -21,6 +21,10 @@ import javax.persistence.ManyToOne;
import javax.persistence.MapsId; import javax.persistence.MapsId;
import javax.persistence.Table; import javax.persistence.Table;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
/** /**
* Relation element between a {@link DistributionSetType} and its * Relation element between a {@link DistributionSetType} and its
* {@link SoftwareModuleType} elements. * {@link SoftwareModuleType} elements.
@@ -40,12 +44,12 @@ public class DistributionSetTypeElement implements Serializable {
@MapsId("dsType") @MapsId("dsType")
@ManyToOne(optional = false, fetch = FetchType.LAZY) @ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "distribution_set_type", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_type_element_dstype")) @JoinColumn(name = "distribution_set_type", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_type_element_dstype"))
private DistributionSetType dsType; private JpaDistributionSetType dsType;
@MapsId("smType") @MapsId("smType")
@ManyToOne(optional = false, fetch = FetchType.LAZY) @ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "software_module_type", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_type_element_smtype")) @JoinColumn(name = "software_module_type", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_type_element_smtype"))
private SoftwareModuleType smType; private JpaSoftwareModuleType smType;
public DistributionSetTypeElement() { public DistributionSetTypeElement() {
// Default constructor for JPA // Default constructor for JPA
@@ -62,7 +66,7 @@ public class DistributionSetTypeElement implements Serializable {
* to <code>true</code> if the {@link SoftwareModuleType} if * to <code>true</code> if the {@link SoftwareModuleType} if
* mandatory element in the {@link DistributionSet}. * mandatory element in the {@link DistributionSet}.
*/ */
public DistributionSetTypeElement(final DistributionSetType dsType, final SoftwareModuleType smType, public DistributionSetTypeElement(final JpaDistributionSetType dsType, final JpaSoftwareModuleType smType,
final boolean mandatory) { final boolean mandatory) {
super(); super();
key = new DistributionSetTypeElementCompositeKey(dsType, smType); key = new DistributionSetTypeElementCompositeKey(dsType, smType);

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serializable; import java.io.Serializable;
@@ -40,7 +40,7 @@ public class DistributionSetTypeElementCompositeKey implements Serializable {
* @param smType * @param smType
* in the key * in the key
*/ */
DistributionSetTypeElementCompositeKey(final DistributionSetType dsType, final SoftwareModuleType smType) { DistributionSetTypeElementCompositeKey(final JpaDistributionSetType dsType, final JpaSoftwareModuleType smType) {
super(); super();
this.dsType = dsType.getId(); this.dsType = dsType.getId();
this.smType = smType.getId(); this.smType = smType.getId();

View File

@@ -6,10 +6,12 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serializable; import java.io.Serializable;
import org.eclipse.hawkbit.repository.model.DistributionSet;
/** /**
* The DistributionSet Metadata composite key which contains the meta data key * The DistributionSet Metadata composite key which contains the meta data key
* and the ID of the DistributionSet itself. * and the ID of the DistributionSet itself.

View File

@@ -0,0 +1,274 @@
/**
* 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.model;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedSubgraph;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.eclipse.hawkbit.cache.CacheField;
import org.eclipse.hawkbit.cache.CacheKeys;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.persistence.annotations.CascadeOnDelete;
/**
* <p>
* Applicable transition changes of the {@link SoftwareModule}s state of a
* {@link Target}, e.g. install, uninstall, update and preparations for the
* transition change, i.e. download.
* </p>
*
* <p>
* Actions are managed by the SP server and applied to the targets by the
* client.
* <p>
*/
@Table(name = "sp_action", indexes = { @Index(name = "sp_idx_action_01", columnList = "tenant,distribution_set"),
@Index(name = "sp_idx_action_02", columnList = "tenant,target,active"),
@Index(name = "sp_idx_action_prim", columnList = "tenant,id") })
@NamedEntityGraphs({ @NamedEntityGraph(name = "Action.ds", attributeNodes = { @NamedAttributeNode("distributionSet") }),
@NamedEntityGraph(name = "Action.all", attributeNodes = { @NamedAttributeNode("distributionSet"),
@NamedAttributeNode(value = "target", subgraph = "target.ds") }, subgraphs = @NamedSubgraph(name = "target.ds", attributeNodes = @NamedAttributeNode("assignedDistributionSet"))) })
@Entity
public class JpaAction extends JpaTenantAwareBaseEntity implements Action {
private static final long serialVersionUID = 1L;
/**
* the {@link DistributionSet} which should be installed by this action.
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "distribution_set", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_ds"))
private JpaDistributionSet distributionSet;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "target", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_target"))
private JpaTarget target;
@Column(name = "active")
private boolean active;
@Column(name = "action_type", nullable = false)
@Enumerated(EnumType.STRING)
private ActionType actionType;
@Column(name = "forced_time")
private long forcedTime;
@Column(name = "status")
private Status status;
@CascadeOnDelete
@OneToMany(mappedBy = "action", targetEntity = JpaActionStatus.class, fetch = FetchType.LAZY, cascade = {
CascadeType.REMOVE })
private List<ActionStatus> actionStatus;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rolloutgroup", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rolloutgroup"))
private JpaRolloutGroup rolloutGroup;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rollout", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rollout"))
private JpaRollout rollout;
/**
* Note: filled only in {@link Status#DOWNLOAD}.
*/
@Transient
@CacheField(key = CacheKeys.DOWNLOAD_PROGRESS_PERCENT)
private int downloadProgressPercent;
/**
* @return the distributionSet
*/
@Override
public DistributionSet getDistributionSet() {
return distributionSet;
}
/**
* @param distributionSet
* the distributionSet to set
*/
@Override
public void setDistributionSet(final DistributionSet distributionSet) {
this.distributionSet = (JpaDistributionSet) distributionSet;
}
/**
* @return true when action is in state {@link Status#CANCELING} or
* {@link Status#CANCELED}, false otherwise
*/
@Override
public boolean isCancelingOrCanceled() {
return status == Status.CANCELING || status == Status.CANCELED;
}
@Override
public void setActive(final boolean active) {
this.active = active;
}
@Override
public Status getStatus() {
return status;
}
@Override
public void setStatus(final Status status) {
this.status = status;
}
@Override
public int getDownloadProgressPercent() {
return downloadProgressPercent;
}
@Override
public void setDownloadProgressPercent(final int downloadProgressPercent) {
this.downloadProgressPercent = downloadProgressPercent;
}
@Override
public boolean isActive() {
return active;
}
@Override
public void setActionType(final ActionType actionType) {
this.actionType = actionType;
}
/**
* @return the actionType
*/
@Override
public ActionType getActionType() {
return actionType;
}
@Override
public List<ActionStatus> getActionStatus() {
return actionStatus;
}
@Override
public void setTarget(final Target target) {
this.target = (JpaTarget) target;
}
@Override
public Target getTarget() {
return target;
}
@Override
public long getForcedTime() {
return forcedTime;
}
@Override
public void setForcedTime(final long forcedTime) {
this.forcedTime = forcedTime;
}
@Override
public RolloutGroup getRolloutGroup() {
return rolloutGroup;
}
@Override
public void setRolloutGroup(final RolloutGroup rolloutGroup) {
this.rolloutGroup = (JpaRolloutGroup) rolloutGroup;
}
@Override
public Rollout getRollout() {
return rollout;
}
@Override
public void setRollout(final Rollout rollout) {
this.rollout = (JpaRollout) rollout;
}
/**
* checks if the {@link #forcedTime} is hit by the given
* {@code hitTimeMillis}, by means if the given milliseconds are greater
* than the forcedTime.
*
* @param hitTimeMillis
* the milliseconds, mostly the
* {@link System#currentTimeMillis()}
* @return {@code true} if this {@link #type} is in
* {@link ActionType#TIMEFORCED} and the given {@code hitTimeMillis}
* is greater than the {@link #forcedTime} otherwise {@code false}
*/
@Override
public boolean isHitAutoForceTime(final long hitTimeMillis) {
if (actionType == ActionType.TIMEFORCED) {
return hitTimeMillis >= forcedTime;
}
return false;
}
/**
* @return {@code true} if either the {@link #type} is
* {@link ActionType#FORCED} or {@link ActionType#TIMEFORCED} but
* then if the {@link #forcedTime} has been exceeded otherwise
* always {@code false}
*/
@Override
public boolean isForce() {
switch (actionType) {
case FORCED:
return true;
case TIMEFORCED:
return isHitAutoForceTime(System.currentTimeMillis());
default:
return false;
}
}
/**
* @return true when action is forced, false otherwise
*/
@Override
public boolean isForced() {
return actionType == ActionType.FORCED;
}
@Override
public String toString() {
return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]";
}
}

View File

@@ -0,0 +1,154 @@
/**
* 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.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.Table;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.persistence.annotations.CascadeOnDelete;
import com.google.common.base.Splitter;
/**
* Entity to store the status for a specific action.
*/
@Table(name = "sp_action_status", indexes = { @Index(name = "sp_idx_action_status_01", columnList = "tenant,action"),
@Index(name = "sp_idx_action_status_02", columnList = "tenant,action,status"),
@Index(name = "sp_idx_action_status_prim", columnList = "tenant,id") })
@NamedEntityGraph(name = "ActionStatus.withMessages", attributeNodes = { @NamedAttributeNode("messages") })
@Entity
public class JpaActionStatus extends JpaTenantAwareBaseEntity implements ActionStatus {
private static final long serialVersionUID = 1L;
@Column(name = "target_occurred_at")
private Long occurredAt;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "action", nullable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_act_stat_action"))
private JpaAction action;
@Column(name = "status")
private Status status;
@CascadeOnDelete
@ElementCollection(fetch = FetchType.LAZY, targetClass = String.class)
@CollectionTable(name = "sp_action_status_messages", joinColumns = @JoinColumn(name = "action_status_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_stat_msg_act_stat")), indexes = {
@Index(name = "sp_idx_action_status_msgs_01", columnList = "action_status_id") })
@Column(name = "detail_message", length = 512)
private final List<String> messages = new ArrayList<>();
/**
* Creates a new {@link ActionStatus} object.
*
* @param action
* the action for this action status
* @param status
* the status for this action status
* @param occurredAt
* the occurred timestamp
*/
public JpaActionStatus(final Action action, final Status status, final Long occurredAt) {
this.action = (JpaAction) action;
this.status = status;
this.occurredAt = occurredAt;
}
/**
* Creates a new {@link ActionStatus} object.
*
* @param action
* the action for this action status
* @param status
* the status for this action status
* @param occurredAt
* the occurred timestamp
* @param messages
* the messages which should be added to this action status
*/
public JpaActionStatus(final JpaAction action, final Status status, final Long occurredAt,
final String... messages) {
this.action = action;
this.status = status;
this.occurredAt = occurredAt;
for (final String msg : messages) {
addMessage(msg);
}
}
/**
* JPA default constructor.
*/
public JpaActionStatus() {
// JPA default constructor.
}
@Override
public Long getOccurredAt() {
return occurredAt;
}
@Override
public void setOccurredAt(final Long occurredAt) {
this.occurredAt = occurredAt;
}
/**
* Adds message including splitting in case it exceeds 512 length.
*
* @param message
* to add
*/
@Override
public final void addMessage(final String message) {
Splitter.fixedLength(512).split(message).forEach(messages::add);
}
@Override
public List<String> getMessages() {
return messages;
}
@Override
public Action getAction() {
return action;
}
@Override
public void setAction(final Action action) {
this.action = (JpaAction) action;
}
@Override
public Status getStatus() {
return status;
}
@Override
public void setStatus(final Status status) {
this.status = status;
}
}

View File

@@ -0,0 +1,63 @@
/**
* 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.model;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
/**
* Tenant specific locally stored artifact representation that is used by
* {@link SoftwareModule}.
*/
@MappedSuperclass
public abstract class JpaArtifact extends JpaTenantAwareBaseEntity implements Artifact {
private static final long serialVersionUID = 1L;
@Column(name = "sha1_hash", length = 40, nullable = true)
private String sha1Hash;
@Column(name = "md5_hash", length = 32, nullable = true)
private String md5Hash;
@Column(name = "file_size")
private Long size;
@Override
public abstract SoftwareModule getSoftwareModule();
@Override
public String getMd5Hash() {
return md5Hash;
}
@Override
public String getSha1Hash() {
return sha1Hash;
}
public void setMd5Hash(final String md5Hash) {
this.md5Hash = md5Hash;
}
public void setSha1Hash(final String sha1Hash) {
this.sha1Hash = sha1Hash;
}
@Override
public Long getSize() {
return size;
}
public void setSize(final Long size) {
this.size = size;
}
}

View File

@@ -0,0 +1,184 @@
/**
* 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.model;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import org.eclipse.hawkbit.eventbus.CacheFieldEntityListener;
import org.eclipse.hawkbit.eventbus.EntityPropertyChangeListener;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
/**
* Holder of the base attributes common to all entities.
*
*/
@MappedSuperclass
@Access(AccessType.FIELD)
@EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class })
public abstract class JpaBaseEntity implements BaseEntity {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
private String createdBy;
private String lastModifiedBy;
private Long createdAt;
private Long lastModifiedAt;
@Version
@Column(name = "optlock_revision")
private long optLockRevision;
/**
* Default constructor needed for JPA entities.
*/
public JpaBaseEntity() {
// Default constructor needed for JPA entities.
}
@Override
@Access(AccessType.PROPERTY)
@Column(name = "created_at", insertable = true, updatable = false)
public Long getCreatedAt() {
return createdAt;
}
@Override
@Access(AccessType.PROPERTY)
@Column(name = "created_by", insertable = true, updatable = false, length = 40)
public String getCreatedBy() {
return createdBy;
}
@Override
@Access(AccessType.PROPERTY)
@Column(name = "last_modified_at", insertable = false, updatable = true)
public Long getLastModifiedAt() {
return lastModifiedAt;
}
@Override
@Access(AccessType.PROPERTY)
@Column(name = "last_modified_by", insertable = false, updatable = true, length = 40)
public String getLastModifiedBy() {
return lastModifiedBy;
}
@CreatedBy
public void setCreatedBy(final String createdBy) {
this.createdBy = createdBy;
}
@LastModifiedBy
public void setLastModifiedBy(final String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
@CreatedDate
public void setCreatedAt(final Long createdAt) {
this.createdAt = createdAt;
}
@LastModifiedDate
public void setLastModifiedAt(final Long lastModifiedAt) {
this.lastModifiedAt = lastModifiedAt;
}
@Override
public long getOptLockRevision() {
return optLockRevision;
}
public void setOptLockRevision(final long optLockRevision) {
this.optLockRevision = optLockRevision;
}
@Override
public Long getId() {
return id;
}
@Override
public String toString() {
return "BaseEntity [id=" + id + "]";
}
public void setId(final Long id) {
this.id = id;
}
/**
* Defined equals/hashcode strategy for the repository in general is that an
* entity is equal if it has the same {@link #getId()} and
* {@link #getOptLockRevision()} and class.
*
* @see java.lang.Object#hashCode()
*/
@Override
// Exception squid:S864 - generated code
@SuppressWarnings({ "squid:S864" })
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (id == null ? 0 : id.hashCode());
result = prime * result + (int) (optLockRevision ^ optLockRevision >>> 32);
result = prime * result + this.getClass().getName().hashCode();
return result;
}
/**
* Defined equals/hashcode strategy for the repository in general is that an
* entity is equal if it has the same {@link #getId()} and
* {@link #getOptLockRevision()} and class.
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) { // NOSONAR - as this is generated
// code
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(this.getClass().isInstance(obj))) {
return false;
}
final JpaBaseEntity other = (JpaBaseEntity) obj;
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
if (optLockRevision != other.optLockRevision) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,326 @@
/**
* 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.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetIdName;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
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.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.persistence.annotations.CascadeOnDelete;
/**
* <p>
* The {@link DistributionSet} is defined in the SP repository and contains at
* least an OS and an Agent Hub.
* </p>
*
* <p>
* A {@link Target} has exactly one target {@link DistributionSet} assigned.
* </p>
*
*/
@Entity
@Table(name = "sp_distribution_set", uniqueConstraints = {
@UniqueConstraint(columnNames = { "name", "version", "tenant" }, name = "uk_distrib_set") }, indexes = {
@Index(name = "sp_idx_distribution_set_01", columnList = "tenant,deleted,name,complete"),
@Index(name = "sp_idx_distribution_set_02", columnList = "tenant,required_migration_step"),
@Index(name = "sp_idx_distribution_set_prim", columnList = "tenant,id") })
@NamedEntityGraph(name = "DistributionSet.detail", attributeNodes = { @NamedAttributeNode("modules"),
@NamedAttributeNode("tags"), @NamedAttributeNode("type") })
public class JpaDistributionSet extends JpaNamedVersionedEntity implements DistributionSet {
private static final long serialVersionUID = 1L;
@Column(name = "required_migration_step")
private boolean requiredMigrationStep = false;
@ManyToMany(targetEntity = JpaSoftwareModule.class, fetch = FetchType.LAZY)
@JoinTable(name = "sp_ds_module", joinColumns = {
@JoinColumn(name = "ds_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_ds")) }, inverseJoinColumns = {
@JoinColumn(name = "module_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_module")) })
private final Set<SoftwareModule> modules = new HashSet<>();
@ManyToMany(targetEntity = JpaDistributionSetTag.class)
@JoinTable(name = "sp_ds_dstag", joinColumns = {
@JoinColumn(name = "ds", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_ds")) }, inverseJoinColumns = {
@JoinColumn(name = "TAG", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_tag")) })
private Set<DistributionSetTag> tags = new HashSet<>();
@Column(name = "deleted")
private boolean deleted = false;
@OneToMany(mappedBy = "assignedDistributionSet", targetEntity = JpaTarget.class, fetch = FetchType.LAZY)
private List<Target> assignedToTargets;
@OneToMany(mappedBy = "installedDistributionSet", targetEntity = JpaTargetInfo.class, fetch = FetchType.LAZY)
private List<TargetInfo> installedAtTargets;
@OneToMany(mappedBy = "distributionSet", targetEntity = JpaAction.class, fetch = FetchType.LAZY)
private List<Action> actions;
@CascadeOnDelete
@OneToMany(fetch = FetchType.LAZY, targetEntity = JpaDistributionSetMetadata.class, cascade = {
CascadeType.REMOVE })
@JoinColumn(name = "ds_id", insertable = false, updatable = false)
private final List<DistributionSetMetadata> metadata = new ArrayList<>();
@ManyToOne(fetch = FetchType.LAZY, targetEntity = JpaDistributionSetType.class)
@JoinColumn(name = "ds_id", nullable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstype_ds"))
private DistributionSetType type;
@Column(name = "complete")
private boolean complete = false;
/**
* Default constructor.
*/
public JpaDistributionSet() {
super();
}
/**
* Parameterized constructor.
*
* @param name
* of the {@link DistributionSet}
* @param version
* of the {@link DistributionSet}
* @param description
* of the {@link DistributionSet}
* @param type
* of the {@link DistributionSet}
* @param moduleList
* {@link SoftwareModule}s of the {@link DistributionSet}
*/
public JpaDistributionSet(final String name, final String version, final String description,
final DistributionSetType type, final Iterable<SoftwareModule> moduleList) {
super(name, version, description);
this.type = type;
if (moduleList != null) {
moduleList.forEach(this::addModule);
}
if (this.type != null) {
complete = this.type.checkComplete(this);
}
}
@Override
public Set<DistributionSetTag> getTags() {
return tags;
}
@Override
public boolean isDeleted() {
return deleted;
}
/**
* @return immutable list of meta data elements.
*/
@Override
public List<DistributionSetMetadata> getMetadata() {
return Collections.unmodifiableList(metadata);
}
@Override
public List<Action> getActions() {
return actions;
}
@Override
public boolean isRequiredMigrationStep() {
return requiredMigrationStep;
}
@Override
public DistributionSet setDeleted(final boolean deleted) {
this.deleted = deleted;
return this;
}
@Override
public DistributionSet setRequiredMigrationStep(final boolean isRequiredMigrationStep) {
requiredMigrationStep = isRequiredMigrationStep;
return this;
}
@Override
public DistributionSet setTags(final Set<DistributionSetTag> tags) {
this.tags = tags;
return this;
}
/**
* @return the assignedTargets
*/
@Override
public List<Target> getAssignedTargets() {
return assignedToTargets;
}
/**
* @return the installedTargets
*/
@Override
public List<TargetInfo> getInstalledTargets() {
return installedAtTargets;
}
@Override
public String toString() {
return "DistributionSet [getName()=" + getName() + ", getOptLockRevision()=" + getOptLockRevision()
+ ", getId()=" + getId() + "]";
}
/**
*
* @return unmodifiableSet of {@link SoftwareModule}.
*/
@Override
public Set<SoftwareModule> getModules() {
return Collections.unmodifiableSet(modules);
}
@Override
public DistributionSetIdName getDistributionSetIdName() {
return new DistributionSetIdName(getId(), getName(), getVersion());
}
/**
* @param softwareModule
* @return <code>true</code> if the module was added and <code>false</code>
* if it already existed in the set
*
*/
@Override
public boolean addModule(final SoftwareModule softwareModule) {
// we cannot allow that modules are added without a type defined
if (type == null) {
throw new DistributionSetTypeUndefinedException();
}
// check if it is allowed to such a module to this DS type
if (!type.containsModuleType(softwareModule.getType())) {
throw new UnsupportedSoftwareModuleForThisDistributionSetException();
}
final Optional<SoftwareModule> found = modules.stream()
.filter(module -> module.getId().equals(softwareModule.getId())).findFirst();
if (found.isPresent()) {
return false;
}
final long allready = modules.stream()
.filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).count();
if (allready >= softwareModule.getType().getMaxAssignments()) {
final Optional<SoftwareModule> sameKey = modules.stream()
.filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).findFirst();
modules.remove(sameKey.get());
}
if (modules.add(softwareModule)) {
complete = type.checkComplete(this);
return true;
}
return false;
}
/**
* Removed given {@link SoftwareModule} from this DS instance.
*
* @param softwareModule
* to remove
* @return <code>true</code> if element was found and removed
*/
@Override
public boolean removeModule(final SoftwareModule softwareModule) {
final Optional<SoftwareModule> found = modules.stream()
.filter(module -> module.getId().equals(softwareModule.getId())).findFirst();
if (found.isPresent()) {
modules.remove(found.get());
complete = type.checkComplete(this);
return true;
}
return false;
}
/**
* Searches through modules for the given type.
*
* @param type
* to search for
* @return SoftwareModule of given type or <code>null</code> if not in the
* list.
*/
@Override
public SoftwareModule findFirstModuleByType(final SoftwareModuleType type) {
final Optional<SoftwareModule> result = modules.stream().filter(module -> module.getType().equals(type))
.findFirst();
if (result.isPresent()) {
return result.get();
}
return null;
}
@Override
public DistributionSetType getType() {
return type;
}
@Override
public void setType(final DistributionSetType type) {
this.type = type;
}
@Override
public boolean isComplete() {
return complete;
}
}

View File

@@ -0,0 +1,85 @@
/**
* 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.model;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
/**
* Meta data for {@link DistributionSet}.
*
*/
@IdClass(DsMetadataCompositeKey.class)
@Entity
@Table(name = "sp_ds_metadata")
public class JpaDistributionSetMetadata extends JpaMetaData implements DistributionSetMetadata {
private static final long serialVersionUID = 1L;
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ds_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_metadata_ds"))
private JpaDistributionSet distributionSet;
public JpaDistributionSetMetadata() {
// default public constructor for JPA
}
public JpaDistributionSetMetadata(final String key, final DistributionSet distributionSet, final String value) {
super(key, value);
this.distributionSet = (JpaDistributionSet) distributionSet;
}
public DsMetadataCompositeKey getId() {
return new DsMetadataCompositeKey(distributionSet, getKey());
}
@Override
public void setDistributionSet(final DistributionSet distributionSet) {
this.distributionSet = (JpaDistributionSet) distributionSet;
}
@Override
public DistributionSet getDistributionSet() {
return distributionSet;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((distributionSet == null) ? 0 : distributionSet.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (!super.equals(obj)) {
return false;
}
final JpaDistributionSetMetadata other = (JpaDistributionSetMetadata) obj;
if (distributionSet == null) {
if (other.distributionSet != null) {
return false;
}
} else if (!distributionSet.equals(other.distributionSet)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,90 @@
/**
* 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.model;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Index;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
/**
* A {@link DistributionSetTag} is used to describe DistributionSet attributes
* and use them also for filtering the DistributionSet list.
*
*/
@Entity
@Table(name = "sp_distributionset_tag", indexes = {
@Index(name = "sp_idx_distribution_set_tag_prim", columnList = "tenant,id") }, uniqueConstraints = @UniqueConstraint(columnNames = {
"name", "tenant" }, name = "uk_ds_tag"))
public class JpaDistributionSetTag extends JpaTag implements DistributionSetTag {
private static final long serialVersionUID = 1L;
@ManyToMany(mappedBy = "tags", targetEntity = JpaDistributionSet.class, fetch = FetchType.LAZY)
private List<DistributionSet> assignedToDistributionSet;
/**
* Public constructor.
*
* @param name
* of the {@link DistributionSetTag}
**/
public JpaDistributionSetTag(final String name) {
super(name, null, null);
}
/**
* Public constructor.
*
* @param name
* of the {@link DistributionSetTag}
* @param description
* of the {@link DistributionSetTag}
* @param colour
* of tag in UI
*/
public JpaDistributionSetTag(final String name, final String description, final String colour) {
super(name, description, colour);
}
public JpaDistributionSetTag() {
super();
}
@Override
public List<DistributionSet> getAssignedToDistributionSet() {
return assignedToDistributionSet;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + this.getClass().getName().hashCode();
return result;
}
@Override
public boolean equals(final Object obj) { // NOSONAR - as this is generated
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof DistributionSetTag)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,310 @@
/**
* 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.model;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
/**
* A distribution set type defines which software module types can or have to be
* {@link DistributionSet}.
*
*/
@Entity
@Table(name = "sp_distribution_set_type", indexes = {
@Index(name = "sp_idx_distribution_set_type_01", columnList = "tenant,deleted"),
@Index(name = "sp_idx_distribution_set_type_prim", columnList = "tenant,id") }, uniqueConstraints = {
@UniqueConstraint(columnNames = { "name", "tenant" }, name = "uk_dst_name"),
@UniqueConstraint(columnNames = { "type_key", "tenant" }, name = "uk_dst_key") })
public class JpaDistributionSetType extends JpaNamedEntity implements DistributionSetType {
private static final long serialVersionUID = 1L;
@OneToMany(targetEntity = DistributionSetTypeElement.class, cascade = {
CascadeType.ALL }, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "distribution_set_type", insertable = false, updatable = false)
private final Set<DistributionSetTypeElement> elements = new HashSet<>();
@Column(name = "type_key", nullable = false, length = 64)
private String key;
@Column(name = "colour", nullable = true, length = 16)
private String colour;
@Column(name = "deleted")
private boolean deleted = false;
public JpaDistributionSetType() {
// default public constructor for JPA
}
/**
* Standard constructor.
*
* @param key
* of the type (unique)
* @param name
* of the type (unique)
* @param description
* of the type
*/
public JpaDistributionSetType(final String key, final String name, final String description) {
this(key, name, description, null);
}
/**
* Constructor.
*
* @param key
* of the type
* @param name
* of the type
* @param description
* of the type
* @param color
* of the type. It will be null by default
*/
public JpaDistributionSetType(final String key, final String name, final String description, final String color) {
super(name, description);
this.key = key;
colour = color;
}
/**
* @return the deleted
*/
@Override
public boolean isDeleted() {
return deleted;
}
/**
* @param deleted
* the deleted to set
*/
@Override
public void setDeleted(final boolean deleted) {
this.deleted = deleted;
}
@Override
public Set<SoftwareModuleType> getMandatoryModuleTypes() {
return elements.stream().filter(element -> element.isMandatory()).map(element -> element.getSmType())
.collect(Collectors.toSet());
}
@Override
public Set<SoftwareModuleType> getOptionalModuleTypes() {
return elements.stream().filter(element -> !element.isMandatory()).map(element -> element.getSmType())
.collect(Collectors.toSet());
}
/**
* Checks if the given {@link SoftwareModuleType} is in this
* {@link DistributionSetType}.
*
* @param softwareModuleType
* search for
* @return <code>true</code> if found
*/
@Override
public boolean containsModuleType(final SoftwareModuleType softwareModuleType) {
for (final DistributionSetTypeElement distributionSetTypeElement : elements) {
if (distributionSetTypeElement.getSmType().equals(softwareModuleType)) {
return true;
}
}
return false;
}
/**
* Checks if the given {@link SoftwareModuleType} is in this
* {@link DistributionSetType} and defined as
* {@link DistributionSetTypeElement#isMandatory()}.
*
* @param softwareModuleType
* search for
* @return <code>true</code> if found
*/
@Override
public boolean containsMandatoryModuleType(final SoftwareModuleType softwareModuleType) {
return elements.stream().filter(element -> element.isMandatory())
.filter(element -> element.getSmType().equals(softwareModuleType)).findFirst().isPresent();
}
/**
* Checks if the given {@link SoftwareModuleType} is in this
* {@link DistributionSetType} and defined as
* {@link DistributionSetTypeElement#isMandatory()}.
*
* @param softwareModuleType
* search for by {@link SoftwareModuleType#getId()}
* @return <code>true</code> if found
*/
@Override
public boolean containsMandatoryModuleType(final Long softwareModuleTypeId) {
return elements.stream().filter(element -> element.isMandatory())
.filter(element -> element.getSmType().getId().equals(softwareModuleTypeId)).findFirst().isPresent();
}
/**
* Checks if the given {@link SoftwareModuleType} is in this
* {@link DistributionSetType} and NOT defined as
* {@link DistributionSetTypeElement#isMandatory()}.
*
* @param softwareModuleType
* search for
* @return <code>true</code> if found
*/
@Override
public boolean containsOptionalModuleType(final SoftwareModuleType softwareModuleType) {
return elements.stream().filter(element -> !element.isMandatory())
.filter(element -> element.getSmType().equals(softwareModuleType)).findFirst().isPresent();
}
/**
* Checks if the given {@link SoftwareModuleType} is in this
* {@link DistributionSetType} and NOT defined as
* {@link DistributionSetTypeElement#isMandatory()}.
*
* @param softwareModuleTypeId
* search by {@link SoftwareModuleType#getId()}
* @return <code>true</code> if found
*/
@Override
public boolean containsOptionalModuleType(final Long softwareModuleTypeId) {
return elements.stream().filter(element -> !element.isMandatory())
.filter(element -> element.getSmType().getId().equals(softwareModuleTypeId)).findFirst().isPresent();
}
/**
* Compares the modules of this {@link DistributionSetType} and the given
* one.
*
* @param dsType
* to compare with
* @return <code>true</code> if the lists are identical.
*/
@Override
public boolean areModuleEntriesIdentical(final DistributionSetType dsType) {
return new HashSet<DistributionSetTypeElement>(((JpaDistributionSetType) dsType).elements).equals(elements);
}
/**
* Adds {@link SoftwareModuleType} that is optional for the
* {@link DistributionSet}.
*
* @param smType
* to add
* @return updated instance
*/
@Override
public DistributionSetType addOptionalModuleType(final SoftwareModuleType smType) {
elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, false));
return this;
}
/**
* Adds {@link SoftwareModuleType} that is mandatory for the
* {@link DistributionSet}.
*
* @param smType
* to add
* @return updated instance
*/
@Override
public DistributionSetType addMandatoryModuleType(final SoftwareModuleType smType) {
elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, true));
return this;
}
/**
* Removes {@link SoftwareModuleType} from the list.
*
* @param smTypeId
* to remove
* @return updated instance
*/
@Override
public DistributionSetType removeModuleType(final Long smTypeId) {
// we search by id (standard equals compares also revison)
final Optional<DistributionSetTypeElement> found = elements.stream()
.filter(element -> element.getSmType().getId().equals(smTypeId)).findFirst();
if (found.isPresent()) {
elements.remove(found.get());
}
return this;
}
@Override
public String getKey() {
return key;
}
@Override
public void setKey(final String key) {
this.key = key;
}
/**
* @param distributionSet
* to check for completeness
* @return <code>true</code> if the all mandatory software module types are
* in the system.
*/
@Override
public boolean checkComplete(final DistributionSet distributionSet) {
return distributionSet.getModules().stream().map(module -> module.getType()).collect(Collectors.toList())
.containsAll(getMandatoryModuleTypes());
}
@Override
public String getColour() {
return colour;
}
@Override
public void setColour(final String colour) {
this.colour = colour;
}
public Set<DistributionSetTypeElement> getElements() {
return elements;
}
@Override
public String toString() {
return "DistributionSetType [key=" + key + ", isDeleted()=" + isDeleted() + ", getId()=" + getId() + "]";
}
}

View File

@@ -0,0 +1,142 @@
/**
* 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.model;
import java.net.URL;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.repository.model.ExternalArtifact;
import org.eclipse.hawkbit.repository.model.ExternalArtifactProvider;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
/**
* External artifact representation with all the necessary information to
* generate an artifact {@link URL} at runtime.
*
*/
@Table(name = "sp_external_artifact", indexes = {
@Index(name = "sp_idx_external_artifact_prim", columnList = "id,tenant") })
@Entity
public class JpaExternalArtifact extends JpaArtifact implements ExternalArtifact {
private static final long serialVersionUID = 1L;
@ManyToOne
@JoinColumn(name = "provider", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_art_to_ext_provider"))
private JpaExternalArtifactProvider externalArtifactProvider;
@Column(name = "url_suffix", length = 512)
private String urlSuffix;
// CascadeType.PERSIST as we register ourself at the BSM
@ManyToOne(optional = false, cascade = { CascadeType.PERSIST })
@JoinColumn(name = "software_module", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_external_assigned_sm"))
private JpaSoftwareModule softwareModule;
/**
* Default constructor.
*/
public JpaExternalArtifact() {
super();
}
/**
* Constructs {@link ExternalArtifact}.
*
* @param externalArtifactProvider
* of the artifact
* @param urlSuffix
* of the artifact
* @param softwareModule
* of the artifact
*/
public JpaExternalArtifact(@NotNull final ExternalArtifactProvider externalArtifactProvider, final String urlSuffix,
final SoftwareModule softwareModule) {
setSoftwareModule(softwareModule);
this.externalArtifactProvider = (JpaExternalArtifactProvider) externalArtifactProvider;
if (urlSuffix != null) {
this.urlSuffix = urlSuffix;
} else {
this.urlSuffix = externalArtifactProvider.getDefaultSuffix();
}
}
/**
* @return the softwareModule
*/
@Override
public SoftwareModule getSoftwareModule() {
return softwareModule;
}
@Override
public final void setSoftwareModule(final SoftwareModule softwareModule) {
this.softwareModule = (JpaSoftwareModule) softwareModule;
this.softwareModule.addArtifact(this);
}
@Override
public ExternalArtifactProvider getExternalArtifactProvider() {
return externalArtifactProvider;
}
@Override
public String getUrl() {
return new StringBuilder().append(externalArtifactProvider.getBasePath()).append(urlSuffix).toString();
}
@Override
public String getUrlSuffix() {
return urlSuffix;
}
@Override
public void setExternalArtifactProvider(final ExternalArtifactProvider externalArtifactProvider) {
this.externalArtifactProvider = (JpaExternalArtifactProvider) externalArtifactProvider;
}
/**
* @param urlSuffix
* the urlSuffix to set
*/
@Override
public void setUrlSuffix(final String urlSuffix) {
this.urlSuffix = urlSuffix;
}
@Override
public int hashCode() { // NOSONAR - as this is generated
final int prime = 31;
int result = super.hashCode();
result = prime * result + this.getClass().getName().hashCode();
return result;
}
@Override
public boolean equals(final Object obj) { // NOSONAR - as this is generated
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof JpaExternalArtifact)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,83 @@
/**
* 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.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
import org.eclipse.hawkbit.repository.model.ExternalArtifact;
import org.eclipse.hawkbit.repository.model.ExternalArtifactProvider;
/**
* External repositories for artifact storage. The SP server provides URLs for
* the targets to download from these external resources but does not access
* them itself.
*
*/
@Table(name = "sp_external_provider", indexes = {
@Index(name = "sp_idx_external_provider_prim", columnList = "tenant,id") })
@Entity
public class JpaExternalArtifactProvider extends JpaNamedEntity implements ExternalArtifactProvider {
private static final long serialVersionUID = 1L;
@Column(name = "base_url", length = 512, nullable = false)
private String basePath;
@Column(name = "default_url_suffix", length = 512, nullable = true)
private String defaultSuffix;
/**
* Constructs {@link ExternalArtifactProvider} based on given properties.
*
* @param name
* of the provided
* @param description
* which is optional
* @param baseURL
* of all {@link ExternalArtifact}s of the provider
* @param defaultUrlSuffix
* that is used if {@link ExternalArtifact#getUrlSuffix()} is
* empty.
*/
public JpaExternalArtifactProvider(final String name, final String description, final String baseURL,
final String defaultUrlSuffix) {
super(name, description);
basePath = baseURL;
defaultSuffix = defaultUrlSuffix;
}
JpaExternalArtifactProvider() {
super();
defaultSuffix = "";
basePath = "";
}
@Override
public String getBasePath() {
return basePath;
}
@Override
public String getDefaultSuffix() {
return defaultSuffix;
}
@Override
public void setBasePath(final String basePath) {
this.basePath = basePath;
}
@Override
public void setDefaultSuffix(final String defaultSuffix) {
this.defaultSuffix = defaultSuffix;
}
}

View File

@@ -0,0 +1,118 @@
/**
* 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.model;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSFile;
/**
* Tenant specific locally stored artifact representation that is used by
* {@link SoftwareModule} . It contains all information that is provided by the
* user while all SP server generated information related to the artifact (hash,
* length) is stored directly with the binary itself.
*
*
*
*/
@Table(name = "sp_artifact", indexes = { @Index(name = "sp_idx_artifact_01", columnList = "tenant,software_module"),
@Index(name = "sp_idx_artifact_prim", columnList = "tenant,id") })
@Entity
public class JpaLocalArtifact extends JpaArtifact implements LocalArtifact {
private static final long serialVersionUID = 1L;
@NotNull
@Column(name = "gridfs_file_name", length = 40)
private String gridFsFileName;
@NotNull
@Column(name = "provided_file_name", length = 256)
private String filename;
@ManyToOne(optional = false, cascade = { CascadeType.PERSIST })
@JoinColumn(name = "software_module", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_assigned_sm"))
private JpaSoftwareModule softwareModule;
/**
* Default constructor.
*/
public JpaLocalArtifact() {
super();
}
/**
* Constructs artifact.
*
* @param gridFsFileName
* that is the link to the {@link GridFS} entity.
* @param filename
* that is used by {@link GridFSFile} store.
* @param softwareModule
* of this artifact
*/
public JpaLocalArtifact(@NotNull final String gridFsFileName, @NotNull final String filename,
final SoftwareModule softwareModule) {
setSoftwareModule(softwareModule);
this.gridFsFileName = gridFsFileName;
this.filename = filename;
}
@Override
public int hashCode() { // NOSONAR - as this is generated
final int prime = 31;
int result = super.hashCode();
result = prime * result + this.getClass().getName().hashCode();
return result;
}
@Override
public boolean equals(final Object obj) { // NOSONAR - as this is generated
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof LocalArtifact)) {
return false;
}
return true;
}
@Override
public SoftwareModule getSoftwareModule() {
return softwareModule;
}
@Override
public final void setSoftwareModule(final SoftwareModule softwareModule) {
this.softwareModule = (JpaSoftwareModule) softwareModule;
this.softwareModule.addArtifact(this);
}
public String getGridFsFileName() {
return gridFsFileName;
}
@Override
public String getFilename() {
return filename;
}
}

View File

@@ -0,0 +1,102 @@
/**
* 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.model;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import org.eclipse.hawkbit.repository.model.MetaData;
/**
* Meta data for entities.
*
*/
@MappedSuperclass
public abstract class JpaMetaData implements MetaData {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "meta_key", length = 128)
private String key;
@Column(name = "meta_value", length = 4000)
@Basic
private String value;
public JpaMetaData(final String key, final String value) {
super();
this.key = key;
this.value = value;
}
public JpaMetaData() {
// Default constructor needed for JPA entities
}
@Override
public String getKey() {
return key;
}
@Override
public void setKey(final String key) {
this.key = key;
}
@Override
public String getValue() {
return value;
}
@Override
public void setValue(final String value) {
this.value = value;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((key == null) ? 0 : key.hashCode());
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(this.getClass().isInstance(obj))) {
return false;
}
final JpaMetaData other = (JpaMetaData) obj;
if (key == null) {
if (other.key != null) {
return false;
}
} else if (!key.equals(other.key)) {
return false;
}
if (value == null) {
if (other.value != null) {
return false;
}
} else if (!value.equals(other.value)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,70 @@
/**
* 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.model;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
/**
* {@link TenantAwareBaseEntity} extension for all entities that are named in
* addition to their technical ID.
*/
@MappedSuperclass
public abstract class JpaNamedEntity extends JpaTenantAwareBaseEntity implements NamedEntity {
private static final long serialVersionUID = 1L;
@Column(name = "name", nullable = false, length = 64)
private String name;
@Column(name = "description", nullable = true, length = 512)
private String description;
/**
* Default constructor.
*/
public JpaNamedEntity() {
super();
}
/**
* Parameterized constructor.
*
* @param name
* of the {@link NamedEntity}
* @param description
* of the {@link NamedEntity}
*/
public JpaNamedEntity(final String name, final String description) {
this.name = name;
this.description = description;
}
@Override
public String getDescription() {
return description;
}
@Override
public String getName() {
return name;
}
@Override
public void setDescription(final String description) {
this.description = description;
}
@Override
public void setName(final String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,55 @@
/**
* 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.model;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
/**
* Extension for {@link NamedEntity} that are versioned.
*
*/
@MappedSuperclass
public abstract class JpaNamedVersionedEntity extends JpaNamedEntity implements NamedVersionedEntity {
private static final long serialVersionUID = 1L;
@Column(name = "version", nullable = false, length = 64)
private String version;
/**
* parameterized constructor.
*
* @param name
* of the entity
* @param version
* of the entity
* @param description
*/
public JpaNamedVersionedEntity(final String name, final String version, final String description) {
super(name, description);
this.version = version;
}
JpaNamedVersionedEntity() {
super();
}
@Override
public String getVersion() {
return version;
}
@Override
public void setVersion(final String version) {
this.version = version;
}
}

View File

@@ -0,0 +1,260 @@
/**
* 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.model;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.cache.CacheField;
import org.eclipse.hawkbit.cache.CacheKeys;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
/**
* @author Michael Hirsch
*
*/
@Entity
@Table(name = "sp_rollout", indexes = {
@Index(name = "sp_idx_rollout_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = {
"name", "tenant" }, name = "uk_rollout"))
public class JpaRollout extends JpaNamedEntity implements Rollout {
private static final long serialVersionUID = 1L;
@OneToMany(targetEntity = JpaRolloutGroup.class)
@JoinColumn(name = "rollout", insertable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rollout_rolloutgroup"))
private List<RolloutGroup> rolloutGroups;
@Column(name = "target_filter", length = 1024, nullable = false)
private String targetFilterQuery;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "distribution_set", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rolltout_ds"))
private JpaDistributionSet distributionSet;
@Column(name = "status")
private RolloutStatus status = RolloutStatus.CREATING;
@Column(name = "last_check")
private long lastCheck = 0L;
@Column(name = "action_type", nullable = false)
@Enumerated(EnumType.STRING)
private ActionType actionType = ActionType.FORCED;
@Column(name = "forced_time")
private long forcedTime;
@Column(name = "total_targets")
private long totalTargets;
@Transient
@CacheField(key = CacheKeys.ROLLOUT_GROUP_TOTAL)
private int rolloutGroupsTotal = 0;
@Transient
@CacheField(key = CacheKeys.ROLLOUT_GROUP_CREATED)
private int rolloutGroupsCreated = 0;
@Transient
private transient TotalTargetCountStatus totalTargetCountStatus;
@Override
public DistributionSet getDistributionSet() {
return distributionSet;
}
@Override
public void setDistributionSet(final DistributionSet distributionSet) {
this.distributionSet = (JpaDistributionSet) distributionSet;
}
@Override
public List<RolloutGroup> getRolloutGroups() {
return rolloutGroups;
}
@Override
public void setRolloutGroups(final List<RolloutGroup> rolloutGroups) {
this.rolloutGroups = rolloutGroups;
}
@Override
public String getTargetFilterQuery() {
return targetFilterQuery;
}
@Override
public void setTargetFilterQuery(final String targetFilterQuery) {
this.targetFilterQuery = targetFilterQuery;
}
@Override
public RolloutStatus getStatus() {
return status;
}
@Override
public void setStatus(final RolloutStatus status) {
this.status = status;
}
@Override
public long getLastCheck() {
return lastCheck;
}
@Override
public void setLastCheck(final long lastCheck) {
this.lastCheck = lastCheck;
}
@Override
public ActionType getActionType() {
return actionType;
}
@Override
public void setActionType(final ActionType actionType) {
this.actionType = actionType;
}
@Override
public long getForcedTime() {
return forcedTime;
}
@Override
public void setForcedTime(final long forcedTime) {
this.forcedTime = forcedTime;
}
@Override
public long getTotalTargets() {
return totalTargets;
}
@Override
public void setTotalTargets(final long totalTargets) {
this.totalTargets = totalTargets;
}
@Override
public int getRolloutGroupsTotal() {
return rolloutGroupsTotal;
}
@Override
public void setRolloutGroupsTotal(final int rolloutGroupsTotal) {
this.rolloutGroupsTotal = rolloutGroupsTotal;
}
@Override
public int getRolloutGroupsCreated() {
return rolloutGroupsCreated;
}
@Override
public void setRolloutGroupsCreated(final int rolloutGroupsCreated) {
this.rolloutGroupsCreated = rolloutGroupsCreated;
}
@Override
public TotalTargetCountStatus getTotalTargetCountStatus() {
if (totalTargetCountStatus == null) {
totalTargetCountStatus = new TotalTargetCountStatus(totalTargets);
}
return totalTargetCountStatus;
}
@Override
public void setTotalTargetCountStatus(final TotalTargetCountStatus totalTargetCountStatus) {
this.totalTargetCountStatus = totalTargetCountStatus;
}
@Override
public String toString() {
return "Rollout [rolloutGroups=" + rolloutGroups + ", targetFilterQuery=" + targetFilterQuery
+ ", distributionSet=" + distributionSet + ", status=" + status + ", lastCheck=" + lastCheck
+ ", getName()=" + getName() + ", getId()=" + getId() + "]";
}
/**
*
* State machine for rollout.
*
*/
public enum RolloutStatus {
/**
* Rollouts is beeing created.
*/
CREATING,
/**
* Rollout is ready to start.
*/
READY,
/**
* Rollout is paused.
*/
PAUSED,
/**
* Rollout is starting.
*/
STARTING,
/**
* Rollout is stopped.
*/
STOPPED,
/**
* Rollout is running.
*/
RUNNING,
/**
* Rollout is finished.
*/
FINISHED,
/**
* Rollout could not created due errors, might be database problem due
* asynchronous creating.
*/
ERROR_CREATING,
/**
* Rollout could not started due errors, might be database problem due
* asynchronous starting.
*/
ERROR_STARTING;
}
}

View File

@@ -0,0 +1,509 @@
/**
* 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.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
/**
* JPA entity definition of persisting a group of an rollout.
*
* @author Michael Hirsch
*
*/
@Entity
@Table(name = "sp_rolloutgroup", indexes = {
@Index(name = "sp_idx_rolloutgroup_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = {
"name", "rollout", "tenant" }, name = "uk_rolloutgroup"))
public class JpaRolloutGroup extends JpaNamedEntity implements RolloutGroup {
private static final long serialVersionUID = 1L;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rollout", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rolloutgroup_rollout"))
private JpaRollout rollout;
@Column(name = "status")
private RolloutGroupStatus status = RolloutGroupStatus.READY;
@OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST }, targetEntity = RolloutTargetGroup.class)
@JoinColumn(name = "rolloutGroup_Id", insertable = false, updatable = false)
private final List<RolloutTargetGroup> rolloutTargetGroup = new ArrayList<>();
@ManyToOne(fetch = FetchType.LAZY)
private JpaRolloutGroup parent;
@Column(name = "success_condition", nullable = false)
private RolloutGroupSuccessCondition successCondition = RolloutGroupSuccessCondition.THRESHOLD;
@Column(name = "success_condition_exp", length = 512, nullable = false)
private String successConditionExp = null;
@Column(name = "success_action", nullable = false)
private RolloutGroupSuccessAction successAction = RolloutGroupSuccessAction.NEXTGROUP;
@Column(name = "success_action_exp", length = 512, nullable = false)
private String successActionExp = null;
@Column(name = "error_condition")
private RolloutGroupErrorCondition errorCondition = null;
@Column(name = "error_condition_exp", length = 512)
private String errorConditionExp = null;
@Column(name = "error_action")
private RolloutGroupErrorAction errorAction = null;
@Column(name = "error_action_exp", length = 512)
private String errorActionExp = null;
@Column(name = "total_targets")
private long totalTargets;
@Transient
private transient TotalTargetCountStatus totalTargetCountStatus;
@Override
public Rollout getRollout() {
return rollout;
}
@Override
public void setRollout(final Rollout rollout) {
this.rollout = (JpaRollout) rollout;
}
@Override
public RolloutGroupStatus getStatus() {
return status;
}
@Override
public void setStatus(final RolloutGroupStatus status) {
this.status = status;
}
public List<RolloutTargetGroup> getRolloutTargetGroup() {
return rolloutTargetGroup;
}
@Override
public RolloutGroup getParent() {
return parent;
}
@Override
public void setParent(final RolloutGroup parent) {
this.parent = (JpaRolloutGroup) parent;
}
@Override
public RolloutGroupSuccessCondition getSuccessCondition() {
return successCondition;
}
@Override
public void setSuccessCondition(final RolloutGroupSuccessCondition finishCondition) {
successCondition = finishCondition;
}
@Override
public String getSuccessConditionExp() {
return successConditionExp;
}
@Override
public void setSuccessConditionExp(final String finishExp) {
successConditionExp = finishExp;
}
@Override
public RolloutGroupErrorCondition getErrorCondition() {
return errorCondition;
}
@Override
public void setErrorCondition(final RolloutGroupErrorCondition errorCondition) {
this.errorCondition = errorCondition;
}
@Override
public String getErrorConditionExp() {
return errorConditionExp;
}
@Override
public void setErrorConditionExp(final String errorExp) {
errorConditionExp = errorExp;
}
@Override
public RolloutGroupErrorAction getErrorAction() {
return errorAction;
}
@Override
public void setErrorAction(final RolloutGroupErrorAction errorAction) {
this.errorAction = errorAction;
}
@Override
public String getErrorActionExp() {
return errorActionExp;
}
@Override
public void setErrorActionExp(final String errorActionExp) {
this.errorActionExp = errorActionExp;
}
@Override
public RolloutGroupSuccessAction getSuccessAction() {
return successAction;
}
@Override
public String getSuccessActionExp() {
return successActionExp;
}
@Override
public long getTotalTargets() {
return totalTargets;
}
@Override
public void setTotalTargets(final long totalTargets) {
this.totalTargets = totalTargets;
}
@Override
public void setSuccessAction(final RolloutGroupSuccessAction successAction) {
this.successAction = successAction;
}
@Override
public void setSuccessActionExp(final String successActionExp) {
this.successActionExp = successActionExp;
}
/**
* @return the totalTargetCountStatus
*/
@Override
public TotalTargetCountStatus getTotalTargetCountStatus() {
if (totalTargetCountStatus == null) {
totalTargetCountStatus = new TotalTargetCountStatus(totalTargets);
}
return totalTargetCountStatus;
}
/**
* @param totalTargetCountStatus
* the totalTargetCountStatus to set
*/
@Override
public void setTotalTargetCountStatus(final TotalTargetCountStatus totalTargetCountStatus) {
this.totalTargetCountStatus = totalTargetCountStatus;
}
@Override
public String toString() {
return "RolloutGroup [rollout=" + rollout + ", status=" + status + ", rolloutTargetGroup=" + rolloutTargetGroup
+ ", parent=" + parent + ", finishCondition=" + successCondition + ", finishExp=" + successConditionExp
+ ", errorCondition=" + errorCondition + ", errorExp=" + errorConditionExp + ", getName()=" + getName()
+ ", getId()=" + getId() + "]";
}
/**
* Rollout goup state machine.
*
*/
public enum RolloutGroupStatus {
/**
* Ready to start the group.
*/
READY,
/**
* Group is scheduled and started sometime, e.g. trigger of group
* before.
*/
SCHEDULED,
/**
* Group is finished.
*/
FINISHED,
/**
* Group is finished and has errors.
*/
ERROR,
/**
* Group is running.
*/
RUNNING;
}
/**
* The condition to evaluate if an group is success state.
*/
public enum RolloutGroupSuccessCondition {
THRESHOLD("thresholdRolloutGroupSuccessCondition");
private final String beanName;
private RolloutGroupSuccessCondition(final String beanName) {
this.beanName = beanName;
}
/**
* @return the beanName
*/
public String getBeanName() {
return beanName;
}
}
/**
* The condition to evaluate if an group is in error state.
*/
public enum RolloutGroupErrorCondition {
THRESHOLD("thresholdRolloutGroupErrorCondition");
private final String beanName;
private RolloutGroupErrorCondition(final String beanName) {
this.beanName = beanName;
}
/**
* @return the beanName
*/
public String getBeanName() {
return beanName;
}
}
/**
* The actions executed when the {@link RolloutGroup#errorCondition} is hit.
*/
public enum RolloutGroupErrorAction {
PAUSE("pauseRolloutGroupAction");
private final String beanName;
private RolloutGroupErrorAction(final String beanName) {
this.beanName = beanName;
}
/**
* @return the beanName
*/
public String getBeanName() {
return beanName;
}
}
/**
* The actions executed when the {@link RolloutGroup#successCondition} is
* hit.
*/
public enum RolloutGroupSuccessAction {
NEXTGROUP("startNextRolloutGroupAction");
private final String beanName;
private RolloutGroupSuccessAction(final String beanName) {
this.beanName = beanName;
}
/**
* @return the beanName
*/
public String getBeanName() {
return beanName;
}
}
/**
* Object which holds all {@link RolloutGroup} conditions together which can
* easily built.
*/
public static class RolloutGroupConditions {
private RolloutGroupSuccessCondition successCondition = null;
private String successConditionExp = null;
private RolloutGroupSuccessAction successAction = null;
private String successActionExp = null;
private RolloutGroupErrorCondition errorCondition = null;
private String errorConditionExp = null;
private RolloutGroupErrorAction errorAction = null;
private String errorActionExp = null;
public RolloutGroupSuccessCondition getSuccessCondition() {
return successCondition;
}
public void setSuccessCondition(final RolloutGroupSuccessCondition finishCondition) {
successCondition = finishCondition;
}
public String getSuccessConditionExp() {
return successConditionExp;
}
public void setSuccessConditionExp(final String finishConditionExp) {
successConditionExp = finishConditionExp;
}
public RolloutGroupSuccessAction getSuccessAction() {
return successAction;
}
public void setSuccessAction(final RolloutGroupSuccessAction successAction) {
this.successAction = successAction;
}
public String getSuccessActionExp() {
return successActionExp;
}
public void setSuccessActionExp(final String successActionExp) {
this.successActionExp = successActionExp;
}
public RolloutGroupErrorCondition getErrorCondition() {
return errorCondition;
}
public void setErrorCondition(final RolloutGroupErrorCondition errorCondition) {
this.errorCondition = errorCondition;
}
public String getErrorConditionExp() {
return errorConditionExp;
}
public void setErrorConditionExp(final String errorConditionExp) {
this.errorConditionExp = errorConditionExp;
}
public RolloutGroupErrorAction getErrorAction() {
return errorAction;
}
public void setErrorAction(final RolloutGroupErrorAction errorAction) {
this.errorAction = errorAction;
}
public String getErrorActionExp() {
return errorActionExp;
}
public void setErrorActionExp(final String errorActionExp) {
this.errorActionExp = errorActionExp;
}
}
/**
* Builder to build easily the {@link RolloutGroupConditions}.
*
*/
public static class RolloutGroupConditionBuilder {
private final RolloutGroupConditions conditions = new RolloutGroupConditions();
public RolloutGroupConditions build() {
return conditions;
}
/**
* Sets the finish condition and expression on the builder.
*
* @param condition
* the finish condition
* @param expression
* the finish expression
* @return the builder itself
*/
public RolloutGroupConditionBuilder successCondition(final RolloutGroupSuccessCondition condition,
final String expression) {
conditions.setSuccessCondition(condition);
conditions.setSuccessConditionExp(expression);
return this;
}
/**
* Sets the success action and expression on the builder.
*
* @param action
* the success action
* @param expression
* the error expression
* @return the builder itself
*/
public RolloutGroupConditionBuilder successAction(final RolloutGroupSuccessAction action,
final String expression) {
conditions.setSuccessAction(action);
conditions.setSuccessActionExp(expression);
return this;
}
/**
* Sets the error condition and expression on the builder.
*
* @param condition
* the error condition
* @param expression
* the error expression
* @return the builder itself
*/
public RolloutGroupConditionBuilder errorCondition(final RolloutGroupErrorCondition condition,
final String expression) {
conditions.setErrorCondition(condition);
conditions.setErrorConditionExp(expression);
return this;
}
/**
* Sets the error action and expression on the builder.
*
* @param action
* the error action
* @param expression
* the error expression
* @return the builder itself
*/
public RolloutGroupConditionBuilder errorAction(final RolloutGroupErrorAction action, final String expression) {
conditions.setErrorAction(action);
conditions.setErrorActionExp(expression);
return this;
}
}
}

View File

@@ -0,0 +1,266 @@
/**
* 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.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.ExternalArtifact;
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.eclipse.persistence.annotations.CascadeOnDelete;
/**
* Base Software Module that is supported by OS level provisioning mechanism on
* the edge controller, e.g. OS, JVM, AgentHub.
*
*/
@Entity
@Table(name = "sp_base_software_module", uniqueConstraints = @UniqueConstraint(columnNames = { "module_type", "name",
"version", "tenant" }, name = "uk_base_sw_mod"), indexes = {
@Index(name = "sp_idx_base_sw_module_01", columnList = "tenant,deleted,name,version"),
@Index(name = "sp_idx_base_sw_module_02", columnList = "tenant,deleted,module_type"),
@Index(name = "sp_idx_base_sw_module_prim", columnList = "tenant,id") })
@NamedEntityGraph(name = "SoftwareModule.artifacts", attributeNodes = { @NamedAttributeNode("artifacts") })
public class JpaSoftwareModule extends JpaNamedVersionedEntity implements SoftwareModule {
private static final long serialVersionUID = 1L;
@ManyToOne
@JoinColumn(name = "module_type", nullable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_module_type"))
private JpaSoftwareModuleType type;
@ManyToMany(mappedBy = "modules", targetEntity = JpaDistributionSet.class, fetch = FetchType.LAZY)
private final List<DistributionSet> assignedTo = new ArrayList<>();
@Column(name = "deleted")
private boolean deleted = false;
@Column(name = "vendor", nullable = true, length = 256)
private String vendor;
@OneToMany(mappedBy = "softwareModule", cascade = { CascadeType.ALL }, targetEntity = JpaLocalArtifact.class)
private List<LocalArtifact> artifacts;
@OneToMany(mappedBy = "softwareModule", cascade = { CascadeType.ALL }, targetEntity = JpaExternalArtifact.class)
private List<ExternalArtifact> externalArtifacts;
@CascadeOnDelete
@OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.REMOVE }, targetEntity = JpaSoftwareModuleMetadata.class)
@JoinColumn(name = "sw_id", insertable = false, updatable = false)
private final List<SoftwareModuleMetadata> metadata = new ArrayList<>();
/**
* Default constructor.
*/
public JpaSoftwareModule() {
super();
}
/**
* parameterized constructor.
*
* @param type
* of the {@link SoftwareModule}
* @param name
* abstract name of the {@link SoftwareModule}
* @param version
* of the {@link SoftwareModule}
* @param description
* of the {@link SoftwareModule}
* @param vendor
* of the {@link SoftwareModule}
*/
public JpaSoftwareModule(final SoftwareModuleType type, final String name, final String version,
final String description, final String vendor) {
super(name, version, description);
this.vendor = vendor;
this.type = (JpaSoftwareModuleType) type;
}
/**
* @param artifact
* is added to the assigned {@link Artifact}s.
*/
@Override
public void addArtifact(final LocalArtifact artifact) {
if (null == artifacts) {
artifacts = new ArrayList<>(4);
}
if (!artifacts.contains(artifact)) {
artifacts.add(artifact);
}
}
/**
* @param artifact
* is added to the assigned {@link Artifact}s.
*/
@Override
public void addArtifact(final ExternalArtifact artifact) {
if (null == externalArtifacts) {
externalArtifacts = new ArrayList<>(4);
}
if (!externalArtifacts.contains(artifact)) {
externalArtifacts.add(artifact);
}
}
/**
* @param artifactId
* to look for
* @return found {@link Artifact}
*/
@Override
public Optional<LocalArtifact> getLocalArtifact(final Long artifactId) {
if (null == artifacts) {
return Optional.empty();
}
return artifacts.stream().filter(artifact -> artifact.getId().equals(artifactId)).findFirst();
}
/**
* @param fileName
* to look for
* @return found {@link Artifact}
*/
@Override
public Optional<LocalArtifact> getLocalArtifactByFilename(final String fileName) {
if (null == artifacts) {
return Optional.empty();
}
return artifacts.stream().filter(artifact -> artifact.getFilename().equalsIgnoreCase(fileName.trim()))
.findFirst();
}
/**
* @return the artifacts
*/
@Override
public List<Artifact> getArtifacts() {
final List<Artifact> result = new ArrayList<>();
result.addAll(artifacts);
result.addAll(externalArtifacts);
return result;
}
/**
* @return local artifacts only
*/
@Override
public List<LocalArtifact> getLocalArtifacts() {
if (artifacts == null) {
return Collections.emptyList();
}
return artifacts;
}
@Override
public String getVendor() {
return vendor;
}
/**
* @param artifact
* is removed from the assigned {@link LocalArtifact}s.
*/
@Override
public void removeArtifact(final LocalArtifact artifact) {
if (null != artifacts) {
artifacts.remove(artifact);
}
}
/**
* @param artifact
* is removed from the assigned {@link ExternalArtifact}s.
*/
@Override
public void removeArtifact(final ExternalArtifact artifact) {
if (null != externalArtifacts) {
externalArtifacts.remove(artifact);
}
}
@Override
public void setVendor(final String vendor) {
this.vendor = vendor;
}
@Override
public SoftwareModuleType getType() {
return type;
}
@Override
public boolean isDeleted() {
return deleted;
}
@Override
public void setDeleted(final boolean deleted) {
this.deleted = deleted;
}
@Override
public void setType(final SoftwareModuleType type) {
this.type = (JpaSoftwareModuleType) type;
}
/**
* @return immutable list of meta data elements.
*/
@Override
public List<SoftwareModuleMetadata> getMetadata() {
return Collections.unmodifiableList(metadata);
}
@Override
public String toString() {
return "SoftwareModule [deleted=" + deleted + ", name=" + getName() + ", version=" + getVersion()
+ ", revision=" + getOptLockRevision() + ", Id=" + getId() + ", type=" + getType().getName() + "]";
}
/**
* @return the assignedTo
*/
@Override
public List<DistributionSet> getAssignedTo() {
return assignedTo;
}
}

View File

@@ -0,0 +1,85 @@
/**
* 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.model;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
/**
* Metadata for {@link SoftwareModule}.
*
*/
@IdClass(SwMetadataCompositeKey.class)
@Entity
@Table(name = "sp_sw_metadata")
public class JpaSoftwareModuleMetadata extends JpaMetaData implements SoftwareModuleMetadata {
private static final long serialVersionUID = 1L;
@Id
@ManyToOne(targetEntity = JpaSoftwareModule.class, fetch = FetchType.LAZY)
@JoinColumn(name = "sw_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_metadata_sw"))
private SoftwareModule softwareModule;
public JpaSoftwareModuleMetadata() {
// default public constructor for JPA
}
public JpaSoftwareModuleMetadata(final String key, final SoftwareModule softwareModule, final String value) {
super(key, value);
this.softwareModule = softwareModule;
}
public SwMetadataCompositeKey getId() {
return new SwMetadataCompositeKey(softwareModule, getKey());
}
@Override
public SoftwareModule getSoftwareModule() {
return softwareModule;
}
@Override
public void setSoftwareModule(final SoftwareModule softwareModule) {
this.softwareModule = softwareModule;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((softwareModule == null) ? 0 : softwareModule.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (!super.equals(obj)) {
return false;
}
final JpaSoftwareModuleMetadata other = (JpaSoftwareModuleMetadata) obj;
if (softwareModule == null) {
if (other.softwareModule != null) {
return false;
}
} else if (!softwareModule.equals(other.softwareModule)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,125 @@
/**
* 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.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
/**
* Type of a software modules.
*
*/
@Entity
@Table(name = "sp_software_module_type", indexes = {
@Index(name = "sp_idx_software_module_type_01", columnList = "tenant,deleted"),
@Index(name = "sp_idx_software_module_type_prim", columnList = "tenant,id") }, uniqueConstraints = {
@UniqueConstraint(columnNames = { "type_key", "tenant" }, name = "uk_smt_type_key"),
@UniqueConstraint(columnNames = { "name", "tenant" }, name = "uk_smt_name") })
public class JpaSoftwareModuleType extends JpaNamedEntity implements SoftwareModuleType {
private static final long serialVersionUID = 1L;
@Column(name = "type_key", nullable = false, length = 64)
private String key;
@Column(name = "max_ds_assignments", nullable = false)
private int maxAssignments;
@Column(name = "colour", nullable = true, length = 16)
private String colour;
@Column(name = "deleted")
private boolean deleted = false;
/**
* Constructor.
*
* @param key
* of the type
* @param name
* of the type
* @param description
* of the type
* @param maxAssignments
* assignments to a DS
*/
public JpaSoftwareModuleType(final String key, final String name, final String description, final int maxAssignments) {
this(key, name, description, maxAssignments, null);
}
/**
* Constructor.
*
* @param key
* of the type
* @param name
* of the type
* @param description
* of the type
* @param maxAssignments
* assignments to a DS
* @param colour
* of the type. It will be null by default
*/
public JpaSoftwareModuleType(final String key, final String name, final String description, final int maxAssignments,
final String colour) {
super();
this.key = key;
this.maxAssignments = maxAssignments;
setDescription(description);
setName(name);
this.colour = colour;
}
/**
* Default Constructor.
*/
public JpaSoftwareModuleType() {
super();
}
@Override
public String getKey() {
return key;
}
@Override
public int getMaxAssignments() {
return maxAssignments;
}
@Override
public boolean isDeleted() {
return deleted;
}
@Override
public void setDeleted(final boolean deleted) {
this.deleted = deleted;
}
@Override
public String getColour() {
return colour;
}
@Override
public void setColour(final String colour) {
this.colour = colour;
}
@Override
public String toString() {
return "SoftwareModuleType [key=" + key + ", getName()=" + getName() + ", getId()=" + getId() + "]";
}
}

View File

@@ -0,0 +1,61 @@
/**
* 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.model;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import org.eclipse.hawkbit.repository.model.Tag;
/**
* A Tag can be used as describing and organizational meta information for any
* kind of entity.
*
*/
@MappedSuperclass
public abstract class JpaTag extends JpaNamedEntity implements Tag {
private static final long serialVersionUID = 1L;
@Column(name = "colour", nullable = true, length = 16)
private String colour;
protected JpaTag() {
super();
}
/**
* Public constructor.
*
* @param name
* of the {@link Tag}
* @param description
* of the {@link Tag}
* @param colour
* of tag in UI
*/
public JpaTag(final String name, final String description, final String colour) {
super(name, description);
this.colour = colour;
}
@Override
public String getColour() {
return colour;
}
@Override
public void setColour(final String colour) {
this.colour = colour;
}
@Override
public String toString() {
return "Tag [getOptLockRevision()=" + getOptLockRevision() + ", getId()=" + getId() + "]";
}
}

View File

@@ -0,0 +1,237 @@
/**
* 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.model;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetIdName;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.helper.SecurityChecker;
import org.eclipse.hawkbit.repository.model.helper.SecurityTokenGeneratorHolder;
import org.eclipse.persistence.annotations.CascadeOnDelete;
import org.springframework.data.domain.Persistable;
/**
* <p>
* The {@link Target} is the target of all provisioning operations. It contains
* the currently installed {@link DistributionSet} (i.e. current state). In
* addition it holds the target {@link DistributionSet} that has to be
* provisioned next (i.e. target state).
* </p>
*
* <p>
* {@link #getStatus()}s() shows if the {@link Target} is
* {@link TargetStatus#IN_SYNC} or a provisioning is
* {@link TargetStatus#PENDING} or the target is only
* {@link TargetStatus#REGISTERED}, i.e. a target {@link DistributionSet} .
* </p>
*
*/
@Entity
@Table(name = "sp_target", indexes = {
@Index(name = "sp_idx_target_01", columnList = "tenant,name,assigned_distribution_set"),
@Index(name = "sp_idx_target_02", columnList = "tenant,name"),
@Index(name = "sp_idx_target_03", columnList = "tenant,controller_id,assigned_distribution_set"),
@Index(name = "sp_idx_target_04", columnList = "tenant,created_at"),
@Index(name = "sp_idx_target_prim", columnList = "tenant,id") }, uniqueConstraints = @UniqueConstraint(columnNames = {
"controller_id", "tenant" }, name = "uk_tenant_controller_id"))
@NamedEntityGraph(name = "Target.detail", attributeNodes = { @NamedAttributeNode("tags"),
@NamedAttributeNode(value = "assignedDistributionSet"), @NamedAttributeNode(value = "targetInfo") })
public class JpaTarget extends JpaNamedEntity implements Persistable<Long>, Target {
private static final long serialVersionUID = 1L;
@Column(name = "controller_id", length = 64)
@Size(min = 1)
@NotNull
private String controllerId;
@Transient
private boolean entityNew = false;
@ManyToMany(targetEntity = JpaTargetTag.class)
@JoinTable(name = "sp_target_target_tag", joinColumns = {
@JoinColumn(name = "target", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_targtag_target")) }, inverseJoinColumns = {
@JoinColumn(name = "tag", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_targtag_tag")) })
private Set<TargetTag> tags = new HashSet<>();
@CascadeOnDelete
@OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, cascade = {
CascadeType.REMOVE }, targetEntity = JpaAction.class)
@JoinColumn(name = "target", insertable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_act_hist_targ"))
private final List<Action> actions = new ArrayList<>();
@ManyToOne(optional = true, fetch = FetchType.LAZY, targetEntity = JpaDistributionSet.class)
@JoinColumn(name = "assigned_distribution_set", nullable = true, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_assign_ds"))
private JpaDistributionSet assignedDistributionSet;
@CascadeOnDelete
@OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, targetEntity = JpaTargetInfo.class)
@PrimaryKeyJoinColumn
private JpaTargetInfo targetInfo = null;
/**
* the security token of the target which allows if enabled to authenticate
* with this security token.
*/
@Column(name = "sec_token", insertable = true, updatable = true, nullable = false, length = 128)
private String securityToken = null;
@CascadeOnDelete
@OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.REMOVE, CascadeType.PERSIST })
@JoinColumn(name = "target_Id", insertable = false, updatable = false)
private final List<RolloutTargetGroup> rolloutTargetGroup = new ArrayList<>();
/**
* Constructor.
*
* @param controllerId
* controller ID of the {@link Target}
*/
public JpaTarget(final String controllerId) {
this.controllerId = controllerId;
setName(controllerId);
securityToken = SecurityTokenGeneratorHolder.getInstance().generateToken();
targetInfo = new JpaTargetInfo(this);
}
/**
* empty constructor for JPA.
*/
JpaTarget() {
controllerId = null;
securityToken = null;
}
@Override
public DistributionSet getAssignedDistributionSet() {
return assignedDistributionSet;
}
@Override
public String getControllerId() {
return controllerId;
}
@Override
public Set<TargetTag> getTags() {
return tags;
}
@Override
public void setAssignedDistributionSet(final DistributionSet assignedDistributionSet) {
this.assignedDistributionSet = (JpaDistributionSet) assignedDistributionSet;
}
@Override
public void setControllerId(final String controllerId) {
this.controllerId = controllerId;
}
@Override
public void setTags(final Set<TargetTag> tags) {
this.tags = tags;
}
@Override
public List<Action> getActions() {
return actions;
}
@Override
public TargetIdName getTargetIdName() {
return new TargetIdName(getId(), getControllerId(), getName());
}
@Override
@Transient
public boolean isNew() {
return entityNew;
}
/**
* @param isNew
* the isNew to set
*/
public void setNew(final boolean entityNew) {
this.entityNew = entityNew;
}
/**
* @return the targetInfo
*/
@Override
public TargetInfo getTargetInfo() {
return targetInfo;
}
/**
* @param targetInfo
* the targetInfo to set
*/
@Override
public void setTargetInfo(final TargetInfo targetInfo) {
this.targetInfo = (JpaTargetInfo) targetInfo;
}
/**
* @return the securityToken
*/
@Override
public String getSecurityToken() {
if (SecurityChecker.hasPermission(SpPermission.READ_TARGET_SEC_TOKEN)) {
return securityToken;
}
return null;
}
/**
* @param securityToken
* the securityToken to set
*/
@Override
public void setSecurityToken(final String securityToken) {
this.securityToken = securityToken;
}
@Override
public String toString() {
return "Target [controllerId=" + controllerId + ", getId()=" + getId() + "]";
}
}

View File

@@ -0,0 +1,64 @@
/**
* 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.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Stored target filter.
*
*/
@Entity
@Table(name = "sp_target_filter_query", indexes = {
@Index(name = "sp_idx_target_filter_query_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = {
"name", "tenant" }, name = "uk_tenant_custom_filter_name"))
public class JpaTargetFilterQuery extends JpaTenantAwareBaseEntity implements TargetFilterQuery {
private static final long serialVersionUID = 7493966984413479089L;
@Column(name = "name", length = 64)
private String name;
@Column(name = "query", length = 1024)
private String query;
public JpaTargetFilterQuery() {
// Default constructor for JPA.
}
public JpaTargetFilterQuery(final String name, final String query) {
this.name = name;
this.query = query;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(final String name) {
this.name = name;
}
@Override
public String getQuery() {
return query;
}
@Override
public void setQuery(final String query) {
this.query = query;
}
}

View File

@@ -0,0 +1,372 @@
/**
* 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.model;
import java.net.URI;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyColumn;
import javax.persistence.MapsId;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder;
import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.eclipse.persistence.annotations.CascadeOnDelete;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Persistable;
/**
* A table which contains all the information inserted, updated by the
* controller itself. So this entity does not provide audit information because
* changes on this entity are mostly only done by controller requests. That's
* the reason that we store these information in a separated table so we don't
* modifying the {@link Target} itself when a controller reports it's
* {@link #lastTargetQuery} for example.
*
*/
@Table(name = "sp_target_info", indexes = {
@Index(name = "sp_idx_target_info_02", columnList = "target_id,update_status") })
@Entity
public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class);
@Id
private Long targetId;
@Transient
private boolean entityNew = false;
@CascadeOnDelete
@OneToOne(cascade = { CascadeType.MERGE,
CascadeType.REMOVE }, fetch = FetchType.LAZY, targetEntity = JpaTarget.class)
@JoinColumn(name = "target_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_stat_targ"))
@MapsId
private JpaTarget target;
@Column(name = "address", length = 512)
private String address = null;
@Column(name = "last_target_query")
private Long lastTargetQuery = null;
@Column(name = "install_date")
private Long installationDate;
@Column(name = "update_status", nullable = false, length = 255)
@Enumerated(EnumType.STRING)
private TargetUpdateStatus updateStatus = TargetUpdateStatus.UNKNOWN;
@ManyToOne(optional = true, fetch = FetchType.LAZY)
@JoinColumn(name = "installed_distribution_set", nullable = true, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_inst_ds"))
private JpaDistributionSet installedDistributionSet;
/**
* Read only on management API. Are commited by controller.
*/
@ElementCollection
@Column(name = "attribute_value", length = 128)
@MapKeyColumn(name = "attribute_key", nullable = false, length = 32)
@CollectionTable(name = "sp_target_attributes", joinColumns = {
@JoinColumn(name = "target_id") }, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_targ_attrib_target"))
private final Map<String, String> controllerAttributes = Collections.synchronizedMap(new HashMap<String, String>());
// set default request controller attributes to true, because we want to
// request them the first
// time
@Column(name = "request_controller_attributes", nullable = false)
private boolean requestControllerAttributes = true;
/**
* Constructor for {@link TargetStatus}.
*
* @param target
* related to this status.
*/
public JpaTargetInfo(final JpaTarget target) {
this.target = target;
targetId = target.getId();
}
JpaTargetInfo() {
target = null;
targetId = null;
}
@Override
public Long getId() {
return targetId;
}
@Override
@Transient
public boolean isNew() {
return entityNew;
}
/**
* @param isNew
* the isNew to set
*/
public void setNew(final boolean entityNew) {
this.entityNew = entityNew;
}
/**
* @return the ipAddress
*/
@Override
public URI getAddress() {
if (address == null) {
return null;
}
try {
return URI.create(address);
} catch (final IllegalArgumentException e) {
LOG.warn("Invalid address provided. Cloud not be configured to URI", e);
return null;
}
}
/**
* @param address
* the ipAddress to set
*
* @throws IllegalArgumentException
* If the given string violates RFC&nbsp;2396
*/
public void setAddress(final String address) {
// check if this is a real URI
if (address != null) {
URI.create(address);
}
this.address = address;
}
public Long getTargetId() {
return targetId;
}
public void setTargetId(final Long targetId) {
this.targetId = targetId;
}
@Override
public Target getTarget() {
return target;
}
public void setTarget(final JpaTarget target) {
this.target = target;
}
@Override
public Long getLastTargetQuery() {
return lastTargetQuery;
}
public void setLastTargetQuery(final Long lastTargetQuery) {
this.lastTargetQuery = lastTargetQuery;
}
public void setRequestControllerAttributes(final boolean requestControllerAttributes) {
this.requestControllerAttributes = requestControllerAttributes;
}
@Override
public Map<String, String> getControllerAttributes() {
return controllerAttributes;
}
public boolean isRequestControllerAttributes() {
return requestControllerAttributes;
}
@Override
public Long getInstallationDate() {
return installationDate;
}
public void setInstallationDate(final Long installationDate) {
this.installationDate = installationDate;
}
@Override
public TargetUpdateStatus getUpdateStatus() {
return updateStatus;
}
public void setUpdateStatus(final TargetUpdateStatus updateStatus) {
this.updateStatus = updateStatus;
}
@Override
public DistributionSet getInstalledDistributionSet() {
return installedDistributionSet;
}
public void setInstalledDistributionSet(final JpaDistributionSet installedDistributionSet) {
this.installedDistributionSet = installedDistributionSet;
}
/**
* @return the poll time which holds the last poll time of the target, the
* next poll time and the overdue time. In case the
* {@link #lastTargetQuery} is not set e.g. the target never polled
* before this method returns {@code null}
*/
@Override
public PollStatus getPollStatus() {
if (lastTargetQuery == null) {
return null;
}
return SystemSecurityContextHolder.getInstance().getSystemSecurityContext().runAsSystem(() -> {
final Duration pollTime = DurationHelper.formattedStringToDuration(TenantConfigurationManagementHolder
.getInstance().getTenantConfigurationManagement()
.getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class).getValue());
final Duration overdueTime = DurationHelper.formattedStringToDuration(
TenantConfigurationManagementHolder.getInstance().getTenantConfigurationManagement()
.getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class)
.getValue());
final LocalDateTime currentDate = LocalDateTime.now();
final LocalDateTime lastPollDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastTargetQuery),
ZoneId.systemDefault());
final LocalDateTime nextPollDate = lastPollDate.plus(pollTime);
final LocalDateTime overdueDate = nextPollDate.plus(overdueTime);
return new PollStatus(lastPollDate, nextPollDate, overdueDate, currentDate);
});
}
/**
* The poll time object which holds all the necessary information around the
* target poll time, e.g. the last poll time, the next poll time and the
* overdue poll time.
*
*/
public static final class PollStatus {
private final LocalDateTime lastPollDate;
private final LocalDateTime nextPollDate;
private final LocalDateTime overdueDate;
private final LocalDateTime currentDate;
private PollStatus(final LocalDateTime lastPollDate, final LocalDateTime nextPollDate,
final LocalDateTime overdueDate, final LocalDateTime currentDate) {
this.lastPollDate = lastPollDate;
this.nextPollDate = nextPollDate;
this.overdueDate = overdueDate;
this.currentDate = currentDate;
}
/**
* calculates if the target poll time is overdue and the target has not
* been polled in the configured poll time interval.
*
* @return {@code true} if the current time is after the poll time
* overdue date otherwise {@code false}.
*/
public boolean isOverdue() {
return currentDate.isAfter(overdueDate);
}
/**
* @return the lastPollDate
*/
public LocalDateTime getLastPollDate() {
return lastPollDate;
}
public LocalDateTime getNextPollDate() {
return nextPollDate;
}
public LocalDateTime getOverdueDate() {
return overdueDate;
}
public LocalDateTime getCurrentDate() {
return currentDate;
}
@Override
public String toString() {
return "PollTime [lastPollDate=" + lastPollDate + ", nextPollDate=" + nextPollDate + ", overdueDate="
+ overdueDate + ", currentDate=" + currentDate + "]";
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((target == null) ? 0 : target.hashCode());
result = prime * result + ((targetId == null) ? 0 : targetId.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof TargetInfo)) {
return false;
}
final JpaTargetInfo other = (JpaTargetInfo) obj;
if (target == null) {
if (other.target != null) {
return false;
}
} else if (!target.equals(other.target)) {
return false;
}
if (targetId == null) {
if (other.targetId != null) {
return false;
}
} else if (!targetId.equals(other.targetId)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,91 @@
/**
* 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.model;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Index;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag;
/**
* A {@link TargetTag} is used to describe Target attributes and use them also
* for filtering the target list.
*
*/
@Entity
@Table(name = "sp_target_tag", indexes = {
@Index(name = "sp_idx_target_tag_prim", columnList = "tenant,id") }, uniqueConstraints = @UniqueConstraint(columnNames = {
"name", "tenant" }, name = "uk_targ_tag"))
public class JpaTargetTag extends JpaTag implements TargetTag {
private static final long serialVersionUID = 1L;
@ManyToMany(mappedBy = "tags", targetEntity = JpaTarget.class, fetch = FetchType.LAZY)
private List<Target> assignedToTargets;
/**
* Constructor.
*
* @param name
* of {@link TargetTag}
* @param description
* of {@link TargetTag}
* @param colour
* of {@link TargetTag}
*/
public JpaTargetTag(final String name, final String description, final String colour) {
super(name, description, colour);
}
/**
* Public constructor.
*
* @param name
* of the {@link TargetTag}
**/
public JpaTargetTag(final String name) {
super(name, null, null);
}
public JpaTargetTag() {
super();
}
@Override
public List<Target> getAssignedToTargets() {
return assignedToTargets;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + this.getClass().getName().hashCode();
return result;
}
@Override
public boolean equals(final Object obj) {
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof TargetTag)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,115 @@
/**
* 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.model;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import org.eclipse.hawkbit.repository.exception.TenantNotExistException;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
import org.eclipse.hawkbit.repository.model.helper.SystemManagementHolder;
import org.eclipse.hawkbit.repository.model.helper.TenantAwareHolder;
import org.eclipse.persistence.annotations.Multitenant;
import org.eclipse.persistence.annotations.MultitenantType;
import org.eclipse.persistence.annotations.TenantDiscriminatorColumn;
/**
* Holder of the base attributes common to all tenant aware entities.
*
*/
@MappedSuperclass
@TenantDiscriminatorColumn(name = "tenant", length = 40)
@Multitenant(MultitenantType.SINGLE_TABLE)
public abstract class JpaTenantAwareBaseEntity extends JpaBaseEntity implements TenantAwareBaseEntity {
private static final long serialVersionUID = 1L;
@Column(name = "tenant", nullable = false, insertable = false, updatable = false, length = 40)
private String tenant;
/**
* Default constructor needed for JPA entities.
*/
public JpaTenantAwareBaseEntity() {
// Default constructor needed for JPA entities.
}
/**
* PrePersist listener method for all {@link TenantAwareBaseEntity}
* entities.
*/
@PrePersist
public void prePersist() {
// before persisting the entity check the current ID of the tenant by
// using the TenantAware
// service
final String currentTenant = SystemManagementHolder.getInstance().currentTenant();
if (currentTenant == null) {
throw new TenantNotExistException("Tenant "
+ TenantAwareHolder.getInstance().getTenantAware().getCurrentTenant()
+ " does not exists, cannot create entity " + this.getClass() + " with id " + super.getId());
}
setTenant(currentTenant.toUpperCase());
}
@Override
public String getTenant() {
return tenant;
}
public void setTenant(final String tenant) {
this.tenant = tenant;
}
@Override
public String toString() {
return "BaseEntity [id=" + super.getId() + "]";
}
/**
* Tenant aware entities extend the equals/hashcode strategy with the tenant
* name. That would allow for instance in a multi-schema based data
* separation setup to have the same primary key for different entities of
* different tenants.
*
* @see org.eclipse.hawkbit.repository.model.BaseEntity#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + (tenant == null ? 0 : tenant.hashCode());
return result;
}
/**
* Tenant aware entities extend the equals/hashcode strategy with the tenant
* name. That would allow for instance in a multi-schema based data
* separation setup to have the same primary key for different entities of
* different tenants.
*
* @see org.eclipse.hawkbit.repository.model.BaseEntity#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (!super.equals(obj)) {
return false;
}
final JpaTenantAwareBaseEntity other = (JpaTenantAwareBaseEntity) obj;
if (tenant == null) {
if (other.tenant != null) {
return false;
}
} else if (!tenant.equals(other.tenant)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,75 @@
/**
* 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.model;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.model.TenantConfiguration;
/**
* A JPA entity which stores the tenant specific configuration.
*
*/
@Entity
@Table(name = "sp_tenant_configuration", uniqueConstraints = @UniqueConstraint(columnNames = { "conf_key",
"tenant" }, name = "uk_tenant_key"))
public class JpaTenantConfiguration extends JpaTenantAwareBaseEntity implements TenantConfiguration {
private static final long serialVersionUID = 1L;
@Column(name = "conf_key", length = 128)
private String key;
@Column(name = "conf_value", length = 512)
@Basic
private String value;
/**
* JPA default constructor.
*/
public JpaTenantConfiguration() {
// JPA default constructor.
}
/**
* @param key
* the key of this configuration
* @param value
* the value of this configuration
*/
public JpaTenantConfiguration(final String key, final String value) {
this.key = key;
this.value = value;
}
@Override
public String getKey() {
return key;
}
@Override
public void setKey(final String key) {
this.key = key;
}
@Override
public String getValue() {
return value;
}
@Override
public void setValue(final String value) {
this.value = value;
}
}

View File

@@ -0,0 +1,107 @@
/**
* 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.model;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
import org.eclipse.hawkbit.repository.model.TenantMetaData;
/**
* Tenant entity with meta data that is configured globally for the entire
* tenant. This entity is not tenant aware to allow the system to access it
* through the {@link EntityManager} even before the actual tenant exists.
*
* Entities owned by the tenant are based on {@link TenantAwareBaseEntity}.
*
*/
@Table(name = "sp_tenant", indexes = {
@Index(name = "sp_idx_tenant_prim", columnList = "tenant,id") }, uniqueConstraints = {
@UniqueConstraint(columnNames = { "tenant" }, name = "uk_tenantmd_tenant") })
@Entity
public class JpaTenantMetaData extends JpaBaseEntity implements TenantMetaData {
private static final long serialVersionUID = 1L;
@Column(name = "tenant", nullable = false, length = 40)
private String tenant;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "default_ds_type", nullable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_tenant_md_default_ds_type"))
private JpaDistributionSetType defaultDsType;
/**
* Default constructor needed for JPA entities.
*/
public JpaTenantMetaData() {
// Default constructor needed for JPA entities.
}
/**
* Standard constructor.
*
* @param defaultDsType
* of this tenant
* @param tenant
*/
public JpaTenantMetaData(final DistributionSetType defaultDsType, final String tenant) {
super();
this.defaultDsType = (JpaDistributionSetType) defaultDsType;
this.tenant = tenant;
}
@Override
public DistributionSetType getDefaultDsType() {
return defaultDsType;
}
@Override
public void setDefaultDsType(final DistributionSetType defaultDsType) {
this.defaultDsType = (JpaDistributionSetType) defaultDsType;
}
@Override
public String getTenant() {
return tenant;
}
public void setTenant(final String tenant) {
this.tenant = tenant;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + this.getClass().getName().hashCode();
return result;
}
@Override
public boolean equals(final Object obj) {
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof TenantMetaData)) {
return false;
}
return true;
}
}

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
@@ -24,6 +24,9 @@ import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.persistence.annotations.ExistenceChecking; import org.eclipse.persistence.annotations.ExistenceChecking;
import org.eclipse.persistence.annotations.ExistenceType; import org.eclipse.persistence.annotations.ExistenceType;
@@ -41,16 +44,16 @@ public class RolloutTargetGroup implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Id @Id
@ManyToOne(targetEntity = RolloutGroup.class, fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST }) @ManyToOne(targetEntity = JpaRolloutGroup.class, fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST })
@JoinColumn(name = "rolloutGroup_Id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rollouttargetgroup_group") ) @JoinColumn(name = "rolloutGroup_Id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rollouttargetgroup_group"))
private RolloutGroup rolloutGroup; private RolloutGroup rolloutGroup;
@Id @Id
@ManyToOne(targetEntity = Target.class, fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST }) @ManyToOne(targetEntity = JpaTarget.class, fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST })
@JoinColumn(name = "target_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rollouttargetgroup_target") ) @JoinColumn(name = "target_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rollouttargetgroup_target"))
private Target target; private JpaTarget target;
@OneToMany(targetEntity = Action.class, fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST }) @OneToMany(targetEntity = JpaAction.class, fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST })
@JoinColumns(value = { @JoinColumn(name = "rolloutgroup", referencedColumnName = "rolloutGroup_Id"), @JoinColumns(value = { @JoinColumn(name = "rolloutgroup", referencedColumnName = "rolloutGroup_Id"),
@JoinColumn(name = "target", referencedColumnName = "target_id") }) @JoinColumn(name = "target", referencedColumnName = "target_id") })
private List<Action> actions; private List<Action> actions;
@@ -64,7 +67,7 @@ public class RolloutTargetGroup implements Serializable {
public RolloutTargetGroup(final RolloutGroup rolloutGroup, final Target target) { public RolloutTargetGroup(final RolloutGroup rolloutGroup, final Target target) {
this.rolloutGroup = rolloutGroup; this.rolloutGroup = rolloutGroup;
this.target = target; this.target = (JpaTarget) target;
} }
public RolloutTargetGroupId getId() { public RolloutTargetGroupId getId() {

View File

@@ -6,10 +6,13 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serializable; import java.io.Serializable;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.Target;
/** /**
* Combined unique key of the table {@link RolloutTargetGroup}. * Combined unique key of the table {@link RolloutTargetGroup}.
* *

View File

@@ -6,10 +6,12 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serializable; import java.io.Serializable;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
/** /**
* The Software Module meta data composite key which contains the meta data key * The Software Module meta data composite key which contains the meta data key
* and the ID of the software module itself. * and the ID of the software module itself.

View File

@@ -6,20 +6,22 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.specifications; package org.eclipse.hawkbit.repository.jpa.specifications;
import javax.persistence.criteria.Join; import javax.persistence.criteria.Join;
import javax.persistence.criteria.ListJoin; import javax.persistence.criteria.ListJoin;
import javax.persistence.criteria.SetJoin; import javax.persistence.criteria.SetJoin;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.model.JpaLocalArtifact;
import org.eclipse.hawkbit.repository.jpa.model.JpaLocalArtifact_;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule_;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action_;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSet_;
import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.LocalArtifact_;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModule_;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
@@ -28,7 +30,7 @@ import org.springframework.data.jpa.domain.Specification;
* Spring Data JPQL Specifications. * Spring Data JPQL Specifications.
* *
*/ */
public class ActionSpecifications { public final class ActionSpecifications {
private ActionSpecifications() { private ActionSpecifications() {
// utility class // utility class
@@ -47,15 +49,16 @@ public class ActionSpecifications {
* assigned * assigned
* @return a specification to use with spring JPA * @return a specification to use with spring JPA
*/ */
public static Specification<Action> hasTargetAssignedArtifact(final Target target, public static Specification<JpaAction> hasTargetAssignedArtifact(final Target target,
final LocalArtifact localArtifact) { final LocalArtifact localArtifact) {
return (actionRoot, query, criteriaBuilder) -> { return (actionRoot, query, criteriaBuilder) -> {
final Join<Action, DistributionSet> dsJoin = actionRoot.join(Action_.distributionSet); final Join<JpaAction, JpaDistributionSet> dsJoin = actionRoot.join(JpaAction_.distributionSet);
final SetJoin<DistributionSet, SoftwareModule> modulesJoin = dsJoin.join(DistributionSet_.modules); final SetJoin<JpaDistributionSet, JpaSoftwareModule> modulesJoin = dsJoin.join(JpaDistributionSet_.modules);
final ListJoin<SoftwareModule, LocalArtifact> artifactsJoin = modulesJoin.join(SoftwareModule_.artifacts); final ListJoin<JpaSoftwareModule, JpaLocalArtifact> artifactsJoin = modulesJoin
.join(JpaSoftwareModule_.artifacts);
return criteriaBuilder.and( return criteriaBuilder.and(
criteriaBuilder.equal(artifactsJoin.get(LocalArtifact_.filename), localArtifact.getFilename()), criteriaBuilder.equal(artifactsJoin.get(JpaLocalArtifact_.filename), localArtifact.getFilename()),
criteriaBuilder.equal(actionRoot.get(Action_.target), target)); criteriaBuilder.equal(actionRoot.get(JpaAction_.target), target));
}; };
} }
} }

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.specifications; package org.eclipse.hawkbit.repository.jpa.specifications;
import java.util.Collection; import java.util.Collection;
@@ -18,15 +18,17 @@ import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.SetJoin; import javax.persistence.criteria.SetJoin;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag_;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetTag_;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.DistributionSet_;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetInfo_;
import org.eclipse.hawkbit.repository.model.Target_;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
/** /**
@@ -48,8 +50,8 @@ public final class DistributionSetSpecification {
* attribute is ignored * attribute is ignored
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<DistributionSet> isDeleted(final Boolean isDeleted) { public static Specification<JpaDistributionSet> isDeleted(final Boolean isDeleted) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(DistributionSet_.deleted), isDeleted); return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSet_.deleted), isDeleted);
} }
@@ -62,8 +64,8 @@ public final class DistributionSetSpecification {
* the attribute is ignored * the attribute is ignored
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<DistributionSet> isCompleted(final Boolean isCompleted) { public static Specification<JpaDistributionSet> isCompleted(final Boolean isCompleted) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(DistributionSet_.complete), isCompleted); return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSet_.complete), isCompleted);
} }
@@ -75,12 +77,12 @@ public final class DistributionSetSpecification {
* to search * to search
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<DistributionSet> byId(final Long distid) { public static Specification<JpaDistributionSet> byId(final Long distid) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final Predicate predicate = cb.equal(targetRoot.<Long> get(DistributionSet_.id), distid); final Predicate predicate = cb.equal(targetRoot.<Long> get(JpaDistributionSet_.id), distid);
targetRoot.fetch(DistributionSet_.modules, JoinType.LEFT); targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
targetRoot.fetch(DistributionSet_.tags, JoinType.LEFT); targetRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT);
targetRoot.fetch(DistributionSet_.type, JoinType.LEFT); targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
query.distinct(true); query.distinct(true);
return predicate; return predicate;
@@ -95,12 +97,12 @@ public final class DistributionSetSpecification {
* to search * to search
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<DistributionSet> byIds(final Collection<Long> distids) { public static Specification<JpaDistributionSet> byIds(final Collection<Long> distids) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final Predicate predicate = targetRoot.<Long> get(DistributionSet_.id).in(distids); final Predicate predicate = targetRoot.<Long> get(JpaDistributionSet_.id).in(distids);
targetRoot.fetch(DistributionSet_.modules, JoinType.LEFT); targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
targetRoot.fetch(DistributionSet_.tags, JoinType.LEFT); targetRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT);
targetRoot.fetch(DistributionSet_.type, JoinType.LEFT); targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
query.distinct(true); query.distinct(true);
return predicate; return predicate;
}; };
@@ -114,11 +116,11 @@ public final class DistributionSetSpecification {
* to be filtered on * to be filtered on
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<DistributionSet> likeNameOrDescriptionOrVersion(final String subString) { public static Specification<JpaDistributionSet> likeNameOrDescriptionOrVersion(final String subString) {
return (targetRoot, query, cb) -> cb.or( return (targetRoot, query, cb) -> cb.or(
cb.like(cb.lower(targetRoot.<String> get(DistributionSet_.name)), subString.toLowerCase()), cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.name)), subString.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(DistributionSet_.version)), subString.toLowerCase()), cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.version)), subString.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(DistributionSet_.description)), subString.toLowerCase())); cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.description)), subString.toLowerCase()));
} }
/** /**
@@ -131,10 +133,10 @@ public final class DistributionSetSpecification {
* flag to select distribution sets with no tag * flag to select distribution sets with no tag
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<DistributionSet> hasTags(final Collection<String> tagNames, public static Specification<JpaDistributionSet> hasTags(final Collection<String> tagNames,
final Boolean selectDSWithNoTag) { final Boolean selectDSWithNoTag) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final SetJoin<DistributionSet, DistributionSetTag> tags = targetRoot.join(DistributionSet_.tags, final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags = targetRoot.join(JpaDistributionSet_.tags,
JoinType.LEFT); JoinType.LEFT);
final Predicate predicate = getPredicate(tags, tagNames, selectDSWithNoTag, cb); final Predicate predicate = getPredicate(tags, tagNames, selectDSWithNoTag, cb);
query.distinct(true); query.distinct(true);
@@ -142,10 +144,10 @@ public final class DistributionSetSpecification {
}; };
} }
private static Predicate getPredicate(final SetJoin<DistributionSet, DistributionSetTag> tags, private static Predicate getPredicate(final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags,
final Collection<String> tagNames, final Boolean selectDSWithNoTag, final CriteriaBuilder cb) { final Collection<String> tagNames, final Boolean selectDSWithNoTag, final CriteriaBuilder cb) {
tags.get(DistributionSetTag_.name); tags.get(JpaDistributionSetTag_.name);
final Path<String> exp = tags.get(DistributionSetTag_.name); final Path<String> exp = tags.get(JpaDistributionSetTag_.name);
if (selectDSWithNoTag != null && selectDSWithNoTag) { if (selectDSWithNoTag != null && selectDSWithNoTag) {
if (tagNames != null) { if (tagNames != null) {
return cb.or(exp.isNull(), exp.in(tagNames)); return cb.or(exp.isNull(), exp.in(tagNames));
@@ -167,11 +169,11 @@ public final class DistributionSetSpecification {
* to be filtered on * to be filtered on
* @return the {@link Specification} * @return the {@link Specification}
*/ */
public static Specification<DistributionSet> equalsNameAndVersionIgnoreCase(final String name, public static Specification<JpaDistributionSet> equalsNameAndVersionIgnoreCase(final String name,
final String version) { final String version) {
return (targetRoot, query, cb) -> cb.and( return (targetRoot, query, cb) -> cb.and(
cb.equal(cb.lower(targetRoot.<String> get(DistributionSet_.name)), name.toLowerCase()), cb.equal(cb.lower(targetRoot.<String> get(JpaDistributionSet_.name)), name.toLowerCase()),
cb.equal(cb.lower(targetRoot.<String> get(DistributionSet_.version)), version.toLowerCase())); cb.equal(cb.lower(targetRoot.<String> get(JpaDistributionSet_.version)), version.toLowerCase()));
} }
@@ -183,8 +185,9 @@ public final class DistributionSetSpecification {
* to search * to search
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<DistributionSet> byType(final DistributionSetType type) { public static Specification<JpaDistributionSet> byType(final DistributionSetType type) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<DistributionSetType> get(DistributionSet_.type), type); return (targetRoot, query, cb) -> cb.equal(targetRoot.<JpaDistributionSetType> get(JpaDistributionSet_.type),
type);
} }
@@ -195,12 +198,12 @@ public final class DistributionSetSpecification {
* @return the specification to search for a distribution set which is * @return the specification to search for a distribution set which is
* installed to the given targetId * installed to the given targetId
*/ */
public static Specification<DistributionSet> installedTarget(final String installedTargetId) { public static Specification<JpaDistributionSet> installedTarget(final String installedTargetId) {
return (dsRoot, query, cb) -> { return (dsRoot, query, cb) -> {
final ListJoin<DistributionSet, TargetInfo> installedTargetJoin = dsRoot final ListJoin<JpaDistributionSet, JpaTargetInfo> installedTargetJoin = dsRoot
.join(DistributionSet_.installedAtTargets, JoinType.INNER); .join(JpaDistributionSet_.installedAtTargets, JoinType.INNER);
final Join<TargetInfo, Target> targetJoin = installedTargetJoin.join(TargetInfo_.target); final Join<JpaTargetInfo, JpaTarget> targetJoin = installedTargetJoin.join(JpaTargetInfo_.target);
return cb.equal(targetJoin.get(Target_.controllerId), installedTargetId); return cb.equal(targetJoin.get(JpaTarget_.controllerId), installedTargetId);
}; };
} }
@@ -211,11 +214,11 @@ public final class DistributionSetSpecification {
* @return the specification to search for a distribution set which is * @return the specification to search for a distribution set which is
* assigned to the given targetId * assigned to the given targetId
*/ */
public static Specification<DistributionSet> assignedTarget(final String assignedTargetId) { public static Specification<JpaDistributionSet> assignedTarget(final String assignedTargetId) {
return (dsRoot, query, cb) -> { return (dsRoot, query, cb) -> {
final ListJoin<DistributionSet, Target> assignedTargetJoin = dsRoot.join(DistributionSet_.assignedToTargets, final ListJoin<JpaDistributionSet, JpaTarget> assignedTargetJoin = dsRoot
JoinType.INNER); .join(JpaDistributionSet_.assignedToTargets, JoinType.INNER);
return cb.equal(assignedTargetJoin.get(Target_.controllerId), assignedTargetId); return cb.equal(assignedTargetJoin.get(JpaTarget_.controllerId), assignedTargetId);
}; };
} }

View File

@@ -6,11 +6,12 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.specifications; package org.eclipse.hawkbit.repository.jpa.specifications;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType_;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.DistributionSetType_;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
/** /**
@@ -31,8 +32,9 @@ public final class DistributionSetTypeSpecification {
* attribute is ignored * attribute is ignored
* @return the {@link DistributionSetType} {@link Specification} * @return the {@link DistributionSetType} {@link Specification}
*/ */
public static Specification<DistributionSetType> isDeleted(final Boolean isDeleted) { public static Specification<JpaDistributionSetType> isDeleted(final Boolean isDeleted) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(DistributionSetType_.deleted), isDeleted); return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSetType_.deleted),
isDeleted);
} }
/** /**
@@ -44,8 +46,8 @@ public final class DistributionSetTypeSpecification {
* to search * to search
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<DistributionSetType> byId(final Long distid) { public static Specification<JpaDistributionSetType> byId(final Long distid) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Long> get(DistributionSetType_.id), distid); return (targetRoot, query, cb) -> cb.equal(targetRoot.<Long> get(JpaDistributionSetType_.id), distid);
} }
/** /**
@@ -57,8 +59,8 @@ public final class DistributionSetTypeSpecification {
* to search * to search
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<DistributionSetType> byName(final String name) { public static Specification<JpaDistributionSetType> byName(final String name) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<String> get(DistributionSetType_.name), name); return (targetRoot, query, cb) -> cb.equal(targetRoot.<String> get(JpaDistributionSetType_.name), name);
} }
/** /**
@@ -70,8 +72,8 @@ public final class DistributionSetTypeSpecification {
* to search * to search
* @return the {@link DistributionSet} {@link Specification} * @return the {@link DistributionSet} {@link Specification}
*/ */
public static Specification<DistributionSetType> byKey(final String key) { public static Specification<JpaDistributionSetType> byKey(final String key) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<String> get(DistributionSetType_.key), key); return (targetRoot, query, cb) -> cb.equal(targetRoot.<String> get(JpaDistributionSetType_.key), key);
} }
} }

View File

@@ -6,13 +6,14 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.specifications; package org.eclipse.hawkbit.repository.jpa.specifications;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule_;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.SoftwareModule_;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
/** /**
@@ -33,10 +34,10 @@ public final class SoftwareModuleSpecification {
* to search for * to search for
* @return the {@link SoftwareModule} {@link Specification} * @return the {@link SoftwareModule} {@link Specification}
*/ */
public static Specification<SoftwareModule> byId(final Long moduleId) { public static Specification<JpaSoftwareModule> byId(final Long moduleId) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final Predicate predicate = cb.equal(targetRoot.<Long> get(SoftwareModule_.id), moduleId); final Predicate predicate = cb.equal(targetRoot.<Long> get(JpaSoftwareModule_.id), moduleId);
targetRoot.fetch(SoftwareModule_.type); targetRoot.fetch(JpaSoftwareModule_.type);
return predicate; return predicate;
}; };
} }
@@ -47,8 +48,8 @@ public final class SoftwareModuleSpecification {
* *
* @return the {@link SoftwareModule} {@link Specification} * @return the {@link SoftwareModule} {@link Specification}
*/ */
public static Specification<SoftwareModule> isDeletedFalse() { public static Specification<JpaSoftwareModule> isDeletedFalse() {
return (swRoot, query, cb) -> cb.equal(swRoot.<Boolean> get(SoftwareModule_.deleted), Boolean.FALSE); return (swRoot, query, cb) -> cb.equal(swRoot.<Boolean> get(JpaSoftwareModule_.deleted), Boolean.FALSE);
} }
/** /**
@@ -59,10 +60,10 @@ public final class SoftwareModuleSpecification {
* to be filtered on * to be filtered on
* @return the {@link SoftwareModule} {@link Specification} * @return the {@link SoftwareModule} {@link Specification}
*/ */
public static Specification<SoftwareModule> likeNameOrVersion(final String subString) { public static Specification<JpaSoftwareModule> likeNameOrVersion(final String subString) {
return (targetRoot, query, cb) -> cb.or( return (targetRoot, query, cb) -> cb.or(
cb.like(cb.lower(targetRoot.<String> get(SoftwareModule_.name)), subString.toLowerCase()), cb.like(cb.lower(targetRoot.<String> get(JpaSoftwareModule_.name)), subString.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(SoftwareModule_.version)), subString.toLowerCase())); cb.like(cb.lower(targetRoot.<String> get(JpaSoftwareModule_.version)), subString.toLowerCase()));
} }
/** /**
@@ -73,8 +74,9 @@ public final class SoftwareModuleSpecification {
* to be filtered on * to be filtered on
* @return the {@link SoftwareModule} {@link Specification} * @return the {@link SoftwareModule} {@link Specification}
*/ */
public static Specification<SoftwareModule> equalType(final SoftwareModuleType type) { public static Specification<JpaSoftwareModule> equalType(final JpaSoftwareModuleType type) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<SoftwareModuleType> get(SoftwareModule_.type), type); return (targetRoot, query, cb) -> cb.equal(targetRoot.<JpaSoftwareModuleType> get(JpaSoftwareModule_.type),
type);
} }
} }

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.specifications; package org.eclipse.hawkbit.repository.jpa.specifications;
import java.util.List; import java.util.List;

View File

@@ -6,10 +6,11 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.specifications; package org.eclipse.hawkbit.repository.jpa.specifications;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery_;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery_;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
/** /**
@@ -22,10 +23,10 @@ public class TargetFilterQuerySpecification {
// utility class // utility class
} }
public static Specification<TargetFilterQuery> likeName(final String searchText) { public static Specification<JpaTargetFilterQuery> likeName(final String searchText) {
return (targetFilterQueryRoot, query, cb) -> { return (targetFilterQueryRoot, query, cb) -> {
final String searchTextToLower = searchText.toLowerCase(); final String searchTextToLower = searchText.toLowerCase();
return cb.like(cb.lower(targetFilterQueryRoot.get(TargetFilterQuery_.name)), searchTextToLower); return cb.like(cb.lower(targetFilterQueryRoot.get(JpaTargetFilterQuery_.name)), searchTextToLower);
}; };
} }
} }

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
package org.eclipse.hawkbit.repository.specifications; package org.eclipse.hawkbit.repository.jpa.specifications;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -20,15 +20,19 @@ import javax.persistence.criteria.Root;
import javax.persistence.criteria.SetJoin; import javax.persistence.criteria.SetJoin;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag_;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSet_;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetInfo_;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetTag_;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.Target_;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
/** /**
@@ -50,10 +54,11 @@ public final class TargetSpecifications {
* *
* @return the {@link Target} {@link Specification} * @return the {@link Target} {@link Specification}
*/ */
public static Specification<Target> byControllerIdWithStatusAndTagsInJoin(final Collection<String> controllerIDs) { public static Specification<JpaTarget> byControllerIdWithStatusAndTagsInJoin(
final Collection<String> controllerIDs) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final Predicate predicate = targetRoot.get(Target_.controllerId).in(controllerIDs); final Predicate predicate = targetRoot.get(JpaTarget_.controllerId).in(controllerIDs);
targetRoot.fetch(Target_.tags, JoinType.LEFT); targetRoot.fetch(JpaTarget_.tags, JoinType.LEFT);
query.distinct(true); query.distinct(true);
return predicate; return predicate;
}; };
@@ -68,12 +73,12 @@ public final class TargetSpecifications {
* *
* @return the {@link Target} {@link Specification} * @return the {@link Target} {@link Specification}
*/ */
public static Specification<Target> byControllerIdWithStatusAndAssignedInJoin( public static Specification<JpaTarget> byControllerIdWithStatusAndAssignedInJoin(
final Collection<String> controllerIDs) { final Collection<String> controllerIDs) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final Predicate predicate = targetRoot.get(Target_.controllerId).in(controllerIDs); final Predicate predicate = targetRoot.get(JpaTarget_.controllerId).in(controllerIDs);
targetRoot.fetch(Target_.assignedDistributionSet); targetRoot.fetch(JpaTarget_.assignedDistributionSet);
return predicate; return predicate;
}; };
} }
@@ -89,19 +94,19 @@ public final class TargetSpecifications {
* join it. * join it.
* @return the {@link Target} {@link Specification} * @return the {@link Target} {@link Specification}
*/ */
public static Specification<Target> hasTargetUpdateStatus(final Collection<TargetUpdateStatus> updateStatus, public static Specification<JpaTarget> hasTargetUpdateStatus(final Collection<TargetUpdateStatus> updateStatus,
final boolean fetch) { final boolean fetch) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
if (!query.getResultType().isAssignableFrom(Long.class)) { if (!query.getResultType().isAssignableFrom(Long.class)) {
if (fetch) { if (fetch) {
targetRoot.fetch(Target_.targetInfo); targetRoot.fetch(JpaTarget_.targetInfo);
} else { } else {
targetRoot.join(Target_.targetInfo); targetRoot.join(JpaTarget_.targetInfo);
} }
return targetRoot.get(Target_.targetInfo).get(TargetInfo_.updateStatus).in(updateStatus); return targetRoot.get(JpaTarget_.targetInfo).get(JpaTargetInfo_.updateStatus).in(updateStatus);
} }
final Join<Target, TargetInfo> targetInfoJoin = targetRoot.join(Target_.targetInfo); final Join<JpaTarget, JpaTargetInfo> targetInfoJoin = targetRoot.join(JpaTarget_.targetInfo);
return targetInfoJoin.get(TargetInfo_.updateStatus).in(updateStatus); return targetInfoJoin.get(JpaTargetInfo_.updateStatus).in(updateStatus);
}; };
} }
@@ -113,11 +118,11 @@ public final class TargetSpecifications {
* to be filtered on * to be filtered on
* @return the {@link Target} {@link Specification} * @return the {@link Target} {@link Specification}
*/ */
public static Specification<Target> likeNameOrDescriptionOrIp(final String searchText) { public static Specification<JpaTarget> likeNameOrDescriptionOrIp(final String searchText) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final String searchTextToLower = searchText.toLowerCase(); final String searchTextToLower = searchText.toLowerCase();
return cb.or(cb.like(cb.lower(targetRoot.get(Target_.name)), searchTextToLower), return cb.or(cb.like(cb.lower(targetRoot.get(JpaTarget_.name)), searchTextToLower),
cb.like(cb.lower(targetRoot.get(Target_.description)), searchTextToLower)); cb.like(cb.lower(targetRoot.get(JpaTarget_.description)), searchTextToLower));
}; };
} }
@@ -129,14 +134,14 @@ public final class TargetSpecifications {
* to be filtered on * to be filtered on
* @return the {@link Target} {@link Specification} * @return the {@link Target} {@link Specification}
*/ */
public static Specification<Target> hasInstalledOrAssignedDistributionSet(@NotNull final Long distributionId) { public static Specification<JpaTarget> hasInstalledOrAssignedDistributionSet(@NotNull final Long distributionId) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final Join<Target, TargetInfo> targetInfoJoin = targetRoot.join(Target_.targetInfo); final Join<JpaTarget, JpaTargetInfo> targetInfoJoin = targetRoot.join(JpaTarget_.targetInfo);
return cb.or( return cb.or(
cb.equal(targetInfoJoin.get(TargetInfo_.installedDistributionSet).get(DistributionSet_.id), cb.equal(targetInfoJoin.get(JpaTargetInfo_.installedDistributionSet).get(JpaDistributionSet_.id),
distributionId), distributionId),
cb.equal(targetRoot.<DistributionSet> get(Target_.assignedDistributionSet).get(DistributionSet_.id), cb.equal(targetRoot.<JpaDistributionSet> get(JpaTarget_.assignedDistributionSet)
distributionId)); .get(JpaDistributionSet_.id), distributionId));
}; };
} }
@@ -150,13 +155,12 @@ public final class TargetSpecifications {
* set that is not yet assigned * set that is not yet assigned
* @return the {@link Target} {@link Specification} * @return the {@link Target} {@link Specification}
*/ */
public static Specification<Target> hasControllerIdAndAssignedDistributionSetIdNot(final List<String> tIDs, public static Specification<JpaTarget> hasControllerIdAndAssignedDistributionSetIdNot(final List<String> tIDs,
@NotNull final Long distributionId) { @NotNull final Long distributionId) {
return (targetRoot, query, cb) -> cb return (targetRoot, query, cb) -> cb.and(targetRoot.get(JpaTarget_.controllerId).in(tIDs),
.and(targetRoot.get(Target_.controllerId).in(tIDs), cb.or(cb.notEqual(targetRoot.<JpaDistributionSet> get(JpaTarget_.assignedDistributionSet)
cb.or(cb.notEqual(targetRoot.<DistributionSet> get(Target_.assignedDistributionSet) .get(JpaDistributionSet_.id), distributionId),
.get(DistributionSet_.id), distributionId), cb.isNull(targetRoot.<JpaDistributionSet> get(JpaTarget_.assignedDistributionSet))));
cb.isNull(targetRoot.<DistributionSet> get(Target_.assignedDistributionSet))));
} }
/** /**
@@ -169,7 +173,7 @@ public final class TargetSpecifications {
* flag to get targets with no tag assigned * flag to get targets with no tag assigned
* @return the {@link Target} {@link Specification} * @return the {@link Target} {@link Specification}
*/ */
public static Specification<Target> hasTags(final String[] tagNames, final Boolean selectTargetWithNoTag) { public static Specification<JpaTarget> hasTags(final String[] tagNames, final Boolean selectTargetWithNoTag) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final Predicate predicate = getPredicate(targetRoot, cb, selectTargetWithNoTag, tagNames); final Predicate predicate = getPredicate(targetRoot, cb, selectTargetWithNoTag, tagNames);
query.distinct(true); query.distinct(true);
@@ -177,10 +181,10 @@ public final class TargetSpecifications {
}; };
} }
private static Predicate getPredicate(final Root<Target> targetRoot, final CriteriaBuilder cb, private static Predicate getPredicate(final Root<JpaTarget> targetRoot, final CriteriaBuilder cb,
final Boolean selectTargetWithNoTag, final String[] tagNames) { final Boolean selectTargetWithNoTag, final String[] tagNames) {
final SetJoin<Target, TargetTag> tags = targetRoot.join(Target_.tags, JoinType.LEFT); final SetJoin<JpaTarget, JpaTargetTag> tags = targetRoot.join(JpaTarget_.tags, JoinType.LEFT);
final Path<String> exp = tags.get(TargetTag_.name); final Path<String> exp = tags.get(JpaTargetTag_.name);
if (selectTargetWithNoTag) { if (selectTargetWithNoTag) {
if (tagNames != null) { if (tagNames != null) {
return cb.or(exp.isNull(), exp.in(tagNames)); return cb.or(exp.isNull(), exp.in(tagNames));
@@ -200,9 +204,9 @@ public final class TargetSpecifications {
* the ID of the distribution set which must be assigned * the ID of the distribution set which must be assigned
* @return the {@link Target} {@link Specification} * @return the {@link Target} {@link Specification}
*/ */
public static Specification<Target> hasAssignedDistributionSet(final Long distributionSetId) { public static Specification<JpaTarget> hasAssignedDistributionSet(final Long distributionSetId) {
return (targetRoot, query, cb) -> cb.equal( return (targetRoot, query, cb) -> cb.equal(
targetRoot.<DistributionSet> get(Target_.assignedDistributionSet).get(DistributionSet_.id), targetRoot.<JpaDistributionSet> get(JpaTarget_.assignedDistributionSet).get(JpaDistributionSet_.id),
distributionSetId); distributionSetId);
} }
@@ -214,10 +218,10 @@ public final class TargetSpecifications {
* the ID of the distribution set which must be assigned * the ID of the distribution set which must be assigned
* @return the {@link Target} {@link Specification} * @return the {@link Target} {@link Specification}
*/ */
public static Specification<Target> hasInstalledDistributionSet(final Long distributionSetId) { public static Specification<JpaTarget> hasInstalledDistributionSet(final Long distributionSetId) {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final Join<Target, TargetInfo> targetInfoJoin = targetRoot.join(Target_.targetInfo); final Join<JpaTarget, JpaTargetInfo> targetInfoJoin = targetRoot.join(JpaTarget_.targetInfo);
return cb.equal(targetInfoJoin.get(TargetInfo_.installedDistributionSet).get(DistributionSet_.id), return cb.equal(targetInfoJoin.get(JpaTargetInfo_.installedDistributionSet).get(JpaDistributionSet_.id),
distributionSetId); distributionSetId);
}; };
} }

View File

@@ -10,193 +10,66 @@ package org.eclipse.hawkbit.repository.model;
import java.util.List; import java.util.List;
import javax.persistence.CascadeType; public interface Action extends TenantAwareBaseEntity {
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedSubgraph;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.eclipse.hawkbit.cache.CacheField;
import org.eclipse.hawkbit.cache.CacheKeys;
import org.eclipse.persistence.annotations.CascadeOnDelete;
/**
* <p>
* Applicable transition changes of the {@link SoftwareModule}s state of a
* {@link Target}, e.g. install, uninstall, update and preparations for the
* transition change, i.e. download.
* </p>
*
* <p>
* Actions are managed by the SP server and applied to the targets by the
* client.
* <p>
*/
@Table(name = "sp_action", indexes = { @Index(name = "sp_idx_action_01", columnList = "tenant,distribution_set"),
@Index(name = "sp_idx_action_02", columnList = "tenant,target,active"),
@Index(name = "sp_idx_action_prim", columnList = "tenant,id") })
@NamedEntityGraphs({ @NamedEntityGraph(name = "Action.ds", attributeNodes = { @NamedAttributeNode("distributionSet") }),
@NamedEntityGraph(name = "Action.all", attributeNodes = { @NamedAttributeNode("distributionSet"),
@NamedAttributeNode(value = "target", subgraph = "target.ds") }, subgraphs = @NamedSubgraph(name = "target.ds", attributeNodes = @NamedAttributeNode("assignedDistributionSet"))) })
@Entity
public class Action extends TenantAwareBaseEntity {
private static final long serialVersionUID = 1L;
/** /**
* indicating that target action has no force time {@link #hasForcedTime()}. * indicating that target action has no force time {@link #hasForcedTime()}.
*/ */
public static final long NO_FORCE_TIME = 0L; public static final long NO_FORCE_TIME = 0L;
/**
* the {@link DistributionSet} which should be installed by this action.
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "distribution_set", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_ds"))
private DistributionSet distributionSet;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "target", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_target"))
private Target target;
@Column(name = "active")
private boolean active;
@Column(name = "action_type", nullable = false)
@Enumerated(EnumType.STRING)
private ActionType actionType;
@Column(name = "forced_time")
private long forcedTime;
@Column(name = "status")
private Status status;
@CascadeOnDelete
@OneToMany(mappedBy = "action", targetEntity = ActionStatus.class, fetch = FetchType.LAZY, cascade = {
CascadeType.REMOVE })
private List<ActionStatus> actionStatus;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rolloutgroup", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rolloutgroup"))
private RolloutGroup rolloutGroup;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rollout", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rollout"))
private Rollout rollout;
/**
* Note: filled only in {@link Status#DOWNLOAD}.
*/
@Transient
@CacheField(key = CacheKeys.DOWNLOAD_PROGRESS_PERCENT)
private int downloadProgressPercent;
/** /**
* @return the distributionSet * @return the distributionSet
*/ */
public DistributionSet getDistributionSet() { DistributionSet getDistributionSet();
return distributionSet;
}
/** /**
* @param distributionSet * @param distributionSet
* the distributionSet to set * the distributionSet to set
*/ */
public void setDistributionSet(final DistributionSet distributionSet) { void setDistributionSet(DistributionSet distributionSet);
this.distributionSet = distributionSet;
}
/** /**
* @return true when action is in state {@link Status#CANCELING} or * @return true when action is in state {@link Status#CANCELING} or
* {@link Status#CANCELED}, false otherwise * {@link Status#CANCELED}, false otherwise
*/ */
public boolean isCancelingOrCanceled() { boolean isCancelingOrCanceled();
return status == Status.CANCELING || status == Status.CANCELED;
}
public void setActive(final boolean active) { void setActive(boolean active);
this.active = active;
}
public Status getStatus() { Status getStatus();
return status;
}
public void setStatus(final Status status) { void setStatus(Status status);
this.status = status;
}
public int getDownloadProgressPercent() { int getDownloadProgressPercent();
return downloadProgressPercent;
}
public void setDownloadProgressPercent(final int downloadProgressPercent) { void setDownloadProgressPercent(int downloadProgressPercent);
this.downloadProgressPercent = downloadProgressPercent;
}
public boolean isActive() { boolean isActive();
return active;
}
public void setActionType(final ActionType actionType) { void setActionType(ActionType actionType);
this.actionType = actionType;
}
/** /**
* @return the actionType * @return the actionType
*/ */
public ActionType getActionType() { ActionType getActionType();
return actionType;
}
public List<ActionStatus> getActionStatus() { List<ActionStatus> getActionStatus();
return actionStatus;
}
public void setTarget(final Target target) { void setTarget(Target target);
this.target = target;
}
public Target getTarget() { Target getTarget();
return target;
}
public long getForcedTime() { long getForcedTime();
return forcedTime;
}
public void setForcedTime(final long forcedTime) { void setForcedTime(long forcedTime);
this.forcedTime = forcedTime;
}
public RolloutGroup getRolloutGroup() { RolloutGroup getRolloutGroup();
return rolloutGroup;
}
public void setRolloutGroup(final RolloutGroup rolloutGroup) { void setRolloutGroup(RolloutGroup rolloutGroup);
this.rolloutGroup = rolloutGroup;
}
public Rollout getRollout() { Rollout getRollout();
return rollout;
}
public void setRollout(final Rollout rollout) { void setRollout(Rollout rollout);
this.rollout = rollout;
}
/** /**
* checks if the {@link #forcedTime} is hit by the given * checks if the {@link #forcedTime} is hit by the given
@@ -210,12 +83,7 @@ public class Action extends TenantAwareBaseEntity {
* {@link ActionType#TIMEFORCED} and the given {@code hitTimeMillis} * {@link ActionType#TIMEFORCED} and the given {@code hitTimeMillis}
* is greater than the {@link #forcedTime} otherwise {@code false} * is greater than the {@link #forcedTime} otherwise {@code false}
*/ */
public boolean isHitAutoForceTime(final long hitTimeMillis) { boolean isHitAutoForceTime(long hitTimeMillis);
if (actionType == ActionType.TIMEFORCED) {
return hitTimeMillis >= forcedTime;
}
return false;
}
/** /**
* @return {@code true} if either the {@link #type} is * @return {@code true} if either the {@link #type} is
@@ -223,28 +91,12 @@ public class Action extends TenantAwareBaseEntity {
* then if the {@link #forcedTime} has been exceeded otherwise * then if the {@link #forcedTime} has been exceeded otherwise
* always {@code false} * always {@code false}
*/ */
public boolean isForce() { boolean isForce();
switch (actionType) {
case FORCED:
return true;
case TIMEFORCED:
return isHitAutoForceTime(System.currentTimeMillis());
default:
return false;
}
}
/** /**
* @return true when action is forced, false otherwise * @return true when action is forced, false otherwise
*/ */
public boolean isForced() { boolean isForced();
return actionType == ActionType.FORCED;
}
@Override
public String toString() {
return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]";
}
/** /**
* Action status as reported by the controller. * Action status as reported by the controller.
@@ -309,4 +161,5 @@ public class Action extends TenantAwareBaseEntity {
public enum ActionType { public enum ActionType {
FORCED, SOFT, TIMEFORCED; FORCED, SOFT, TIMEFORCED;
} }
} }

View File

@@ -8,107 +8,15 @@
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.model;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.Table;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.persistence.annotations.CascadeOnDelete;
import com.google.common.base.Splitter; public interface ActionStatus extends TenantAwareBaseEntity {
/** Long getOccurredAt();
* Entity to store the status for a specific action.
*/
@Table(name = "sp_action_status", indexes = { @Index(name = "sp_idx_action_status_01", columnList = "tenant,action"),
@Index(name = "sp_idx_action_status_02", columnList = "tenant,action,status"),
@Index(name = "sp_idx_action_status_prim", columnList = "tenant,id") })
@NamedEntityGraph(name = "ActionStatus.withMessages", attributeNodes = { @NamedAttributeNode("messages") })
@Entity
public class ActionStatus extends TenantAwareBaseEntity {
private static final long serialVersionUID = 1L;
@Column(name = "target_occurred_at") void setOccurredAt(Long occurredAt);
private Long occurredAt;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "action", nullable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_act_stat_action"))
private Action action;
@Column(name = "status")
private Status status;
@CascadeOnDelete
@ElementCollection(fetch = FetchType.LAZY, targetClass = String.class)
@CollectionTable(name = "sp_action_status_messages", joinColumns = @JoinColumn(name = "action_status_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_stat_msg_act_stat")), indexes = {
@Index(name = "sp_idx_action_status_msgs_01", columnList = "action_status_id") })
@Column(name = "detail_message", length = 512)
private final List<String> messages = new ArrayList<>();
/**
* Creates a new {@link ActionStatus} object.
*
* @param action
* the action for this action status
* @param status
* the status for this action status
* @param occurredAt
* the occurred timestamp
*/
public ActionStatus(final Action action, final Status status, final Long occurredAt) {
this.action = action;
this.status = status;
this.occurredAt = occurredAt;
}
/**
* Creates a new {@link ActionStatus} object.
*
* @param action
* the action for this action status
* @param status
* the status for this action status
* @param occurredAt
* the occurred timestamp
* @param messages
* the messages which should be added to this action status
*/
public ActionStatus(final Action action, final Status status, final Long occurredAt, final String... messages) {
this.action = action;
this.status = status;
this.occurredAt = occurredAt;
for (final String msg : messages) {
addMessage(msg);
}
}
/**
* JPA default constructor.
*/
public ActionStatus() {
// JPA default constructor.
}
public Long getOccurredAt() {
return occurredAt;
}
public void setOccurredAt(final Long occurredAt) {
this.occurredAt = occurredAt;
}
/** /**
* Adds message including splitting in case it exceeds 512 length. * Adds message including splitting in case it exceeds 512 length.
@@ -116,28 +24,16 @@ public class ActionStatus extends TenantAwareBaseEntity {
* @param message * @param message
* to add * to add
*/ */
public final void addMessage(final String message) { void addMessage(String message);
Splitter.fixedLength(512).split(message).forEach(messages::add);
}
public List<String> getMessages() { List<String> getMessages();
return messages;
}
public Action getAction() { Action getAction();
return action;
}
public void setAction(final Action action) { void setAction(Action action);
this.action = action;
}
public Status getStatus() { Status getStatus();
return status;
}
public void setStatus(final Status status) { void setStatus(Status status);
this.status = status;
}
} }

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.model;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
@@ -16,6 +17,7 @@ import org.eclipse.hawkbit.repository.model.Action.Status;
* action's {@link ActionStatus}. * action's {@link ActionStatus}.
* *
*/ */
// TODO: create interface
public class ActionWithStatusCount { public class ActionWithStatusCount {
private final Long actionStatusCount; private final Long actionStatusCount;
private final Long actionId; private final Long actionId;
@@ -28,7 +30,7 @@ public class ActionWithStatusCount {
private final Long dsId; private final Long dsId;
private final String dsName; private final String dsName;
private final String dsVersion; private final String dsVersion;
private final Action action; private final JpaAction action;
private final String rolloutName; private final String rolloutName;
/** /**
@@ -78,7 +80,7 @@ public class ActionWithStatusCount {
this.actionStatusCount = actionStatusCount; this.actionStatusCount = actionStatusCount;
this.rolloutName = rolloutName; this.rolloutName = rolloutName;
action = new Action(); action = new JpaAction();
action.setActionType(actionType); action.setActionType(actionType);
action.setActive(actionActive); action.setActive(actionActive);
action.setForcedTime(actionForceTime); action.setForcedTime(actionForceTime);

View File

@@ -8,49 +8,16 @@
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.model;
import javax.persistence.Column; public interface Artifact extends TenantAwareBaseEntity {
import javax.persistence.MappedSuperclass;
/** SoftwareModule getSoftwareModule();
* Tenant specific locally stored artifact representation that is used by
* {@link SoftwareModule}.
*/
@MappedSuperclass
public abstract class Artifact extends TenantAwareBaseEntity {
private static final long serialVersionUID = 1L;
@Column(name = "sha1_hash", length = 40, nullable = true) void setSoftwareModule(SoftwareModule softwareModule);
private String sha1Hash;
@Column(name = "md5_hash", length = 32, nullable = true) String getMd5Hash();
private String md5Hash;
@Column(name = "file_size") String getSha1Hash();
private Long size;
public abstract SoftwareModule getSoftwareModule(); Long getSize();
public String getMd5Hash() {
return md5Hash;
}
public String getSha1Hash() {
return sha1Hash;
}
public void setMd5Hash(final String md5Hash) {
this.md5Hash = md5Hash;
}
public void setSha1Hash(final String sha1Hash) {
this.sha1Hash = sha1Hash;
}
public Long getSize() {
return size;
}
public void setSize(final Long size) {
this.size = size;
}
} }

View File

@@ -10,171 +10,18 @@ package org.eclipse.hawkbit.repository.model;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import org.eclipse.hawkbit.eventbus.CacheFieldEntityListener;
import org.eclipse.hawkbit.eventbus.EntityPropertyChangeListener;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.hateoas.Identifiable; import org.springframework.hateoas.Identifiable;
/** public interface BaseEntity extends Serializable, Identifiable<Long> {
* Holder of the base attributes common to all entities.
*
*/
@MappedSuperclass
@Access(AccessType.FIELD)
@EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class })
public abstract class BaseEntity implements Serializable, Identifiable<Long> {
private static final long serialVersionUID = 1L;
@Id Long getCreatedAt();
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
private String createdBy; String getCreatedBy();
private String lastModifiedBy;
private Long createdAt;
private Long lastModifiedAt;
@Version Long getLastModifiedAt();
@Column(name = "optlock_revision")
private long optLockRevision;
/** String getLastModifiedBy();
* Default constructor needed for JPA entities.
*/
public BaseEntity() {
// Default constructor needed for JPA entities.
}
@Access(AccessType.PROPERTY) long getOptLockRevision();
@Column(name = "created_at", insertable = true, updatable = false)
public Long getCreatedAt() {
return createdAt;
}
@Access(AccessType.PROPERTY)
@Column(name = "created_by", insertable = true, updatable = false, length = 40)
public String getCreatedBy() {
return createdBy;
}
@Access(AccessType.PROPERTY)
@Column(name = "last_modified_at", insertable = false, updatable = true)
public Long getLastModifiedAt() {
return lastModifiedAt;
}
@Access(AccessType.PROPERTY)
@Column(name = "last_modified_by", insertable = false, updatable = true, length = 40)
public String getLastModifiedBy() {
return lastModifiedBy;
}
@CreatedBy
public void setCreatedBy(final String createdBy) {
this.createdBy = createdBy;
}
@LastModifiedBy
public void setLastModifiedBy(final String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
@CreatedDate
public void setCreatedAt(final Long createdAt) {
this.createdAt = createdAt;
}
@LastModifiedDate
public void setLastModifiedAt(final Long lastModifiedAt) {
this.lastModifiedAt = lastModifiedAt;
}
public long getOptLockRevision() {
return optLockRevision;
}
// for test purposes only
void setOptLockRevision(final long optLockRevision) {
this.optLockRevision = optLockRevision;
}
@Override
public Long getId() {
return id;
}
@Override
public String toString() {
return "BaseEntity [id=" + id + "]";
}
public void setId(final Long id) {
this.id = id;
}
/**
* Defined equals/hashcode strategy for the repository in general is that an
* entity is equal if it has the same {@link #getId()} and
* {@link #getOptLockRevision()} and class.
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() { // NOSONAR - as this is generated code
final int prime = 31;
int result = 1;
result = prime * result + (id == null ? 0 : id.hashCode());
result = prime * result + (int) (optLockRevision ^ optLockRevision >>> 32);
result = prime * result + this.getClass().getName().hashCode();
return result;
}
/**
* Defined equals/hashcode strategy for the repository in general is that an
* entity is equal if it has the same {@link #getId()} and
* {@link #getOptLockRevision()} and class.
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) { // NOSONAR - as this is generated
// code
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(this.getClass().isInstance(obj))) {
return false;
}
final BaseEntity other = (BaseEntity) obj;
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
if (optLockRevision != other.optLockRevision) {
return false;
}
return true;
}
} }

View File

@@ -8,198 +8,47 @@
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import javax.persistence.CascadeType; public interface DistributionSet extends NamedVersionedEntity {
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException; Set<DistributionSetTag> getTags();
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
import org.eclipse.persistence.annotations.CascadeOnDelete;
/** boolean isDeleted();
* <p>
* The {@link DistributionSet} is defined in the SP repository and contains at
* least an OS and an Agent Hub.
* </p>
*
* <p>
* A {@link Target} has exactly one target {@link DistributionSet} assigned.
* </p>
*
*/
@Entity
@Table(name = "sp_distribution_set", uniqueConstraints = {
@UniqueConstraint(columnNames = { "name", "version", "tenant" }, name = "uk_distrib_set") }, indexes = {
@Index(name = "sp_idx_distribution_set_01", columnList = "tenant,deleted,name,complete"),
@Index(name = "sp_idx_distribution_set_02", columnList = "tenant,required_migration_step"),
@Index(name = "sp_idx_distribution_set_prim", columnList = "tenant,id") })
@NamedEntityGraph(name = "DistributionSet.detail", attributeNodes = { @NamedAttributeNode("modules"),
@NamedAttributeNode("tags"), @NamedAttributeNode("type") })
public class DistributionSet extends NamedVersionedEntity {
private static final long serialVersionUID = 1L;
@Column(name = "required_migration_step")
private boolean requiredMigrationStep = false;
@ManyToMany(targetEntity = SoftwareModule.class, fetch = FetchType.LAZY)
@JoinTable(name = "sp_ds_module", joinColumns = {
@JoinColumn(name = "ds_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_ds")) }, inverseJoinColumns = {
@JoinColumn(name = "module_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_module_module")) })
private final Set<SoftwareModule> modules = new HashSet<>();
@ManyToMany(targetEntity = DistributionSetTag.class)
@JoinTable(name = "sp_ds_dstag", joinColumns = {
@JoinColumn(name = "ds", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_ds")) }, inverseJoinColumns = {
@JoinColumn(name = "TAG", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstag_tag")) })
private Set<DistributionSetTag> tags = new HashSet<>();
@Column(name = "deleted")
private boolean deleted = false;
@OneToMany(mappedBy = "assignedDistributionSet", targetEntity = Target.class, fetch = FetchType.LAZY)
private List<Target> assignedToTargets;
@OneToMany(mappedBy = "installedDistributionSet", targetEntity = TargetInfo.class, fetch = FetchType.LAZY)
private List<TargetInfo> installedAtTargets;
@OneToMany(mappedBy = "distributionSet", targetEntity = Action.class, fetch = FetchType.LAZY)
private List<Action> actions;
@CascadeOnDelete
@OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.REMOVE })
@JoinColumn(name = "ds_id", insertable = false, updatable = false)
private final List<DistributionSetMetadata> metadata = new ArrayList<>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ds_id", nullable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstype_ds"))
private DistributionSetType type;
@Column(name = "complete")
private boolean complete = false;
/**
* Default constructor.
*/
public DistributionSet() {
super();
}
/**
* Parameterized constructor.
*
* @param name
* of the {@link DistributionSet}
* @param version
* of the {@link DistributionSet}
* @param description
* of the {@link DistributionSet}
* @param type
* of the {@link DistributionSet}
* @param moduleList
* {@link SoftwareModule}s of the {@link DistributionSet}
*/
public DistributionSet(final String name, final String version, final String description,
final DistributionSetType type, final Iterable<SoftwareModule> moduleList) {
super(name, version, description);
this.type = type;
if (moduleList != null) {
moduleList.forEach(this::addModule);
}
if (this.type != null) {
complete = this.type.checkComplete(this);
}
}
public Set<DistributionSetTag> getTags() {
return tags;
}
public boolean isDeleted() {
return deleted;
}
/** /**
* @return immutable list of meta data elements. * @return immutable list of meta data elements.
*/ */
public List<DistributionSetMetadata> getMetadata() { List<DistributionSetMetadata> getMetadata();
return Collections.unmodifiableList(metadata);
}
public List<Action> getActions() { List<Action> getActions();
return actions;
}
public boolean isRequiredMigrationStep() { boolean isRequiredMigrationStep();
return requiredMigrationStep;
}
public DistributionSet setDeleted(final boolean deleted) { DistributionSet setDeleted(boolean deleted);
this.deleted = deleted;
return this;
}
public DistributionSet setRequiredMigrationStep(final boolean isRequiredMigrationStep) { DistributionSet setRequiredMigrationStep(boolean isRequiredMigrationStep);
requiredMigrationStep = isRequiredMigrationStep;
return this;
}
public DistributionSet setTags(final Set<DistributionSetTag> tags) { DistributionSet setTags(Set<DistributionSetTag> tags);
this.tags = tags;
return this;
}
/** /**
* @return the assignedTargets * @return the assignedTargets
*/ */
public List<Target> getAssignedTargets() { List<Target> getAssignedTargets();
return assignedToTargets;
}
/** /**
* @return the installedTargets * @return the installedTargets
*/ */
public List<TargetInfo> getInstalledTargets() { List<TargetInfo> getInstalledTargets();
return installedAtTargets;
}
@Override
public String toString() {
return "DistributionSet [getName()=" + getName() + ", getOptLockRevision()=" + getOptLockRevision()
+ ", getId()=" + getId() + "]";
}
/** /**
* *
* @return unmodifiableSet of {@link SoftwareModule}. * @return unmodifiableSet of {@link SoftwareModule}.
*/ */
public Set<SoftwareModule> getModules() { Set<SoftwareModule> getModules();
return Collections.unmodifiableSet(modules);
}
public DistributionSetIdName getDistributionSetIdName() { DistributionSetIdName getDistributionSetIdName();
return new DistributionSetIdName(getId(), getName(), getVersion());
}
/** /**
* @param softwareModule * @param softwareModule
@@ -207,41 +56,7 @@ public class DistributionSet extends NamedVersionedEntity {
* if it already existed in the set * if it already existed in the set
* *
*/ */
public boolean addModule(final SoftwareModule softwareModule) { boolean addModule(SoftwareModule softwareModule);
// we cannot allow that modules are added without a type defined
if (type == null) {
throw new DistributionSetTypeUndefinedException();
}
// check if it is allowed to such a module to this DS type
if (!type.containsModuleType(softwareModule.getType())) {
throw new UnsupportedSoftwareModuleForThisDistributionSetException();
}
final Optional<SoftwareModule> found = modules.stream()
.filter(module -> module.getId().equals(softwareModule.getId())).findFirst();
if (found.isPresent()) {
return false;
}
final long allready = modules.stream()
.filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).count();
if (allready >= softwareModule.getType().getMaxAssignments()) {
final Optional<SoftwareModule> sameKey = modules.stream()
.filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())).findFirst();
modules.remove(sameKey.get());
}
if (modules.add(softwareModule)) {
complete = type.checkComplete(this);
return true;
}
return false;
}
/** /**
* Removed given {@link SoftwareModule} from this DS instance. * Removed given {@link SoftwareModule} from this DS instance.
@@ -250,19 +65,7 @@ public class DistributionSet extends NamedVersionedEntity {
* to remove * to remove
* @return <code>true</code> if element was found and removed * @return <code>true</code> if element was found and removed
*/ */
public boolean removeModule(final SoftwareModule softwareModule) { boolean removeModule(SoftwareModule softwareModule);
final Optional<SoftwareModule> found = modules.stream()
.filter(module -> module.getId().equals(softwareModule.getId())).findFirst();
if (found.isPresent()) {
modules.remove(found.get());
complete = type.checkComplete(this);
return true;
}
return false;
}
/** /**
* Searches through modules for the given type. * Searches through modules for the given type.
@@ -272,26 +75,12 @@ public class DistributionSet extends NamedVersionedEntity {
* @return SoftwareModule of given type or <code>null</code> if not in the * @return SoftwareModule of given type or <code>null</code> if not in the
* list. * list.
*/ */
public SoftwareModule findFirstModuleByType(final SoftwareModuleType type) { SoftwareModule findFirstModuleByType(SoftwareModuleType type);
final Optional<SoftwareModule> result = modules.stream().filter(module -> module.getType().equals(type))
.findFirst();
if (result.isPresent()) { DistributionSetType getType();
return result.get();
}
return null; void setType(DistributionSetType type);
}
public DistributionSetType getType() { boolean isComplete();
return type;
}
public void setType(final DistributionSetType type) {
this.type = type;
}
public boolean isComplete() {
return complete;
}
} }

View File

@@ -8,73 +8,10 @@
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.model;
import javax.persistence.ConstraintMode; public interface DistributionSetMetadata extends MetaData {
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/** void setDistributionSet(DistributionSet distributionSet);
* Meta data for {@link DistributionSet}.
*
*/
@IdClass(DsMetadataCompositeKey.class)
@Entity
@Table(name = "sp_ds_metadata")
public class DistributionSetMetadata extends MetaData {
private static final long serialVersionUID = 1L;
@Id DistributionSet getDistributionSet();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ds_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_metadata_ds"))
private DistributionSet distributionSet;
public DistributionSetMetadata() {
// default public constructor for JPA
}
public DistributionSetMetadata(final String key, final DistributionSet distributionSet, final String value) {
super(key, value);
this.distributionSet = distributionSet;
}
public DsMetadataCompositeKey getId() {
return new DsMetadataCompositeKey(distributionSet, getKey());
}
public void setDistributionSet(final DistributionSet distributionSet) {
this.distributionSet = distributionSet;
}
public DistributionSet getDistributionSet() {
return distributionSet;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((distributionSet == null) ? 0 : distributionSet.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (!super.equals(obj)) {
return false;
}
final DistributionSetMetadata other = (DistributionSetMetadata) obj;
if (distributionSet == null) {
if (other.distributionSet != null) {
return false;
}
} else if (!distributionSet.equals(other.distributionSet)) {
return false;
}
return true;
}
} }

View File

@@ -10,77 +10,8 @@ package org.eclipse.hawkbit.repository.model;
import java.util.List; import java.util.List;
import javax.persistence.Entity; public interface DistributionSetTag extends Tag {
import javax.persistence.FetchType;
import javax.persistence.Index;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
/** List<DistributionSet> getAssignedToDistributionSet();
* A {@link DistributionSetTag} is used to describe DistributionSet attributes
* and use them also for filtering the DistributionSet list.
*
*/
@Entity
@Table(name = "sp_distributionset_tag", indexes = {
@Index(name = "sp_idx_distribution_set_tag_prim", columnList = "tenant,id") }, uniqueConstraints = @UniqueConstraint(columnNames = {
"name", "tenant" }, name = "uk_ds_tag"))
public class DistributionSetTag extends Tag {
private static final long serialVersionUID = 1L;
@ManyToMany(mappedBy = "tags", targetEntity = DistributionSet.class, fetch = FetchType.LAZY)
private List<DistributionSet> assignedToDistributionSet;
/**
* Public constructor.
*
* @param name
* of the {@link DistributionSetTag}
**/
public DistributionSetTag(final String name) {
super(name, null, null);
}
/**
* Public constructor.
*
* @param name
* of the {@link DistributionSetTag}
* @param description
* of the {@link DistributionSetTag}
* @param colour
* of tag in UI
*/
public DistributionSetTag(final String name, final String description, final String colour) {
super(name, description, colour);
}
DistributionSetTag() {
super();
}
public List<DistributionSet> getAssignedToDistributionSet() {
return assignedToDistributionSet;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + this.getClass().getName().hashCode();
return result;
}
@Override
public boolean equals(final Object obj) { // NOSONAR - as this is generated
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof DistributionSetTag)) {
return false;
}
return true;
}
} }

View File

@@ -8,109 +8,26 @@
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.model;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.CascadeType; import org.eclipse.hawkbit.repository.jpa.model.DistributionSetTypeElement;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
/** public interface DistributionSetType extends NamedEntity {
* A distribution set type defines which software module types can or have to be
* {@link DistributionSet}.
*
*/
@Entity
@Table(name = "sp_distribution_set_type", indexes = {
@Index(name = "sp_idx_distribution_set_type_01", columnList = "tenant,deleted"),
@Index(name = "sp_idx_distribution_set_type_prim", columnList = "tenant,id") }, uniqueConstraints = {
@UniqueConstraint(columnNames = { "name", "tenant" }, name = "uk_dst_name"),
@UniqueConstraint(columnNames = { "type_key", "tenant" }, name = "uk_dst_key") })
public class DistributionSetType extends NamedEntity {
private static final long serialVersionUID = 1L;
@OneToMany(targetEntity = DistributionSetTypeElement.class, cascade = {
CascadeType.ALL }, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "distribution_set_type", insertable = false, updatable = false)
private final Set<DistributionSetTypeElement> elements = new HashSet<>();
@Column(name = "type_key", nullable = false, length = 64)
private String key;
@Column(name = "colour", nullable = true, length = 16)
private String colour;
@Column(name = "deleted")
private boolean deleted = false;
public DistributionSetType() {
// default public constructor for JPA
}
/**
* Standard constructor.
*
* @param key
* of the type (unique)
* @param name
* of the type (unique)
* @param description
* of the type
*/
public DistributionSetType(final String key, final String name, final String description) {
this(key, name, description, null);
}
/**
* Constructor.
*
* @param key
* of the type
* @param name
* of the type
* @param description
* of the type
* @param color
* of the type. It will be null by default
*/
public DistributionSetType(final String key, final String name, final String description, final String color) {
super(name, description);
this.key = key;
colour = color;
}
/** /**
* @return the deleted * @return the deleted
*/ */
public boolean isDeleted() { boolean isDeleted();
return deleted;
}
/** /**
* @param deleted * @param deleted
* the deleted to set * the deleted to set
*/ */
public void setDeleted(final boolean deleted) { void setDeleted(boolean deleted);
this.deleted = deleted;
}
public Set<SoftwareModuleType> getMandatoryModuleTypes() { Set<SoftwareModuleType> getMandatoryModuleTypes();
return elements.stream().filter(element -> element.isMandatory()).map(element -> element.getSmType())
.collect(Collectors.toSet());
}
public Set<SoftwareModuleType> getOptionalModuleTypes() { Set<SoftwareModuleType> getOptionalModuleTypes();
return elements.stream().filter(element -> !element.isMandatory()).map(element -> element.getSmType())
.collect(Collectors.toSet());
}
/** /**
* Checks if the given {@link SoftwareModuleType} is in this * Checks if the given {@link SoftwareModuleType} is in this
@@ -120,15 +37,7 @@ public class DistributionSetType extends NamedEntity {
* search for * search for
* @return <code>true</code> if found * @return <code>true</code> if found
*/ */
public boolean containsModuleType(final SoftwareModuleType softwareModuleType) { boolean containsModuleType(SoftwareModuleType softwareModuleType);
for (final DistributionSetTypeElement distributionSetTypeElement : elements) {
if (distributionSetTypeElement.getSmType().equals(softwareModuleType)) {
return true;
}
}
return false;
}
/** /**
* Checks if the given {@link SoftwareModuleType} is in this * Checks if the given {@link SoftwareModuleType} is in this
@@ -139,11 +48,7 @@ public class DistributionSetType extends NamedEntity {
* search for * search for
* @return <code>true</code> if found * @return <code>true</code> if found
*/ */
public boolean containsMandatoryModuleType(final SoftwareModuleType softwareModuleType) { boolean containsMandatoryModuleType(SoftwareModuleType softwareModuleType);
return elements.stream().filter(element -> element.isMandatory())
.filter(element -> element.getSmType().equals(softwareModuleType)).findFirst().isPresent();
}
/** /**
* Checks if the given {@link SoftwareModuleType} is in this * Checks if the given {@link SoftwareModuleType} is in this
@@ -154,11 +59,7 @@ public class DistributionSetType extends NamedEntity {
* search for by {@link SoftwareModuleType#getId()} * search for by {@link SoftwareModuleType#getId()}
* @return <code>true</code> if found * @return <code>true</code> if found
*/ */
public boolean containsMandatoryModuleType(final Long softwareModuleTypeId) { boolean containsMandatoryModuleType(Long softwareModuleTypeId);
return elements.stream().filter(element -> element.isMandatory())
.filter(element -> element.getSmType().getId().equals(softwareModuleTypeId)).findFirst().isPresent();
}
/** /**
* Checks if the given {@link SoftwareModuleType} is in this * Checks if the given {@link SoftwareModuleType} is in this
@@ -169,11 +70,7 @@ public class DistributionSetType extends NamedEntity {
* search for * search for
* @return <code>true</code> if found * @return <code>true</code> if found
*/ */
public boolean containsOptionalModuleType(final SoftwareModuleType softwareModuleType) { boolean containsOptionalModuleType(SoftwareModuleType softwareModuleType);
return elements.stream().filter(element -> !element.isMandatory())
.filter(element -> element.getSmType().equals(softwareModuleType)).findFirst().isPresent();
}
/** /**
* Checks if the given {@link SoftwareModuleType} is in this * Checks if the given {@link SoftwareModuleType} is in this
@@ -184,11 +81,7 @@ public class DistributionSetType extends NamedEntity {
* search by {@link SoftwareModuleType#getId()} * search by {@link SoftwareModuleType#getId()}
* @return <code>true</code> if found * @return <code>true</code> if found
*/ */
public boolean containsOptionalModuleType(final Long softwareModuleTypeId) { boolean containsOptionalModuleType(Long softwareModuleTypeId);
return elements.stream().filter(element -> !element.isMandatory())
.filter(element -> element.getSmType().getId().equals(softwareModuleTypeId)).findFirst().isPresent();
}
/** /**
* Compares the modules of this {@link DistributionSetType} and the given * Compares the modules of this {@link DistributionSetType} and the given
@@ -198,9 +91,7 @@ public class DistributionSetType extends NamedEntity {
* to compare with * to compare with
* @return <code>true</code> if the lists are identical. * @return <code>true</code> if the lists are identical.
*/ */
public boolean areModuleEntriesIdentical(final DistributionSetType dsType) { boolean areModuleEntriesIdentical(DistributionSetType dsType);
return new HashSet<DistributionSetTypeElement>(dsType.elements).equals(elements);
}
/** /**
* Adds {@link SoftwareModuleType} that is optional for the * Adds {@link SoftwareModuleType} that is optional for the
@@ -210,11 +101,7 @@ public class DistributionSetType extends NamedEntity {
* to add * to add
* @return updated instance * @return updated instance
*/ */
public DistributionSetType addOptionalModuleType(final SoftwareModuleType smType) { DistributionSetType addOptionalModuleType(SoftwareModuleType smType);
elements.add(new DistributionSetTypeElement(this, smType, false));
return this;
}
/** /**
* Adds {@link SoftwareModuleType} that is mandatory for the * Adds {@link SoftwareModuleType} that is mandatory for the
@@ -224,11 +111,7 @@ public class DistributionSetType extends NamedEntity {
* to add * to add
* @return updated instance * @return updated instance
*/ */
public DistributionSetType addMandatoryModuleType(final SoftwareModuleType smType) { DistributionSetType addMandatoryModuleType(SoftwareModuleType smType);
elements.add(new DistributionSetTypeElement(this, smType, true));
return this;
}
/** /**
* Removes {@link SoftwareModuleType} from the list. * Removes {@link SoftwareModuleType} from the list.
@@ -237,25 +120,11 @@ public class DistributionSetType extends NamedEntity {
* to remove * to remove
* @return updated instance * @return updated instance
*/ */
public DistributionSetType removeModuleType(final Long smTypeId) { DistributionSetType removeModuleType(Long smTypeId);
// we search by id (standard equals compares also revison)
final Optional<DistributionSetTypeElement> found = elements.stream()
.filter(element -> element.getSmType().getId().equals(smTypeId)).findFirst();
if (found.isPresent()) { String getKey();
elements.remove(found.get());
}
return this; void setKey(String key);
}
public String getKey() {
return key;
}
public void setKey(final String key) {
this.key = key;
}
/** /**
* @param distributionSet * @param distributionSet
@@ -263,26 +132,10 @@ public class DistributionSetType extends NamedEntity {
* @return <code>true</code> if the all mandatory software module types are * @return <code>true</code> if the all mandatory software module types are
* in the system. * in the system.
*/ */
public boolean checkComplete(final DistributionSet distributionSet) { boolean checkComplete(DistributionSet distributionSet);
return distributionSet.getModules().stream().map(module -> module.getType()).collect(Collectors.toList())
.containsAll(getMandatoryModuleTypes());
}
public String getColour() { String getColour();
return colour;
}
public void setColour(final String colour) { void setColour(final String colour);
this.colour = colour;
}
public Set<DistributionSetTypeElement> getElements() {
return elements;
}
@Override
public String toString() {
return "DistributionSetType [key=" + key + ", isDeleted()=" + isDeleted() + ", getId()=" + getId() + "]";
}
} }

View File

@@ -8,125 +8,20 @@
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.model;
import java.net.URL; public interface ExternalArtifact extends Artifact {
import javax.persistence.CascadeType; ExternalArtifactProvider getExternalArtifactProvider();
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
/** String getUrl();
* External artifact representation with all the necessary information to
* generate an artifact {@link URL} at runtime.
*
*/
@Table(name = "sp_external_artifact", indexes = {
@Index(name = "sp_idx_external_artifact_prim", columnList = "id,tenant") })
@Entity
public class ExternalArtifact extends Artifact {
private static final long serialVersionUID = 1L;
@ManyToOne String getUrlSuffix();
@JoinColumn(name = "provider", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_art_to_ext_provider"))
private ExternalArtifactProvider externalArtifactProvider;
@Column(name = "url_suffix", length = 512) void setExternalArtifactProvider(ExternalArtifactProvider externalArtifactProvider);
private String urlSuffix;
// CascadeType.PERSIST as we register ourself at the BSM
@ManyToOne(optional = false, cascade = { CascadeType.PERSIST })
@JoinColumn(name = "software_module", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_external_assigned_sm"))
private SoftwareModule softwareModule;
/**
* Default constructor.
*/
public ExternalArtifact() {
super();
}
/**
* Constructs {@link ExternalArtifact}.
*
* @param externalArtifactProvider
* of the artifact
* @param urlSuffix
* of the artifact
* @param softwareModule
* of the artifact
*/
public ExternalArtifact(@NotNull final ExternalArtifactProvider externalArtifactProvider, final String urlSuffix,
final SoftwareModule softwareModule) {
setSoftwareModule(softwareModule);
this.externalArtifactProvider = externalArtifactProvider;
if (urlSuffix != null) {
this.urlSuffix = urlSuffix;
} else {
this.urlSuffix = externalArtifactProvider.getDefaultSuffix();
}
}
/**
* @return the softwareModule
*/
@Override
public SoftwareModule getSoftwareModule() {
return softwareModule;
}
public final void setSoftwareModule(final SoftwareModule softwareModule) {
this.softwareModule = softwareModule;
this.softwareModule.addArtifact(this);
}
public ExternalArtifactProvider getExternalArtifactProvider() {
return externalArtifactProvider;
}
public String getUrl() {
return new StringBuilder().append(externalArtifactProvider.getBasePath()).append(urlSuffix).toString();
}
public String getUrlSuffix() {
return urlSuffix;
}
public void setExternalArtifactProvider(final ExternalArtifactProvider externalArtifactProvider) {
this.externalArtifactProvider = externalArtifactProvider;
}
/** /**
* @param urlSuffix * @param urlSuffix
* the urlSuffix to set * the urlSuffix to set
*/ */
public void setUrlSuffix(final String urlSuffix) { void setUrlSuffix(String urlSuffix);
this.urlSuffix = urlSuffix;
}
@Override
public int hashCode() { // NOSONAR - as this is generated
final int prime = 31;
int result = super.hashCode();
result = prime * result + this.getClass().getName().hashCode();
return result;
}
@Override
public boolean equals(final Object obj) { // NOSONAR - as this is generated
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof ExternalArtifact)) {
return false;
}
return true;
}
} }

View File

@@ -8,69 +8,14 @@
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.model;
import javax.persistence.Column; public interface ExternalArtifactProvider extends NamedEntity {
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
/** String getBasePath();
* External repositories for artifact storage. The SP server provides URLs for
* the targets to download from these external resources but does not access
* them itself.
*
*/
@Table(name = "sp_external_provider", indexes = {
@Index(name = "sp_idx_external_provider_prim", columnList = "tenant,id") })
@Entity
public class ExternalArtifactProvider extends NamedEntity {
private static final long serialVersionUID = 1L;
@Column(name = "base_url", length = 512, nullable = false) String getDefaultSuffix();
private String basePath;
@Column(name = "default_url_suffix", length = 512, nullable = true) void setBasePath(String basePath);
private String defaultSuffix;
/** void setDefaultSuffix(String defaultSuffix);
* Constructs {@link ExternalArtifactProvider} based on given properties.
*
* @param name
* of the provided
* @param description
* which is optional
* @param baseURL
* of all {@link ExternalArtifact}s of the provider
* @param defaultUrlSuffix
* that is used if {@link ExternalArtifact#getUrlSuffix()} is
* empty.
*/
public ExternalArtifactProvider(final String name, final String description, final String baseURL,
final String defaultUrlSuffix) {
super(name, description);
basePath = baseURL;
defaultSuffix = defaultUrlSuffix;
}
ExternalArtifactProvider() {
super();
defaultSuffix = "";
basePath = "";
}
public String getBasePath() {
return basePath;
}
public String getDefaultSuffix() {
return defaultSuffix;
}
public void setBasePath(final String basePath) {
this.basePath = basePath;
}
public void setDefaultSuffix(final String defaultSuffix) {
this.defaultSuffix = defaultSuffix;
}
} }

View File

@@ -8,106 +8,8 @@
*/ */
package org.eclipse.hawkbit.repository.model; package org.eclipse.hawkbit.repository.model;
import javax.persistence.CascadeType; public interface LocalArtifact extends Artifact {
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import com.mongodb.gridfs.GridFS; String getFilename();
import com.mongodb.gridfs.GridFSFile;
/**
* Tenant specific locally stored artifact representation that is used by
* {@link SoftwareModule} . It contains all information that is provided by the
* user while all SP server generated information related to the artifact (hash,
* length) is stored directly with the binary itself.
*
*
*
*/
@Table(name = "sp_artifact", indexes = { @Index(name = "sp_idx_artifact_01", columnList = "tenant,software_module"),
@Index(name = "sp_idx_artifact_prim", columnList = "tenant,id") })
@Entity
public class LocalArtifact extends Artifact {
private static final long serialVersionUID = 1L;
@NotNull
@Column(name = "gridfs_file_name", length = 40)
private String gridFsFileName;
@NotNull
@Column(name = "provided_file_name", length = 256)
private String filename;
@ManyToOne(optional = false, cascade = { CascadeType.PERSIST })
@JoinColumn(name = "software_module", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_assigned_sm"))
private SoftwareModule softwareModule;
/**
* Default constructor.
*/
public LocalArtifact() {
super();
}
/**
* Constructs artifact.
*
* @param gridFsFileName
* that is the link to the {@link GridFS} entity.
* @param filename
* that is used by {@link GridFSFile} store.
* @param softwareModule
* of this artifact
*/
public LocalArtifact(@NotNull final String gridFsFileName, @NotNull final String filename,
final SoftwareModule softwareModule) {
setSoftwareModule(softwareModule);
this.gridFsFileName = gridFsFileName;
this.filename = filename;
}
@Override
public int hashCode() { // NOSONAR - as this is generated
final int prime = 31;
int result = super.hashCode();
result = prime * result + this.getClass().getName().hashCode();
return result;
}
@Override
public boolean equals(final Object obj) { // NOSONAR - as this is generated
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof LocalArtifact)) {
return false;
}
return true;
}
@Override
public SoftwareModule getSoftwareModule() {
return softwareModule;
}
public final void setSoftwareModule(final SoftwareModule softwareModule) {
this.softwareModule = softwareModule;
this.softwareModule.addArtifact(this);
}
public String getGridFsFileName() {
return gridFsFileName;
}
public String getFilename() {
return filename;
}
} }

Some files were not shown because too many files have changed in this diff Show More