JPA Refactoring (#2107)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2024-11-29 14:07:37 +02:00
committed by GitHub
parent ebcb6a0b29
commit 2a95adc562
29 changed files with 356 additions and 919 deletions

View File

@@ -86,8 +86,7 @@ public final class JpaManagementHelper {
public static <J extends AbstractJpaBaseEntity> J touch(final EntityManager entityManager,
final CrudRepository<J, ?> repository, final J entity) {
// merge base entity so optLockRevision gets updated and audit
// log written because modifying e.g. metadata is modifying the base
// merge base entity so optLockRevision gets updated and auditing log written because modifying e.g. metadata is modifying the base
// entity itself for auditing purposes.
final J result = entityManager.merge(entity);
result.setLastModifiedAt(0L);

View File

@@ -592,13 +592,11 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public DistributionSetMetadata updateMetaData(final long id, final MetaData md) {
// check if exists otherwise throw entity not found exception
final JpaDistributionSetMetadata toUpdate = (JpaDistributionSetMetadata) getMetaDataByDistributionSetId(id,
md.getKey())
final JpaDistributionSetMetadata toUpdate = (JpaDistributionSetMetadata) getMetaDataByDistributionSetId(id, md.getKey())
.orElseThrow(() -> new EntityNotFoundException(DistributionSetMetadata.class, id, md.getKey()));
toUpdate.setValue(md.getValue());
// touch it to update the lock revision because we are modifying the
// DS indirectly, it will, also check UPDATE access
// touch it to update the lock revision because we are modifying the DS indirectly, it will, also check UPDATE access
JpaManagementHelper.touch(entityManager, distributionSetRepository, (JpaDistributionSet) getValid(id));
return distributionSetMetadataRepository.save(toUpdate);
}

View File

@@ -25,6 +25,7 @@ import jakarta.persistence.PostUpdate;
import jakarta.persistence.Version;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
@@ -38,11 +39,12 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* Holder of the base attributes common to all entities.
* Base hawkBit entity class containing the common attributes.
*/
@NoArgsConstructor(access = AccessLevel.PROTECTED) // Default constructor needed for JPA entities.
@Setter
@Getter
@MappedSuperclass
@Access(AccessType.FIELD)
@EntityListeners({ AuditingEntityListener.class, EntityInterceptorListener.class })
public abstract class AbstractJpaBaseEntity implements BaseEntity {
@@ -51,62 +53,53 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
@Setter
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "created_by", updatable = false, nullable = false, length = USERNAME_FIELD_LENGTH)
private String createdBy;
@Column(name = "created_at", updatable = false, nullable = false)
private long createdAt;
@Column(name = "last_modified_by", nullable = false, length = USERNAME_FIELD_LENGTH)
private String lastModifiedBy;
@Column(name = "last_modified_at", nullable = false)
private long lastModifiedAt;
@Setter
@Version
@Column(name = "optlock_revision")
private int optLockRevision;
@Override
@CreatedBy
public void setCreatedBy(final String createdBy) {
if (isController()) {
this.createdBy = "CONTROLLER_PLUG_AND_PLAY";
// In general modification audit entry is not changed by the controller.
// However, we want to stay consistent with EnableJpaAuditing#modifyOnCreate=true.
this.lastModifiedBy = this.createdBy;
return;
}
this.createdBy = createdBy;
}
// maybe needed to have correct createdBy value in the database
@Access(AccessType.PROPERTY)
@Column(name = "created_by", updatable = false, nullable = false, length = USERNAME_FIELD_LENGTH)
public String getCreatedBy() {
return createdBy;
}
@Override
@Access(AccessType.PROPERTY)
@Column(name = "created_at", updatable = false, nullable = false)
public long getCreatedAt() {
return createdAt;
}
@CreatedDate
public void setCreatedAt(final long createdAt) {
this.createdAt = createdAt;
@Override
@Access(AccessType.PROPERTY)
@Column(name = "last_modified_by", nullable = false, length = USERNAME_FIELD_LENGTH)
public String getLastModifiedBy() {
return lastModifiedBy;
}
@Override
@Access(AccessType.PROPERTY)
@Column(name = "last_modified_at", nullable = false)
public long getLastModifiedAt() {
return lastModifiedAt;
}
@Override
public int getOptLockRevision() {
return optLockRevision;
}
@LastModifiedDate
public void setLastModifiedAt(final long lastModifiedAt) {
// In general modification audit entry is not changed by the controller.
// However, we want to stay consistent with EnableJpaAuditing#modifyOnCreate=true.
if (isController()) {
return;
this.lastModifiedAt = createdAt;
}
this.lastModifiedAt = lastModifiedAt;
}
@LastModifiedBy
@@ -118,44 +111,36 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
this.lastModifiedBy = lastModifiedBy;
}
@CreatedDate
public void setCreatedAt(final long createdAt) {
this.createdAt = createdAt;
// In general modification audit entry is not changed by the controller.
// However, we want to stay consistent with
// EnableJpaAuditing#modifyOnCreate=true.
if (isController()) {
this.lastModifiedAt = createdAt;
}
// maybe needed to have correct createdAt value in the database
@Access(AccessType.PROPERTY)
public long getCreatedAt() {
return createdAt;
}
@CreatedBy
public void setCreatedBy(final String createdBy) {
if (isController()) {
this.createdBy = "CONTROLLER_PLUG_AND_PLAY";
// seems needed to have correct lastModifiedBy value in the database
@Access(AccessType.PROPERTY)
public String getLastModifiedBy() {
return lastModifiedBy;
}
// In general modification audit entry is not changed by the
// controller. However, we want to stay consistent with
// EnableJpaAuditing#modifyOnCreate=true.
this.lastModifiedBy = this.createdBy;
@LastModifiedDate
public void setLastModifiedAt(final long lastModifiedAt) {
if (isController()) {
return;
}
this.createdBy = createdBy;
this.lastModifiedAt = lastModifiedAt;
}
@Override
public Long getId() {
return id;
// property access to make entity manager to detect touch
@Access(AccessType.PROPERTY)
public long getLastModifiedAt() {
return lastModifiedAt;
}
/**
* Defined equals/hashcode strategy for the repository in general is that an
* entity is equal if it has the same {@link #getId()} and
* 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
@@ -170,11 +155,8 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
}
/**
* Defined equals/hashcode strategy for the repository in general is that an
* entity is equal if it has the same {@link #getId()} and
* 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) {

View File

@@ -33,7 +33,10 @@ import org.eclipse.persistence.annotations.TenantDiscriminatorColumn;
* Holder of the base attributes common to all tenant aware entities.
*/
@NoArgsConstructor(access = AccessLevel.PROTECTED) // Default constructor needed for JPA entities.
@Setter
@Getter
@MappedSuperclass
// Eclipse link MultiTenant support
@TenantDiscriminatorColumn(name = "tenant", length = 40)
@Multitenant(MultitenantType.SINGLE_TABLE)
public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEntity implements TenantAwareBaseEntity {
@@ -41,8 +44,6 @@ public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEn
@Serial
private static final long serialVersionUID = 1L;
@Setter
@Getter
@Column(name = "tenant", nullable = false, insertable = false, updatable = false, length = 40)
@Size(min = 1, max = 40)
@NotNull
@@ -74,13 +75,10 @@ public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEn
}
final AbstractJpaTenantAwareBaseEntity other = (AbstractJpaTenantAwareBaseEntity) obj;
if (tenant == null) {
if (other.tenant != null) {
return false;
}
} else if (!tenant.equals(other.tenant)) {
return false;
return other.tenant == null;
} else {
return tenant.equals(other.tenant);
}
return true;
}
@Override

View File

@@ -25,6 +25,10 @@ import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
@@ -32,9 +36,14 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
/**
* JPA implementation of {@link Artifact}.
*/
@Table(name = "sp_artifact", indexes = { @Index(name = "sp_idx_artifact_01", columnList = "tenant,software_module"),
@Index(name = "sp_idx_artifact_02", columnList = "tenant,sha1_hash"),
@Index(name = "sp_idx_artifact_prim", columnList = "tenant,id") })
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor needed for JPA entities.
@Setter
@Getter
@Table(name = "sp_artifact",
indexes = {
@Index(name = "sp_idx_artifact_01", columnList = "tenant,software_module"),
@Index(name = "sp_idx_artifact_02", columnList = "tenant,sha1_hash"),
@Index(name = "sp_idx_artifact_prim", columnList = "tenant,id") })
@Entity
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities
@SuppressWarnings("squid:S2160")
@@ -43,36 +52,31 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art
@Serial
private static final long serialVersionUID = 1L;
@Column(name = "sha1_hash", length = 40, nullable = false, updatable = false)
@Size(min = 1, max = 40)
@NotNull
private String sha1Hash;
@ManyToOne(optional = false, cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)
@JoinColumn(
name = "software_module", nullable = false, updatable = false,
foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_assigned_sm"))
private JpaSoftwareModule softwareModule;
@Column(name = "provided_file_name", length = 256, updatable = false)
@Size(min = 1, max = 256)
@NotNull
private String filename;
@ManyToOne(optional = false, cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)
@JoinColumn(name = "software_module", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_assigned_sm"))
private JpaSoftwareModule softwareModule;
@Column(name = "md5_hash", length = 32, updatable = false, nullable = true)
private String md5Hash;
@Column(name = "sha1_hash", length = 40, nullable = false, updatable = false)
@Size(min = 1, max = 40)
@NotNull
private String sha1Hash;
@Column(name = "sha256_hash", length = 64, updatable = false, nullable = true)
private String sha256Hash;
@Column(name = "file_size", updatable = false)
private long size;
/**
* Default constructor needed for JPA entities..
*/
public JpaArtifact() {
// Default constructor needed for JPA entities.
}
/**
* Constructs artifact.
*
@@ -80,57 +84,10 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art
* @param filename that is used by {@link AbstractDbArtifact} store.
* @param softwareModule of this artifact
*/
public JpaArtifact(@NotEmpty final String sha1Hash, @NotNull final String filename,
final SoftwareModule softwareModule) {
public JpaArtifact(@NotEmpty final String sha1Hash, @NotNull final String filename, final SoftwareModule softwareModule) {
this.sha1Hash = sha1Hash;
this.filename = filename;
this.softwareModule = (JpaSoftwareModule) softwareModule;
this.softwareModule.addArtifact(this);
}
@Override
public String getFilename() {
return filename;
}
@Override
public SoftwareModule getSoftwareModule() {
return softwareModule;
}
@Override
public String getMd5Hash() {
return md5Hash;
}
@Override
public String getSha1Hash() {
return sha1Hash;
}
@Override
public String getSha256Hash() {
return sha256Hash;
}
public void setSha256Hash(final String sha256Hash) {
this.sha256Hash = sha256Hash;
}
@Override
public long getSize() {
return size;
}
public void setSize(final long size) {
this.size = size;
}
public void setSha1Hash(final String sha1Hash) {
this.sha1Hash = sha1Hash;
}
public void setMd5Hash(final String md5Hash) {
this.md5Hash = md5Hash;
}
}
}

View File

@@ -19,11 +19,17 @@ import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.Target;
import org.springframework.util.StringUtils;
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor needed for JPA entities.
@Getter
@Entity
@Table(name = "sp_target_conf_status")
public class JpaAutoConfirmationStatus extends AbstractJpaTenantAwareBaseEntity implements AutoConfirmationStatus {
@@ -40,39 +46,17 @@ public class JpaAutoConfirmationStatus extends AbstractJpaTenantAwareBaseEntity
@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE)
private String remark;
/**
* Default constructor needed for JPA entities.
*/
public JpaAutoConfirmationStatus() {
// Default constructor needed for JPA entities.
}
public JpaAutoConfirmationStatus(final String initiator, final String remark, final Target target) {
this.target = (JpaTarget) target;
this.initiator = StringUtils.isEmpty(initiator) ? null : initiator;
this.remark = StringUtils.isEmpty(remark) ? null : remark;
}
@Override
public Target getTarget() {
return target;
}
@Override
public String getInitiator() {
return initiator;
}
@Override
public long getActivatedAt() {
return getCreatedAt();
}
@Override
public String getRemark() {
return remark;
}
@Override
public String constructActionMessage() {
final String remarkMessage = StringUtils.hasText(remark) ? remark : "n/a";
@@ -82,16 +66,16 @@ public class JpaAutoConfirmationStatus extends AbstractJpaTenantAwareBaseEntity
// nevertheless of the end of line of the file (\r\n, \n or \r) the result will contains \n
return """
Assignment automatically confirmed by initiator '%s'.\040
Auto confirmation activated by system user: '%s'\040
Remark: %s""".formatted(formattedInitiator, createdByRolloutsUser, remarkMessage);
}
@Override
public String toString() {
return "AutoConfirmationStatus [id=" + getId() + ", target=" + target.getControllerId() + ", initiator="
+ initiator + ", bosch_user=" + getCreatedBy() + ", activatedAt=" + getCreatedAt() + ", remark="
+ remark + "]";
return "AutoConfirmationStatus [id=" + getId() + ", target=" + target.getControllerId() +
", initiator=" + initiator + ", bosch_user=" + getCreatedBy() + ", activatedAt=" + getCreatedAt() +
", remark=" + remark + "]";
}
}

View File

@@ -37,6 +37,7 @@ import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.eclipse.hawkbit.repository.event.remote.DistributionSetDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
@@ -60,12 +61,13 @@ import org.springframework.context.ApplicationEvent;
@Getter
@ToString(callSuper = true)
@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,complete"),
@Index(name = "sp_idx_distribution_set_prim", columnList = "tenant,id") })
@NamedEntityGraph(name = "DistributionSet.detail", attributeNodes = { @NamedAttributeNode("modules"),
@NamedAttributeNode("tags"), @NamedAttributeNode("type") })
@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,complete"),
@Index(name = "sp_idx_distribution_set_prim", columnList = "tenant,id") })
@NamedEntityGraph(name = "DistributionSet.detail",
attributeNodes = { @NamedAttributeNode("modules"), @NamedAttributeNode("tags"), @NamedAttributeNode("type") })
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities
@SuppressWarnings("squid:S2160")
public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet, EventAwareEntity {
@@ -75,6 +77,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
private static final String DELETED_PROPERTY = "deleted";
@Setter
@ManyToOne(fetch = FetchType.LAZY, optional = false, targetEntity = JpaDistributionSetType.class)
@JoinColumn(name = "ds_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_dstype_ds"))
@NotNull
@@ -117,12 +120,14 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
@Column(name = "locked")
private boolean locked;
@Setter
@Column(name = "deleted")
private boolean deleted;
@Column(name = "valid")
private boolean valid;
@Setter
@Column(name = "required_migration_step")
private boolean requiredMigrationStep;
@@ -155,10 +160,6 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
this(name, version, description, type, moduleList, false);
}
public void setType(final DistributionSetType type) {
this.type = type;
}
@Override
public Set<SoftwareModule> getModules() {
if (modules == null) {
@@ -168,7 +169,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
return Collections.unmodifiableSet(modules);
}
public boolean addModule(final SoftwareModule softwareModule) {
public void addModule(final SoftwareModule softwareModule) {
if (isLocked()) {
throw new LockedException(JpaDistributionSet.class, getId(), "ADD_SOFTWARE_MODULE");
}
@@ -183,7 +184,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
.filter(module -> module.getId().equals(softwareModule.getId())).findAny();
if (found.isPresent()) {
return false;
return;
}
final long already = modules.stream()
@@ -196,10 +197,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
if (modules.add(softwareModule)) {
complete = type.checkComplete(this);
return true;
}
return false;
}
public void removeModule(final SoftwareModule softwareModule) {
@@ -255,18 +253,10 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
locked = false;
}
public void setDeleted(final boolean deleted) {
this.deleted = deleted;
}
public void invalidate() {
this.valid = false;
}
public void setRequiredMigrationStep(final boolean isRequiredMigrationStep) {
requiredMigrationStep = isRequiredMigrationStep;
}
@Override
public void fireCreateEvent() {
publishEventWithEventPublisher(

View File

@@ -21,12 +21,18 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
/**
* Meta data for {@link DistributionSet}.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor needed for JPA entities.
@Getter
@IdClass(DsMetadataCompositeKey.class)
@Entity
@Table(name = "sp_ds_metadata")
@@ -40,10 +46,6 @@ public class JpaDistributionSetMetadata extends AbstractJpaMetaData implements D
@JoinColumn(name = "ds_id", nullable = false, updatable = false, 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 String value) {
super(key, value);
}
@@ -57,11 +59,6 @@ public class JpaDistributionSetMetadata extends AbstractJpaMetaData implements D
return new DsMetadataCompositeKey(distributionSet.getId(), getKey());
}
@Override
public DistributionSet getDistributionSet() {
return distributionSet;
}
public void setDistributionSet(final DistributionSet distributionSet) {
this.distributionSet = (JpaDistributionSet) distributionSet;
}
@@ -83,12 +80,9 @@ public class JpaDistributionSetMetadata extends AbstractJpaMetaData implements D
}
final JpaDistributionSetMetadata other = (JpaDistributionSetMetadata) obj;
if (distributionSet == null) {
if (other.distributionSet != null) {
return false;
}
} else if (!distributionSet.equals(other.distributionSet)) {
return false;
return other.distributionSet == null;
} else {
return distributionSet.equals(other.distributionSet);
}
return true;
}
}

View File

@@ -19,6 +19,8 @@ import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.repository.event.remote.DistributionSetTagDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagUpdatedEvent;
@@ -27,9 +29,9 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
/**
* A {@link DistributionSetTag} is used to describe DistributionSet attributes
* and use them also for filtering the DistributionSet list.
* A {@link DistributionSetTag} is used to describe DistributionSet attributes and use them also for filtering the DistributionSet list.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor needed for JPA entities.
@Entity
@Table(name = "sp_distributionset_tag",
indexes = {
@@ -55,13 +57,6 @@ public class JpaDistributionSetTag extends JpaTag implements DistributionSetTag,
super(name, description, colour);
}
/**
* Default constructor for JPA.
*/
public JpaDistributionSetTag() {
// Default constructor for JPA.
}
@Override
public void fireCreateEvent() {
EventPublisherHolder.getInstance().getEventPublisher().publishEvent(

View File

@@ -27,6 +27,10 @@ import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.event.remote.DistributionSetTypeDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTypeCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTypeUpdatedEvent;
@@ -39,9 +43,9 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
import org.springframework.util.CollectionUtils;
/**
* A distribution set type defines which software module types can or have to be
* {@link DistributionSet}.
* A distribution set type defines which software module types can or have to be {@link DistributionSet}.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor needed for JPA entities.
@Entity
@Table(name = "sp_distribution_set_type", indexes = {
@Index(name = "sp_idx_distribution_set_type_01", columnList = "tenant,deleted"),
@@ -57,68 +61,34 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis
@OneToMany(mappedBy = "dsType", targetEntity = DistributionSetTypeElement.class, fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST,
CascadeType.REMOVE }, orphanRemoval = true)
private Set<DistributionSetTypeElement> elements;
private Set<DistributionSetTypeElement> elements = new HashSet<>();
@Setter
@Getter
@Column(name = "deleted")
private boolean deleted;
@ManyToMany(mappedBy = "distributionSetTypes", targetEntity = JpaTargetType.class, fetch = FetchType.LAZY)
private List<TargetType> compatibleToTargetTypes;
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 colour of the type. It will be null by default
*/
public JpaDistributionSetType(final String key, final String name, final String description, final String colour) {
super(name, description, key, colour);
}
@Override
public boolean isDeleted() {
return deleted;
}
public void setDeleted(final boolean deleted) {
this.deleted = deleted;
}
@Override
public Set<SoftwareModuleType> getMandatoryModuleTypes() {
if (elements == null) {
return Collections.emptySet();
}
return elements.stream().filter(DistributionSetTypeElement::isMandatory)
.map(DistributionSetTypeElement::getSmType).collect(Collectors.toSet());
}
@Override
public Set<SoftwareModuleType> getOptionalModuleTypes() {
if (elements == null) {
return Collections.emptySet();
}
return elements.stream().filter(element -> !element.isMandatory()).map(DistributionSetTypeElement::getSmType)
.collect(Collectors.toSet());
return elements.stream().filter(element -> !element.isMandatory())
.map(DistributionSetTypeElement::getSmType).collect(Collectors.toSet());
}
@Override
@@ -134,12 +104,11 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis
@Override
public boolean checkComplete(final DistributionSet distributionSet) {
final List<SoftwareModuleType> smTypes = distributionSet.getModules().stream().map(SoftwareModule::getType)
.distinct().toList();
if (smTypes.isEmpty()) {
return false;
}
return new HashSet<>(smTypes).containsAll(getMandatoryModuleTypes());
final List<SoftwareModuleType> smTypes = distributionSet.getModules().stream()
.map(SoftwareModule::getType)
.distinct()
.toList();
return !smTypes.isEmpty() && new HashSet<>(smTypes).containsAll(getMandatoryModuleTypes());
}
public JpaDistributionSetType addOptionalModuleType(final SoftwareModuleType smType) {
@@ -151,22 +120,14 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis
}
public JpaDistributionSetType removeModuleType(final Long smTypeId) {
if (elements == null) {
return this;
}
// we search by id (standard equals compares also revison)
elements.stream().filter(element -> element.getSmType().getId().equals(smTypeId)).findAny()
// we search by id (standard equals compares also revision)
elements.stream().filter(element -> element.getSmType().getId().equals(smTypeId))
.findAny()
.ifPresent(elements::remove);
return this;
}
public Set<DistributionSetTypeElement> getElements() {
if (elements == null) {
return Collections.emptySet();
}
return Collections.unmodifiableSet(elements);
}
@@ -194,10 +155,8 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis
}
private boolean isOneModuleListEmpty(final DistributionSetType dsType) {
return (!CollectionUtils.isEmpty(((JpaDistributionSetType) dsType).elements)
&& CollectionUtils.isEmpty(elements))
|| (CollectionUtils.isEmpty(((JpaDistributionSetType) dsType).elements)
&& !CollectionUtils.isEmpty(elements));
return (!CollectionUtils.isEmpty(((JpaDistributionSetType) dsType).elements) && CollectionUtils.isEmpty(elements)) ||
(CollectionUtils.isEmpty(((JpaDistributionSetType) dsType).elements) && !CollectionUtils.isEmpty(elements));
}
private boolean areBothModuleListsEmpty(final DistributionSetType dsType) {
@@ -205,22 +164,19 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis
}
private JpaDistributionSetType setModuleType(final SoftwareModuleType smType, final boolean mandatory) {
if (elements == null) {
elements = new HashSet<>();
if (elements.isEmpty()) {
elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory));
return this;
}
// check if this was in the list before before
final Optional<DistributionSetTypeElement> existing = elements.stream()
.filter(element -> element.getSmType().getKey().equals(smType.getKey())).findAny();
if (existing.isPresent()) {
existing.get().setMandatory(mandatory);
} else {
elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory));
}
// check if this was in the list before
elements.stream()
.filter(element -> element.getSmType().getKey().equals(smType.getKey()))
.findAny()
.ifPresentOrElse(
element -> element.setMandatory(mandatory),
() -> elements.add(new DistributionSetTypeElement(this, (JpaSoftwareModuleType) smType, mandatory)));
return this;
}
}
}

View File

@@ -10,6 +10,7 @@
package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serial;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -34,6 +35,10 @@ import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.RolloutCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.RolloutUpdatedEvent;
@@ -50,6 +55,7 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
/**
* JPA implementation of a {@link Rollout}.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor needed for JPA entities.
@Entity
@Table(name = "sp_rollout", uniqueConstraints = @UniqueConstraint(columnNames = { "name",
"tenant" }, name = "uk_rollout"))
@@ -61,80 +67,134 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event
private static final long serialVersionUID = 1L;
@OneToMany(targetEntity = JpaRolloutGroup.class, fetch = FetchType.LAZY, cascade = { CascadeType.REMOVE }, mappedBy = "rollout")
private List<JpaRolloutGroup> rolloutGroups;
private List<JpaRolloutGroup> rolloutGroups = new ArrayList<>();
@Setter
@Getter
@Column(name = "target_filter", length = TargetFilterQuery.QUERY_MAX_SIZE, nullable = false)
@Size(min = 1, max = TargetFilterQuery.QUERY_MAX_SIZE)
@NotNull
private String targetFilterQuery;
@Getter
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "distribution_set", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rolltout_ds"))
@NotNull
private JpaDistributionSet distributionSet;
@Setter
@Getter
@Column(name = "status", nullable = false)
@Convert(converter = RolloutStatusConverter.class)
@NotNull
private RolloutStatus status = RolloutStatus.CREATING;
@Setter
@Getter
@Column(name = "last_check")
private long lastCheck;
@Setter
@Getter
@Column(name = "action_type", nullable = false)
@Convert(converter = JpaAction.ActionTypeConverter.class)
@NotNull
private ActionType actionType = ActionType.FORCED;
@Setter
@Getter
@Column(name = "forced_time")
private long forcedTime;
@Setter
@Getter
@Column(name = "total_targets")
private long totalTargets;
@Setter
@Getter
@Column(name = "rollout_groups_created")
private int rolloutGroupsCreated;
@Setter
@Getter
@Column(name = "deleted")
private boolean deleted;
@Setter
@Getter
@Column(name = "start_at")
private Long startAt;
@Setter
@Getter
@Column(name = "approval_decided_by")
@Size(min = 1, max = Rollout.APPROVED_BY_MAX_SIZE)
private String approvalDecidedBy;
@Setter
@Getter
@Column(name = "approval_remark")
@Size(max = Rollout.APPROVAL_REMARK_MAX_SIZE)
private String approvalRemark;
@Setter
@Column(name = "weight")
@Min(Action.WEIGHT_MIN)
@Max(Action.WEIGHT_MAX)
private Integer weight;
@Setter
@Column(name = "is_dynamic") // dynamic is reserved keyword in some databases
private Boolean dynamic;
@Setter
@Column(name = "access_control_context", nullable = true)
private String accessControlContext;
@Setter
@Transient
private transient TotalTargetCountStatus totalTargetCountStatus;
public List<RolloutGroup> getRolloutGroups() {
if (rolloutGroups == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(rolloutGroups);
}
public long getLastCheck() {
return lastCheck;
}
public void setLastCheck(final long lastCheck) {
this.lastCheck = lastCheck;
}
// dynamic is null only for old rollouts - could be used for distinguishing
// old once from the other
// dynamic is null only for old rollouts - could be used for distinguishing old once from the other
public boolean isNewStyleTargetPercent() {
return dynamic != null;
}
public void setDistributionSet(final DistributionSet distributionSet) {
this.distributionSet = (JpaDistributionSet) distributionSet;
}
@Override
public TotalTargetCountStatus getTotalTargetCountStatus() {
if (totalTargetCountStatus == null) {
totalTargetCountStatus = new TotalTargetCountStatus(totalTargets, actionType);
}
return totalTargetCountStatus;
}
@Override
public Optional<Integer> getWeight() {
return Optional.ofNullable(weight);
}
@Override
public boolean isDynamic() {
return Boolean.TRUE.equals(dynamic);
}
public Optional<String> getAccessControlContext() {
return Optional.ofNullable(accessControlContext);
}
@Override
public String toString() {
return "Rollout [ targetFilterQuery=" + targetFilterQuery + ", distributionSet=" + distributionSet + ", status="
+ status + ", lastCheck=" + lastCheck + ", getName()=" + getName() + ", getId()=" + getId() + "]";
return "Rollout [ targetFilterQuery=" + targetFilterQuery + ", distributionSet=" + distributionSet + ", status=" + status +
", lastCheck=" + lastCheck + ", getName()=" + getName() + ", getId()=" + getId() + "]";
}
@Override
@@ -160,143 +220,6 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event
getId(), getClass(), EventPublisherHolder.getInstance().getApplicationId()));
}
@Override
public boolean isDeleted() {
return deleted;
}
@Override
public DistributionSet getDistributionSet() {
return distributionSet;
}
public void setDistributionSet(final DistributionSet distributionSet) {
this.distributionSet = (JpaDistributionSet) distributionSet;
}
@Override
public String getTargetFilterQuery() {
return targetFilterQuery;
}
public void setTargetFilterQuery(final String targetFilterQuery) {
this.targetFilterQuery = targetFilterQuery;
}
@Override
public RolloutStatus getStatus() {
return status;
}
public void setStatus(final RolloutStatus status) {
this.status = status;
}
@Override
public ActionType getActionType() {
return actionType;
}
public void setActionType(final ActionType actionType) {
this.actionType = actionType;
}
@Override
public long getForcedTime() {
return forcedTime;
}
@Override
public Long getStartAt() {
return startAt;
}
public void setStartAt(final Long startAt) {
this.startAt = startAt;
}
@Override
public long getTotalTargets() {
return totalTargets;
}
public void setTotalTargets(final long totalTargets) {
this.totalTargets = totalTargets;
}
@Override
public int getRolloutGroupsCreated() {
return rolloutGroupsCreated;
}
public void setRolloutGroupsCreated(final int rolloutGroupsCreated) {
this.rolloutGroupsCreated = rolloutGroupsCreated;
}
@Override
public TotalTargetCountStatus getTotalTargetCountStatus() {
if (totalTargetCountStatus == null) {
totalTargetCountStatus = new TotalTargetCountStatus(totalTargets, actionType);
}
return totalTargetCountStatus;
}
public void setTotalTargetCountStatus(final TotalTargetCountStatus totalTargetCountStatus) {
this.totalTargetCountStatus = totalTargetCountStatus;
}
@Override
public String getApprovalDecidedBy() {
return approvalDecidedBy;
}
public void setApprovalDecidedBy(final String approvalDecidedBy) {
this.approvalDecidedBy = approvalDecidedBy;
}
@Override
public String getApprovalRemark() {
return approvalRemark;
}
@Override
public Optional<Integer> getWeight() {
return Optional.ofNullable(weight);
}
public void setWeight(final Integer weight) {
this.weight = weight;
}
@Override
public boolean isDynamic() {
return Boolean.TRUE.equals(dynamic);
}
public void setDynamic(final Boolean dynamic) {
this.dynamic = dynamic;
}
public Optional<String> getAccessControlContext() {
return Optional.ofNullable(accessControlContext);
}
public void setAccessControlContext(final String accessControlContext) {
this.accessControlContext = accessControlContext;
}
public void setApprovalRemark(final String approvalRemark) {
this.approvalRemark = approvalRemark;
}
public void setForcedTime(final long forcedTime) {
this.forcedTime = forcedTime;
}
public void setDeleted(final boolean deleted) {
this.deleted = deleted;
}
@Converter
public static class RolloutStatusConverter extends MapAttributeConverter<RolloutStatus, Integer> {

View File

@@ -31,7 +31,9 @@ import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.event.remote.RolloutGroupDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.RolloutGroupUpdatedEvent;
@@ -44,6 +46,7 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
/**
* JPA entity definition of persisting a group of an rollout.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor needed for JPA entities.
@Entity
@Table(name = "sp_rolloutgroup", uniqueConstraints = @UniqueConstraint(columnNames = { "name", "rollout", "tenant" }, name = "uk_rolloutgroup"))
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities
@@ -57,80 +60,97 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rollout", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_rolloutgroup_rollout"))
private JpaRollout rollout;
@Setter
@Getter
@Column(name = "status", nullable = false)
@Convert(converter = RolloutGroupStatusConverter.class)
private RolloutGroupStatus status = RolloutGroupStatus.CREATING;
@OneToMany(mappedBy = "rolloutGroup", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST,
CascadeType.REMOVE }, targetEntity = RolloutTargetGroup.class)
private List<RolloutTargetGroup> rolloutTargetGroup;
// No foreign key to avoid to many nested cascades on delete which some DBs cannot handle
@Setter
@Getter
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST })
@JoinColumn(name = "parent_id")
private JpaRolloutGroup parent;
@Setter
@Getter
@Column(name = "is_dynamic") // dynamic is reserved keyword in some databases
private boolean dynamic;
@Setter
@Getter
@Column(name = "success_condition", nullable = false)
@NotNull
private RolloutGroupSuccessCondition successCondition = RolloutGroupSuccessCondition.THRESHOLD;
@Setter
@Getter
@Column(name = "success_condition_exp", length = 512, nullable = false)
@Size(max = 512)
@NotNull
private String successConditionExp;
@Setter
@Getter
@Column(name = "success_action", nullable = false)
@NotNull
private RolloutGroupSuccessAction successAction = RolloutGroupSuccessAction.NEXTGROUP;
@Setter
@Getter
@Column(name = "success_action_exp", length = 512)
@Size(max = 512)
private String successActionExp;
@Setter
@Getter
@Column(name = "error_condition")
private RolloutGroupErrorCondition errorCondition;
@Setter
@Getter
@Column(name = "error_condition_exp", length = 512)
@Size(max = 512)
private String errorConditionExp;
@Setter
@Getter
@Column(name = "error_action")
private RolloutGroupErrorAction errorAction;
@Setter
@Getter
@Column(name = "error_action_exp", length = 512)
@Size(max = 512)
private String errorActionExp;
@Setter
@Getter
@Column(name = "total_targets")
private int totalTargets;
@Setter
@Getter
@Column(name = "target_filter", length = 1024)
@Size(max = 1024)
private String targetFilterQuery = "";
@Setter
@Getter
@Column(name = "target_percentage")
private float targetPercentage = 100;
@Setter
@Getter
@Column(name = "confirmation_required")
private boolean confirmationRequired;
@Setter
@Transient
private transient TotalTargetCountStatus totalTargetCountStatus;
@@ -150,14 +170,6 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr
return totalTargetCountStatus;
}
public List<RolloutTargetGroup> getRolloutTargetGroup() {
if (rolloutTargetGroup == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(rolloutTargetGroup);
}
@Override
public String toString() {
return "RolloutGroup [" +

View File

@@ -48,10 +48,10 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
/**
* Base Software Module that is supported by OS level provisioning mechanism on
* the edge controller, e.g. OS, JVM, AgentHub.
* Base Software Module that is supported by OS level provisioning mechanism on the edge controller, e.g. OS, JVM, AgentHub.
*/
@NoArgsConstructor // Default constructor for JPA
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Setter
@Getter
@ToString(callSuper = true)
@Entity
@@ -73,12 +73,14 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement
@Setter
@ManyToOne
@JoinColumn(name = "module_type", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_module_type"))
@JoinColumn(name = "module_type", nullable = false, updatable = false,
foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_module_type"))
@NotNull
private JpaSoftwareModuleType type;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "softwareModule", cascade = { CascadeType.PERSIST,
CascadeType.REMOVE }, targetEntity = JpaArtifact.class, orphanRemoval = true)
@OneToMany(fetch = FetchType.LAZY, mappedBy = "softwareModule",
cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE },
targetEntity = JpaArtifact.class, orphanRemoval = true)
private List<JpaArtifact> artifacts;
@Setter
@@ -91,8 +93,9 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement
private boolean encrypted;
@ToString.Exclude
@OneToMany(mappedBy = "softwareModule", fetch = FetchType.LAZY, cascade = {
CascadeType.REMOVE }, targetEntity = JpaSoftwareModuleMetadata.class)
@OneToMany(mappedBy = "softwareModule", fetch = FetchType.LAZY,
cascade = { CascadeType.REMOVE },
targetEntity = JpaSoftwareModuleMetadata.class)
private List<JpaSoftwareModuleMetadata> metadata;
@Column(name = "locked")
@@ -146,9 +149,6 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement
}
}
/**
* @param artifact is removed from the assigned {@link Artifact}s.
*/
public void removeArtifact(final Artifact artifact) {
if (isLocked()) {
throw new LockedException(JpaSoftwareModule.class, getId(), "REMOVE_ARTIFACT");

View File

@@ -22,12 +22,21 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
/**
* Metadata for {@link SoftwareModule}.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@IdClass(SwMetadataCompositeKey.class)
@Entity
@Table(name = "sp_sw_metadata")
@@ -44,73 +53,19 @@ public class JpaSoftwareModuleMetadata extends AbstractJpaMetaData implements So
@Column(name = "target_visible")
private boolean targetVisible;
public JpaSoftwareModuleMetadata() {
// default public constructor for JPA
}
public JpaSoftwareModuleMetadata(final String key, final SoftwareModule softwareModule, final String value) {
super(key, value);
this.softwareModule = (JpaSoftwareModule) softwareModule;
}
public JpaSoftwareModuleMetadata(final String key, final SoftwareModule softwareModule, final String value,
final boolean targetVisible) {
public JpaSoftwareModuleMetadata(final String key, final SoftwareModule softwareModule, final String value, final boolean targetVisible) {
super(key, value);
this.softwareModule = (JpaSoftwareModule) softwareModule;
this.targetVisible = targetVisible;
}
public JpaSoftwareModuleMetadata(final String key, final String value, final boolean targetVisible) {
super(key, value);
this.targetVisible = targetVisible;
}
public SwMetadataCompositeKey getId() {
return new SwMetadataCompositeKey(softwareModule.getId(), getKey());
}
@Override
public SoftwareModule getSoftwareModule() {
return softwareModule;
}
public void setSoftwareModule(final JpaSoftwareModule softwareModule) {
this.softwareModule = softwareModule;
}
@Override
public boolean isTargetVisible() {
return targetVisible;
}
public void setTargetVisible(final boolean targetVisible) {
this.targetVisible = targetVisible;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((softwareModule == null) ? 0 : softwareModule.hashCode());
return result;
}
@Override
// exception squid:S2259 - obj is checked for null in super
@SuppressWarnings("squid:S2259")
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

@@ -18,6 +18,10 @@ import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.Min;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleTypeDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleTypeCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleTypeUpdatedEvent;
@@ -25,8 +29,9 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
/**
* Type of a software modules.
* Type of software modules.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Entity
@Table(name = "sp_software_module_type", indexes = {
@Index(name = "sp_idx_software_module_type_01", columnList = "tenant,deleted"),
@@ -40,66 +45,25 @@ public class JpaSoftwareModuleType extends AbstractJpaTypeEntity implements Soft
@Serial
private static final long serialVersionUID = 1L;
@Getter
@Column(name = "max_ds_assignments", nullable = false)
@Min(1)
private int maxAssignments;
@Setter
@Getter
@Column(name = "deleted")
private boolean deleted;
/**
* 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) {
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) {
public JpaSoftwareModuleType(final String key, final String name, final String description, final int maxAssignments, final String colour) {
super(name, description, key, colour);
this.maxAssignments = maxAssignments;
}
/**
* Default Constructor for JPA.
*/
public JpaSoftwareModuleType() {
// Default Constructor for JPA.
}
@Override
public int getMaxAssignments() {
return maxAssignments;
}
public void setMaxAssignments(final int maxAssignments) {
this.maxAssignments = maxAssignments;
}
@Override
public boolean isDeleted() {
return deleted;
}
public void setDeleted(final boolean deleted) {
this.deleted = deleted;
}
@Override
public String toString() {
return "SoftwareModuleType [key=" + getKey() + ", getName()=" + getName() + ", getId()=" + getId() + "]";
@@ -122,4 +86,4 @@ public class JpaSoftwareModuleType extends AbstractJpaTypeEntity implements Soft
EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new SoftwareModuleTypeDeletedEvent(
getTenant(), getId(), getClass(), EventPublisherHolder.getInstance().getApplicationId()));
}
}
}

View File

@@ -12,6 +12,4 @@ package org.eclipse.hawkbit.repository.jpa.model;
import org.eclipse.hawkbit.repository.model.Statistic;
public interface JpaStatistic extends Statistic {
}
public interface JpaStatistic extends Statistic {}

View File

@@ -15,12 +15,18 @@ import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.model.Tag;
/**
* A Tag can be used as describing and organizational meta information for any
* kind of entity.
* A Tag can be used as describing and organizational meta information for any kind of entity.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Setter
@Getter
@MappedSuperclass
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities
@SuppressWarnings("squid:S2160")
@@ -33,33 +39,13 @@ public class JpaTag extends AbstractJpaNamedEntity implements Tag {
@Size(max = Tag.COLOUR_MAX_SIZE)
private String colour;
protected JpaTag() {
// Default constructor needed for JPA entities
}
/**
* 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;
}
public void setColour(final String colour) {
this.colour = colour;
}
@Override
public String toString() {
return "Tag [getOptLockRevision()=" + getOptLockRevision() + ", getId()=" + getId() + "]";
}
}
}

View File

@@ -74,7 +74,7 @@ import org.eclipse.persistence.queries.UpdateObjectQuery;
/**
* JPA implementation of {@link Target}.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // empty constructor for JPA.
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Entity
@Table(name = "sp_target",
indexes = {

View File

@@ -25,6 +25,10 @@ import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.event.remote.TargetFilterQueryDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetFilterQueryCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetFilterQueryUpdatedEvent;
@@ -37,6 +41,9 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
/**
* Stored target filter.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Setter
@Getter
@Entity
@Table(
name = "sp_target_filter_query",
@@ -78,20 +85,6 @@ public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity imple
@Column(name = "access_control_context", nullable = true)
private String accessControlContext;
public JpaTargetFilterQuery() {
// Default constructor for JPA.
}
/**
* Construct a Target filter query with auto assign distribution set
*
* @param name of the {@link TargetFilterQuery}.
* @param query of the {@link TargetFilterQuery}.
* @param autoAssignDistributionSet of the {@link TargetFilterQuery}.
* @param autoAssignActionType of the {@link TargetFilterQuery}.
* @param autoAssignWeight of the {@link TargetFilterQuery}.
* @param confirmationRequired of the {@link TargetFilterQuery}.
*/
public JpaTargetFilterQuery(final String name, final String query, final DistributionSet autoAssignDistributionSet,
final ActionType autoAssignActionType, final Integer autoAssignWeight, final boolean confirmationRequired) {
this.name = name;
@@ -102,38 +95,6 @@ public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity imple
this.confirmationRequired = confirmationRequired;
}
@Override
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
@Override
public String getQuery() {
return query;
}
public void setQuery(final String query) {
this.query = query;
}
@Override
public DistributionSet getAutoAssignDistributionSet() {
return autoAssignDistributionSet;
}
public void setAutoAssignDistributionSet(final JpaDistributionSet distributionSet) {
this.autoAssignDistributionSet = distributionSet;
}
@Override
public ActionType getAutoAssignActionType() {
return autoAssignActionType;
}
public void setAutoAssignActionType(final ActionType actionType) {
if (actionType == ActionType.TIMEFORCED) {
throw new IllegalArgumentException("TIMEFORCED is not permitted in autoAssignment");
@@ -146,35 +107,11 @@ public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity imple
return Optional.ofNullable(autoAssignWeight);
}
public void setAutoAssignWeight(final Integer weight) {
this.autoAssignWeight = weight;
}
public String getAutoAssignInitiatedBy() {
return autoAssignInitiatedBy;
}
public void setAutoAssignInitiatedBy(final String autoAssignInitiatedBy) {
this.autoAssignInitiatedBy = autoAssignInitiatedBy;
}
@Override
public boolean isConfirmationRequired() {
return confirmationRequired;
}
public void setConfirmationRequired(final boolean confirmationRequired) {
this.confirmationRequired = confirmationRequired;
}
public Optional<String> getAccessControlContext() {
return Optional.ofNullable(accessControlContext);
}
public void setAccessControlContext(final String accessControlContext) {
this.accessControlContext = accessControlContext;
}
@Override
public void fireCreateEvent() {
EventPublisherHolder.getInstance().getEventPublisher().publishEvent(
@@ -192,5 +129,4 @@ public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity imple
EventPublisherHolder.getInstance().getEventPublisher().publishEvent(new TargetFilterQueryDeletedEvent(
getTenant(), getId(), getClass(), EventPublisherHolder.getInstance().getApplicationId()));
}
}
}

View File

@@ -21,12 +21,19 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetMetadata;
/**
* Meta data for {@link Target}.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Setter
@Getter
@IdClass(TargetMetadataCompositeKey.class)
@Entity
@Table(name = "sp_target_metadata")
@@ -40,15 +47,11 @@ public class JpaTargetMetadata extends AbstractJpaMetaData implements TargetMeta
@JoinColumn(name = "target_id", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_metadata_target"))
private JpaTarget target;
public JpaTargetMetadata() {
// default public constructor for JPA
}
/**
* Creates a single metadata entry with the given key and value.
*
* @param key of the meta data entry
* @param value of the meta data entry
* @param key of the meta-data entry
* @param value of the meta-data entry
*/
public JpaTargetMetadata(final String key, final String value) {
super(key, value);
@@ -58,9 +61,9 @@ public class JpaTargetMetadata extends AbstractJpaMetaData implements TargetMeta
* Creates a single metadata entry with the given key and value for the
* given {@link Target}.
*
* @param key of the meta data entry
* @param value of the meta data entry
* @param target the meta data entry is associated with
* @param key of the meta-data entry
* @param value of the meta-data entry
* @param target the meta-data entry is associated with
*/
public JpaTargetMetadata(final String key, final String value, final Target target) {
super(key, value);
@@ -71,15 +74,6 @@ public class JpaTargetMetadata extends AbstractJpaMetaData implements TargetMeta
return new TargetMetadataCompositeKey(target.getId(), getKey());
}
@Override
public Target getTarget() {
return target;
}
public void setTarget(final Target target) {
this.target = (JpaTarget) target;
}
@Override
public int hashCode() {
final int prime = 31;
@@ -97,12 +91,9 @@ public class JpaTargetMetadata extends AbstractJpaMetaData implements TargetMeta
}
final JpaTargetMetadata other = (JpaTargetMetadata) obj;
if (target == null) {
if (other.target != null) {
return false;
}
} else if (!target.equals(other.target)) {
return false;
return other.target == null;
} else {
return target.equals(other.target);
}
return true;
}
}

View File

@@ -16,6 +16,7 @@ import jakarta.persistence.Index;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.eclipse.hawkbit.repository.event.remote.TargetTagDeletedEvent;
@@ -27,7 +28,7 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
/**
* A {@link TargetTag} is used to describe Target attributes and use them also for filtering the target list.
*/
@NoArgsConstructor // Default constructor for JPA.
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@ToString(callSuper = true)
@Entity
@Table(name = "sp_target_tag", indexes = { @Index(name = "sp_idx_target_tag_prim", columnList = "tenant,id"),

View File

@@ -24,6 +24,7 @@ import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.eclipse.hawkbit.repository.event.remote.TargetTypeDeletedEvent;
@@ -35,10 +36,9 @@ import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
/**
* A target type defines which distribution set types can or have to be
* {@link Target}.
* A target type defines which distribution set types can or have to be {@link Target}.
*/
@NoArgsConstructor // default public constructor for JPA
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@ToString(callSuper = true)
@Entity
@Table(name = "sp_target_type", indexes = {
@@ -60,7 +60,7 @@ public class JpaTargetType extends AbstractJpaTypeEntity implements TargetType,
@JoinColumn(
name = "distribution_set_type", nullable = false, insertable = false, updatable = false,
foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_type_relation_ds_type")) })
private Set<DistributionSetType> distributionSetTypes;
private Set<DistributionSetType> distributionSetTypes = new HashSet<>();
public JpaTargetType(final String key, final String name, final String description, final String colour) {
super(name, description, key, colour);
@@ -73,21 +73,12 @@ public class JpaTargetType extends AbstractJpaTypeEntity implements TargetType,
* @return Target type
*/
public JpaTargetType addCompatibleDistributionSetType(final DistributionSetType dsSetType) {
if (distributionSetTypes == null) {
distributionSetTypes = new HashSet<>();
}
distributionSetTypes.add(dsSetType);
return this;
}
@Override
public Set<DistributionSetType> getCompatibleDistributionSetTypes() {
if (distributionSetTypes == null) {
return Collections.emptySet();
}
return Collections.unmodifiableSet(distributionSetTypes);
}
@@ -98,15 +89,10 @@ public class JpaTargetType extends AbstractJpaTypeEntity implements TargetType,
* @return Target type
*/
public JpaTargetType removeDistributionSetType(final Long dsTypeId) {
if (distributionSetTypes == null) {
return this;
}
distributionSetTypes.stream()
.filter(element -> element.getId().equals(dsTypeId))
.findAny()
.ifPresent(distributionSetTypes::remove);
return this;
}

View File

@@ -19,6 +19,10 @@ import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.event.remote.TenantConfigurationDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TenantConfigurationCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TenantConfigurationUpdatedEvent;
@@ -28,6 +32,9 @@ import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
/**
* A JPA entity which stores the tenant specific configuration.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Setter
@Getter
@Entity
@Table(name = "sp_tenant_configuration", uniqueConstraints = @UniqueConstraint(columnNames = { "conf_key",
"tenant" }, name = "uk_tenant_key"))
@@ -49,39 +56,9 @@ public class JpaTenantConfiguration extends AbstractJpaTenantAwareBaseEntity imp
@NotNull
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;
}
public void setKey(final String key) {
this.key = key;
}
@Override
public String getValue() {
return value;
}
public void setValue(final String value) {
this.value = value;
}
@Override
@@ -102,4 +79,4 @@ public class JpaTenantConfiguration extends AbstractJpaTenantAwareBaseEntity imp
.publishEvent(new TenantConfigurationDeletedEvent(getTenant(), getId(), getKey(), getValue(),
getClass(), EventPublisherHolder.getInstance().getApplicationId()));
}
}
}

View File

@@ -25,6 +25,10 @@ import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
import org.eclipse.hawkbit.repository.model.TenantMetaData;
@@ -36,6 +40,9 @@ import org.eclipse.hawkbit.repository.model.TenantMetaData;
*
* Entities owned by the tenant are based on {@link TenantAwareBaseEntity}.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Setter
@Getter
@Table(name = "sp_tenant", indexes = {
@Index(name = "sp_idx_tenant_prim", columnList = "tenant,id") }, uniqueConstraints = {
@UniqueConstraint(columnNames = { "tenant" }, name = "uk_tenantmd_tenant") })
@@ -56,39 +63,8 @@ public class JpaTenantMetaData extends AbstractJpaBaseEntity implements TenantMe
@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) {
this.defaultDsType = (JpaDistributionSetType) defaultDsType;
this.tenant = tenant;
}
@Override
public DistributionSetType getDefaultDsType() {
return defaultDsType;
}
public void setDefaultDsType(final JpaDistributionSetType defaultDsType) {
this.defaultDsType = defaultDsType;
}
@Override
public String getTenant() {
return tenant;
}
public void setTenant(final String tenant) {
this.tenant = tenant;
}
}
}

View File

@@ -34,7 +34,7 @@ import org.eclipse.hawkbit.repository.model.Target;
/**
* Entity with JPA annotation to store the information which {@link Target} is in a specific {@link RolloutGroup}.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // JPA constructor
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@IdClass(RolloutTargetGroupId.class)
@Entity
@Table(name = "sp_rollouttargetgroup")

View File

@@ -12,12 +12,17 @@ package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serial;
import java.io.Serializable;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.Target;
/**
* Combined unique key of the table {@link RolloutTargetGroup}.
*/
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Getter
public class RolloutTargetGroupId implements Serializable {
@Serial
@@ -26,13 +31,6 @@ public class RolloutTargetGroupId implements Serializable {
private Long rolloutGroup;
private Long target;
/**
* default constructor necessary for JPA.
*/
public RolloutTargetGroupId() {
// default constructor necessary for JPA, empty.
}
/**
* Constructor.
*
@@ -43,12 +41,4 @@ public class RolloutTargetGroupId implements Serializable {
this.rolloutGroup = rolloutGroup.getId();
this.target = target.getId();
}
public Long getRolloutGroup() {
return rolloutGroup;
}
public Long getTarget() {
return target;
}
}
}

View File

@@ -12,13 +12,15 @@ package org.eclipse.hawkbit.repository.jpa.model;
import java.io.Serial;
import java.io.Serializable;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* The Software Module meta-data composite key which contains the meta-data key
* and the ID of the software module itself.
* The Software Module meta-data composite key which contains the meta-data key and the ID of the software module itself.
*/
@NoArgsConstructor // Default constructor for JPA
@NoArgsConstructor(access = AccessLevel.PUBLIC) // Default constructor for JPA
@Data
public final class SwMetadataCompositeKey implements Serializable {
@Serial
@@ -35,72 +37,4 @@ public final class SwMetadataCompositeKey implements Serializable {
this.softwareModule = moduleId;
this.key = key;
}
/**
* @return the key
*/
public String getKey() {
return key;
}
/**
* @param key the key to set
*/
public void setKey(final String key) {
this.key = key;
}
/**
* @return the softwareModule
*/
public Long getSoftwareModule() {
return softwareModule;
}
/**
* @param softwareModule the softwareModule to set
*/
public void setSoftwareModule(final Long softwareModule) {
this.softwareModule = softwareModule;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (key == null ? 0 : key.hashCode());
result = prime * result + (softwareModule == null ? 0 : softwareModule.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final SwMetadataCompositeKey other = (SwMetadataCompositeKey) obj;
if (key == null) {
if (other.key != null) {
return false;
}
} else if (!key.equals(other.key)) {
return false;
}
if (softwareModule == null) {
if (other.softwareModule != null) {
return false;
}
} else if (!softwareModule.equals(other.softwareModule)) {
return false;
}
return true;
}
}
}

View File

@@ -13,12 +13,14 @@ import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* The Target Metadata composite key which contains the meta-data key and the ID of the Target itself.
*/
@NoArgsConstructor // Default constructor for JPA
@Data
public final class TargetMetadataCompositeKey implements Serializable {
@Serial
@@ -35,54 +37,4 @@ public final class TargetMetadataCompositeKey implements Serializable {
this.target = target;
this.key = key;
}
public String getKey() {
return key;
}
public void setKey(final String key) {
this.key = key;
}
public Long getTargetId() {
return target;
}
public void setTargetId(final Long target) {
this.target = target;
}
@Override
public int hashCode() {
return Objects.hash(target, key);
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TargetMetadataCompositeKey other = (TargetMetadataCompositeKey) obj;
if (target == null) {
if (other.target != null) {
return false;
}
} else if (!target.equals(other.target)) {
return false;
}
if (key == null) {
if (other.key != null) {
return false;
}
} else if (!key.equals(other.key)) {
return false;
}
return true;
}
}
}

View File

@@ -312,8 +312,11 @@ public class TestdataFactory {
.description(randomDescriptionLong()).vendor(prefix + " vendor Limited Inc, California"));
return distributionSetManagement.create(
entityFactory.distributionSet().create().name(prefix != null && prefix.length() > 0 ? prefix : "DS")
.version(version).description(randomDescriptionShort()).type(findOrCreateDefaultTestDsType())
entityFactory.distributionSet().create()
.type(findOrCreateDefaultTestDsType())
.name(prefix == null || prefix.isEmpty() ? "DS" : prefix)
.version(version)
.description(randomDescriptionShort())
.modules(Arrays.asList(osMod.getId(), runtimeMod.getId(), appMod.getId()))
.requiredMigrationStep(isRequiredMigrationStep));
}