From 5f1db53defb244763315731257b1a9d85cfec6c1 Mon Sep 17 00:00:00 2001 From: GAH6KOR Date: Thu, 21 Jul 2016 12:39:54 +0200 Subject: [PATCH] Removed the extra level of abstraction and modified the code accordingly. --- .../AbstractDescriptorEventVisitorImpl.java | 189 ----- .../jpa/model/AbstractJpaBaseEntity.java | 6 +- .../repository/jpa/model/AcceptVisitor.java | 18 - .../model/EntityPropertyChangeListener.java | 31 +- ...ventVisitor.java => EventAwareEntity.java} | 17 +- .../repository/jpa/model/JpaAction.java | 373 +++++----- .../jpa/model/JpaDistributionSet.java | 602 ++++++++-------- .../repository/jpa/model/JpaRollout.java | 423 +++++------ .../repository/jpa/model/JpaRolloutGroup.java | 500 ++++++------- .../repository/jpa/model/JpaTarget.java | 491 +++++++------ .../repository/jpa/model/JpaTargetInfo.java | 668 +++++++++--------- .../helper/EntityPropertyChangeHelper.java | 42 ++ 12 files changed, 1673 insertions(+), 1687 deletions(-) delete mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractDescriptorEventVisitorImpl.java delete mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AcceptVisitor.java rename hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/{AbstractDescriptorEventVisitor.java => EventAwareEntity.java} (53%) create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractDescriptorEventVisitorImpl.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractDescriptorEventVisitorImpl.java deleted file mode 100644 index 8755f8051..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractDescriptorEventVisitorImpl.java +++ /dev/null @@ -1,189 +0,0 @@ -/** - * 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.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.stream.Collectors; - -import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent; -import org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent; -import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent; -import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent; -import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent; -import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent; -import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent; -import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent; -import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent; -import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent; -import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; -import org.eclipse.hawkbit.repository.jpa.model.DescriptorEventDetails.ActionType; -import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; -import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder; -import org.eclipse.hawkbit.repository.model.Action; -import org.eclipse.hawkbit.repository.model.Rollout; -import org.eclipse.hawkbit.repository.model.RolloutGroup; -import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; -import org.eclipse.persistence.descriptors.DescriptorEvent; -import org.eclipse.persistence.internal.sessions.ObjectChangeSet; -import org.eclipse.persistence.queries.UpdateObjectQuery; -import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.eventbus.EventBus; - -/** - * Implementation of @link{AbstractDescriptorEventVisitor} .Publishes the - * appropriate event after any action on entity like create/update. - * - */ -public class AbstractDescriptorEventVisitorImpl implements - AbstractDescriptorEventVisitor { - - private static final String COMPLETE = "complete"; - private static final Logger LOG = LoggerFactory - .getLogger(AbstractDescriptorEventVisitorImpl.class); - - @Override - public void publishEventPostAction(final DescriptorEventDetails event) { - Method method = null; - DescriptorEvent descriptorEvent = event.getDescriptorEvent(); - ActionType actiontype = event.getActiontype(); - try { - method = getMethod(descriptorEvent, actiontype); - if (method != null) { - method.invoke(this, descriptorEvent.getObject(), - descriptorEvent); - } - } catch (NoSuchMethodException | SecurityException - | IllegalAccessException | IllegalArgumentException - | InvocationTargetException e) { - LOG.info( - "Exception when invoking approriate method to publis event {}", - e); - } - } - - private Method getMethod(DescriptorEvent descriptorEvent, - ActionType actiontype) throws NoSuchMethodException { - if (actiontype == ActionType.UPDATE) { - return this.getClass().getMethod("publishEventAfterUpdate", - descriptorEvent.getObject().getClass(), - DescriptorEvent.class); - } else if (actiontype == ActionType.CREATE) { - return this.getClass().getMethod("publishEventAfterCreate", - descriptorEvent.getObject().getClass(), - DescriptorEvent.class); - } - return null; - } - - public void publishEventAfterCreate(JpaAction action, DescriptorEvent event) { - if (action.getRollout() != null) { - getAfterTransactionCommmitExecutor().afterCommit( - () -> getEventBus().post(new ActionCreatedEvent(action))); - } - } - - public void publishEventAfterCreate(JpaTarget target, DescriptorEvent event) { - getAfterTransactionCommmitExecutor().afterCommit( - () -> getEventBus().post(new TargetCreatedEvent(target))); - } - - public void publishEventAfterCreate(JpaDistributionSet ds, - DescriptorEvent event) { - getAfterTransactionCommmitExecutor().afterCommit( - () -> getEventBus().post(new DistributionCreatedEvent(ds))); - - } - - public void publishEventAfterUpdate(JpaAction action, DescriptorEvent event) { - getAfterTransactionCommmitExecutor().afterCommit( - () -> getEventBus().post( - new ActionPropertyChangeEvent(action, getChangeSet( - Action.class, event)))); - } - - public void publishEventAfterUpdate(JpaTarget target, DescriptorEvent event) { - getAfterTransactionCommmitExecutor().afterCommit( - () -> getEventBus().post(new TargetUpdatedEvent(target))); - } - - public void publishEventAfterUpdate(JpaTargetInfo targetInfo, - DescriptorEvent event) { - getAfterTransactionCommmitExecutor() - .afterCommit( - () -> getEventBus().post( - new TargetInfoUpdateEvent(targetInfo))); - } - - public void publishEventAfterUpdate(JpaRollout entity, DescriptorEvent event) { - getAfterTransactionCommmitExecutor().afterCommit( - () -> getEventBus().post( - new RolloutPropertyChangeEvent(entity, getChangeSet( - Rollout.class, event)))); - } - - public void publishEventAfterUpdate(JpaRolloutGroup entity, - DescriptorEvent event) { - getAfterTransactionCommmitExecutor().afterCommit( - () -> getEventBus().post( - new RolloutGroupPropertyChangeEvent(entity, - getChangeSet(RolloutGroup.class, event)))); - - } - - public void publishEventAfterUpdate(JpaDistributionSet entity, - DescriptorEvent event) { - Map.Values> changeSet = getChangeSet( - JpaDistributionSet.class, event); - if (changeSet.containsKey(COMPLETE) - && changeSet.get(COMPLETE).getOldValue().equals(false) - && changeSet.get(COMPLETE).getNewValue().equals(true)) { - getAfterTransactionCommmitExecutor().afterCommit( - () -> getEventBus().post( - new DistributionCreatedEvent(entity))); - } - - getAfterTransactionCommmitExecutor().afterCommit( - () -> getEventBus() - .post(new DistributionSetUpdateEvent(entity))); - - } - - private Map.Values> getChangeSet( - final Class clazz, final DescriptorEvent event) { - final T rolloutGroup = clazz.cast(event.getObject()); - final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()) - .getObjectChangeSet(); - return changeSet - .getChanges() - .stream() - .filter(record -> record instanceof DirectToFieldChangeRecord) - .map(record -> (DirectToFieldChangeRecord) record) - .collect( - Collectors.toMap( - record -> record.getAttribute(), - record -> new AbstractPropertyChangeEvent( - rolloutGroup, null).new Values(record - .getOldValue(), record.getNewValue()))); - } - - private AfterTransactionCommitExecutor getAfterTransactionCommmitExecutor() { - return AfterTransactionCommitExecutorHolder.getInstance() - .getAfterCommit(); - } - - private EventBus getEventBus() { - return EventBusHolder.getInstance().getEventBus(); - } - -} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java index 2785676fb..c2e91afea 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java @@ -32,7 +32,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; @MappedSuperclass @Access(AccessType.FIELD) @EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class }) -public abstract class AbstractJpaBaseEntity implements BaseEntity,AcceptVisitor { +public abstract class AbstractJpaBaseEntity implements BaseEntity { private static final long serialVersionUID = 1L; @Id @@ -179,8 +179,4 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity,AcceptVisitor } - @Override - public void postActionOnEntity(AbstractDescriptorEventVisitor visitor, DescriptorEventDetails eventDetails){ - visitor.publishEventPostAction(eventDetails); - } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AcceptVisitor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AcceptVisitor.java deleted file mode 100644 index 78d89219b..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AcceptVisitor.java +++ /dev/null @@ -1,18 +0,0 @@ -/** - * 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; - -/** - * Interface to accept visitor @link{AbstractDescriptorEventVisitor}. - * - */ -public interface AcceptVisitor { - public void postActionOnEntity(AbstractDescriptorEventVisitor visitor, - DescriptorEventDetails eventDetails); -} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java index bdb366edb..df36309df 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.repository.jpa.model; -import org.eclipse.hawkbit.repository.jpa.model.DescriptorEventDetails.ActionType; import org.eclipse.persistence.descriptors.DescriptorEvent; import org.eclipse.persistence.descriptors.DescriptorEventAdapter; @@ -18,19 +17,23 @@ import org.eclipse.persistence.descriptors.DescriptorEventAdapter; */ public class EntityPropertyChangeListener extends DescriptorEventAdapter { - @Override - public void postInsert(final DescriptorEvent event) { - AbstractDescriptorEventVisitor visitor = new AbstractDescriptorEventVisitorImpl(); - ((AbstractJpaBaseEntity) event.getObject()).postActionOnEntity(visitor, - new DescriptorEventDetails(ActionType.CREATE, event)); + @Override + public void postInsert(final DescriptorEvent event) { + + final Object object = event.getObject(); + if (object instanceof EventAwareEntity) { + ((EventAwareEntity) object).fireCreateEvent(object,event); + } + } + + @Override + public void postUpdate(final DescriptorEvent event) { + + final Object object = event.getObject(); + if (object instanceof EventAwareEntity) { + ((EventAwareEntity) object).fireUpdateEvent(object,event); + } + } - } - @Override - public void postUpdate(final DescriptorEvent event) { - AbstractDescriptorEventVisitor visitor = new AbstractDescriptorEventVisitorImpl(); - ((AbstractJpaBaseEntity) event.getObject()).postActionOnEntity(visitor, - new DescriptorEventDetails(ActionType.UPDATE, event)); - } - } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractDescriptorEventVisitor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EventAwareEntity.java similarity index 53% rename from hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractDescriptorEventVisitor.java rename to hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EventAwareEntity.java index ce32b025f..2c1fe51d2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractDescriptorEventVisitor.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EventAwareEntity.java @@ -8,12 +8,13 @@ */ package org.eclipse.hawkbit.repository.jpa.model; -/** - * - * Interface defining the action to be performed after entity is - * created/updated. - * - */ -public interface AbstractDescriptorEventVisitor { - void publishEventPostAction(DescriptorEventDetails eventDetails); +import org.eclipse.persistence.descriptors.DescriptorEvent; + +public interface EventAwareEntity { + + public void fireCreateEvent(T t,DescriptorEvent descriptorEvent); + + public void fireUpdateEvent(T t,DescriptorEvent descriptorEvent); + + public void fireDeleteEvent(T t,DescriptorEvent descriptorEvent); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java index 5fa2c3bed..fc879aa87 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java @@ -1,174 +1,199 @@ -/** - * 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 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.Target; -import org.eclipse.persistence.annotations.CascadeOnDelete; - -/** - * JPA implementation of {@link Action}. - */ -@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 -// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for -// sub entities -@SuppressWarnings("squid:S2160") -public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action { - private static final long serialVersionUID = 1L; - - @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; - - @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; - - @Override - public DistributionSet getDistributionSet() { - return distributionSet; - } - - @Override - public void setDistributionSet(final DistributionSet distributionSet) { - this.distributionSet = (JpaDistributionSet) distributionSet; - } - - 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 boolean isActive() { - return active; - } - - public void setActionType(final ActionType actionType) { - this.actionType = actionType; - } - - @Override - public ActionType getActionType() { - return actionType; - } - - @Override - public List 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; - } - - public void setForcedTime(final long forcedTime) { - this.forcedTime = forcedTime; - } - - @Override - public RolloutGroup getRolloutGroup() { - return rolloutGroup; - } - - public void setRolloutGroup(final RolloutGroup rolloutGroup) { - this.rolloutGroup = (JpaRolloutGroup) rolloutGroup; - } - - @Override - public Rollout getRollout() { - return rollout; - } - - public void setRollout(final Rollout rollout) { - this.rollout = (JpaRollout) rollout; - } - - @Override - public String toString() { - return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]"; - } - -} +/** + * 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 org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent; +import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent; +import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper; +import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder; +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.Target; +import org.eclipse.persistence.annotations.CascadeOnDelete; +import org.eclipse.persistence.descriptors.DescriptorEvent; + +/** + * JPA implementation of {@link Action}. + */ +@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 +// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for +// sub entities +@SuppressWarnings("squid:S2160") +public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action,EventAwareEntity { + private static final long serialVersionUID = 1L; + + @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; + + @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; + + @Override + public DistributionSet getDistributionSet() { + return distributionSet; + } + + @Override + public void setDistributionSet(final DistributionSet distributionSet) { + this.distributionSet = (JpaDistributionSet) distributionSet; + } + + 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 boolean isActive() { + return active; + } + + public void setActionType(final ActionType actionType) { + this.actionType = actionType; + } + + @Override + public ActionType getActionType() { + return actionType; + } + + @Override + public List 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; + } + + public void setForcedTime(final long forcedTime) { + this.forcedTime = forcedTime; + } + + @Override + public RolloutGroup getRolloutGroup() { + return rolloutGroup; + } + + public void setRolloutGroup(final RolloutGroup rolloutGroup) { + this.rolloutGroup = (JpaRolloutGroup) rolloutGroup; + } + + @Override + public Rollout getRollout() { + return rollout; + } + + public void setRollout(final Rollout rollout) { + this.rollout = (JpaRollout) rollout; + } + + @Override + public String toString() { + return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]"; + } + + @Override + public void fireCreateEvent(final JpaAction jpaAction, final DescriptorEvent descriptorEvent) { + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () ->EventBusHolder.getInstance().getEventBus().post(new ActionCreatedEvent(jpaAction))); + + } + + @Override + public void fireUpdateEvent(final JpaAction jpaAction, final DescriptorEvent descriptorEvent) { + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () ->EventBusHolder.getInstance().getEventBus(). + post(new ActionPropertyChangeEvent(jpaAction, EntityPropertyChangeHelper.getChangeSet(Action.class, descriptorEvent)))); + + } + + + @Override + public void fireDeleteEvent(final JpaAction jpaAction, final DescriptorEvent descriptorEvent) { + + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java index 676215424..af8984286 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java @@ -1,282 +1,320 @@ -/** - * 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.Collection; -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.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; - -/** - * Jpa implementation of {@link DistributionSet}. - * - */ -@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") }) -// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for -// sub entities -@SuppressWarnings("squid:S2160") -public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet { - private static final long serialVersionUID = 1L; - - @Column(name = "required_migration_step") - private boolean requiredMigrationStep; - - @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 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 tags = new HashSet<>(); - - @Column(name = "deleted") - private boolean deleted; - - @OneToMany(mappedBy = "assignedDistributionSet", targetEntity = JpaTarget.class, fetch = FetchType.LAZY) - private List assignedToTargets; - - @OneToMany(mappedBy = "installedDistributionSet", targetEntity = JpaTargetInfo.class, fetch = FetchType.LAZY) - private List installedAtTargets; - - @OneToMany(mappedBy = "distributionSet", targetEntity = JpaAction.class, fetch = FetchType.LAZY) - private List actions; - - @CascadeOnDelete - @OneToMany(fetch = FetchType.LAZY, targetEntity = JpaDistributionSetMetadata.class, cascade = { - CascadeType.REMOVE }) - @JoinColumn(name = "ds_id", insertable = false, updatable = false) - private final List 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; - - /** - * 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 Collection 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 getTags() { - return tags; - } - - @Override - public boolean isDeleted() { - return deleted; - } - - @Override - public List getMetadata() { - return Collections.unmodifiableList(metadata); - } - - public List 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; - } - - public DistributionSet setTags(final Set tags) { - this.tags = tags; - return this; - } - - @Override - public List getAssignedTargets() { - return assignedToTargets; - } - - @Override - public List getInstalledTargets() { - return installedAtTargets; - } - - @Override - public String toString() { - return "DistributionSet [getName()=" + getName() + ", getOptLockRevision()=" + getOptLockRevision() - + ", getId()=" + getId() + "]"; - } - - @Override - public Set getModules() { - return Collections.unmodifiableSet(modules); - } - - @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 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 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; - } - - @Override - public boolean removeModule(final SoftwareModule softwareModule) { - final Optional 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; - - } - - @Override - public SoftwareModule findFirstModuleByType(final SoftwareModuleType type) { - final Optional 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; - } - -} +/** + * 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.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +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.eventbus.event.AbstractPropertyChangeEvent; +import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent; +import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent; +import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException; +import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException; +import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper; +import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder; +import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.DistributionSet; +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; +import org.eclipse.persistence.descriptors.DescriptorEvent; + +/** + * Jpa implementation of {@link DistributionSet}. + * + */ +@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") }) +// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for +// sub entities +@SuppressWarnings("squid:S2160") +public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet,EventAwareEntity { + private static final long serialVersionUID = 1L; + + private static final String COMPLETE = "complete"; + + @Column(name = "required_migration_step") + private boolean requiredMigrationStep; + + @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 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 tags = new HashSet<>(); + + @Column(name = "deleted") + private boolean deleted; + + @OneToMany(mappedBy = "assignedDistributionSet", targetEntity = JpaTarget.class, fetch = FetchType.LAZY) + private List assignedToTargets; + + @OneToMany(mappedBy = "installedDistributionSet", targetEntity = JpaTargetInfo.class, fetch = FetchType.LAZY) + private List installedAtTargets; + + @OneToMany(mappedBy = "distributionSet", targetEntity = JpaAction.class, fetch = FetchType.LAZY) + private List actions; + + @CascadeOnDelete + @OneToMany(fetch = FetchType.LAZY, targetEntity = JpaDistributionSetMetadata.class, cascade = { + CascadeType.REMOVE }) + @JoinColumn(name = "ds_id", insertable = false, updatable = false) + private final List 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; + + /** + * 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 Collection 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 getTags() { + return tags; + } + + @Override + public boolean isDeleted() { + return deleted; + } + + @Override + public List getMetadata() { + return Collections.unmodifiableList(metadata); + } + + public List 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; + } + + public DistributionSet setTags(final Set tags) { + this.tags = tags; + return this; + } + + @Override + public List getAssignedTargets() { + return assignedToTargets; + } + + @Override + public List getInstalledTargets() { + return installedAtTargets; + } + + @Override + public String toString() { + return "DistributionSet [getName()=" + getName() + ", getOptLockRevision()=" + getOptLockRevision() + + ", getId()=" + getId() + "]"; + } + + @Override + public Set getModules() { + return Collections.unmodifiableSet(modules); + } + + @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 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 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; + } + + @Override + public boolean removeModule(final SoftwareModule softwareModule) { + final Optional 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; + + } + + @Override + public SoftwareModule findFirstModuleByType(final SoftwareModuleType type) { + final Optional 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; + } + + @Override + public void fireCreateEvent(final JpaDistributionSet jpaDistributionSet, final DescriptorEvent descriptorEvent) { + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () -> EventBusHolder.getInstance().getEventBus().post(new DistributionCreatedEvent(jpaDistributionSet))); + + } + + @Override + public void fireUpdateEvent(final JpaDistributionSet jpaDistributionSet, final DescriptorEvent descriptorEvent) { + final Map.Values> changeSet = EntityPropertyChangeHelper.getChangeSet( + JpaDistributionSet.class, descriptorEvent); + if (changeSet.containsKey(COMPLETE) + && changeSet.get(COMPLETE).getOldValue().equals(false) + && changeSet.get(COMPLETE).getNewValue().equals(true)) { + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( + () -> EventBusHolder.getInstance().getEventBus().post( + new DistributionCreatedEvent(jpaDistributionSet))); + } + + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( + () -> EventBusHolder.getInstance().getEventBus().post(new DistributionSetUpdateEvent(jpaDistributionSet))); + + } + + @Override + public void fireDeleteEvent(final JpaDistributionSet jpaDistributionSet, final DescriptorEvent descriptorEvent) { + + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java index 3cbe65717..73d19086d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java @@ -1,200 +1,223 @@ -/** - * 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.repository.jpa.cache.CacheField; -import org.eclipse.hawkbit.repository.jpa.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; - -/** - * JPA implementation of a {@link Rollout}. - * - */ -@Entity -@Table(name = "sp_rollout", indexes = { - @Index(name = "sp_idx_rollout_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = { - "name", "tenant" }, name = "uk_rollout")) -// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for -// sub entities -@SuppressWarnings("squid:S2160") -public class JpaRollout extends AbstractJpaNamedEntity 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 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; - - @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; - - @Transient - @CacheField(key = CacheKeys.ROLLOUT_GROUP_CREATED) - private int rolloutGroupsCreated; - - @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 getRolloutGroups() { - return rolloutGroups; - } - - public void setRolloutGroups(final List 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; - } - - public void setStatus(final RolloutStatus status) { - this.status = status; - } - - public long getLastCheck() { - return lastCheck; - } - - 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; - } - - public void setTotalTargets(final long totalTargets) { - this.totalTargets = totalTargets; - } - - public int getRolloutGroupsTotal() { - return rolloutGroupsTotal; - } - - public void setRolloutGroupsTotal(final int rolloutGroupsTotal) { - this.rolloutGroupsTotal = rolloutGroupsTotal; - } - - @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); - } - return totalTargetCountStatus; - } - - 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() + "]"; - } - -} +/** + * 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.repository.eventbus.event.RolloutPropertyChangeEvent; +import org.eclipse.hawkbit.repository.jpa.cache.CacheField; +import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys; +import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper; +import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder; +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; +import org.eclipse.persistence.descriptors.DescriptorEvent; + +/** + * JPA implementation of a {@link Rollout}. + * + */ +@Entity +@Table(name = "sp_rollout", indexes = { + @Index(name = "sp_idx_rollout_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = { + "name", "tenant" }, name = "uk_rollout")) +// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for +// sub entities +@SuppressWarnings("squid:S2160") +public class JpaRollout extends AbstractJpaNamedEntity implements Rollout,EventAwareEntity { + + 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 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; + + @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; + + @Transient + @CacheField(key = CacheKeys.ROLLOUT_GROUP_CREATED) + private int rolloutGroupsCreated; + + @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 getRolloutGroups() { + return rolloutGroups; + } + + public void setRolloutGroups(final List 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; + } + + public void setStatus(final RolloutStatus status) { + this.status = status; + } + + public long getLastCheck() { + return lastCheck; + } + + 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; + } + + public void setTotalTargets(final long totalTargets) { + this.totalTargets = totalTargets; + } + + public int getRolloutGroupsTotal() { + return rolloutGroupsTotal; + } + + public void setRolloutGroupsTotal(final int rolloutGroupsTotal) { + this.rolloutGroupsTotal = rolloutGroupsTotal; + } + + @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); + } + return totalTargetCountStatus; + } + + 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() + "]"; + } + + @Override + public void fireCreateEvent(final JpaRollout jpaRollout, final DescriptorEvent descriptorEvent) { + + } + + @Override + public void fireUpdateEvent(final JpaRollout jpaRollout, final DescriptorEvent descriptorEvent) { + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> EventBusHolder.getInstance().getEventBus(). + post(new RolloutPropertyChangeEvent(jpaRollout, EntityPropertyChangeHelper.getChangeSet( + Rollout.class, descriptorEvent)))); + + } + + @Override + public void fireDeleteEvent(final JpaRollout jpaRollout, final DescriptorEvent descriptorEvent) { + + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java index 79da6630a..6456a3e93 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java @@ -1,239 +1,261 @@ -/** - * 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. - * - */ -@Entity -@Table(name = "sp_rolloutgroup", indexes = { - @Index(name = "sp_idx_rolloutgroup_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = { - "name", "rollout", "tenant" }, name = "uk_rolloutgroup")) -// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for -// sub entities -@SuppressWarnings("squid:S2160") -public class JpaRolloutGroup extends AbstractJpaNamedEntity 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 = 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; - - @Column(name = "success_action", nullable = false) - private RolloutGroupSuccessAction successAction = RolloutGroupSuccessAction.NEXTGROUP; - - @Column(name = "success_action_exp", length = 512, nullable = false) - private String successActionExp; - - @Column(name = "error_condition") - private RolloutGroupErrorCondition errorCondition; - - @Column(name = "error_condition_exp", length = 512) - private String errorConditionExp; - - @Column(name = "error_action") - private RolloutGroupErrorAction errorAction; - - @Column(name = "error_action_exp", length = 512) - private String errorActionExp; - - @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 getRolloutTargetGroup() { - return rolloutTargetGroup; - } - - @Override - public RolloutGroup getParent() { - return parent; - } - - 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; - } - - public void setTotalTargets(final long totalTargets) { - this.totalTargets = totalTargets; - } - - public void setSuccessAction(final RolloutGroupSuccessAction successAction) { - this.successAction = successAction; - } - - 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() + "]"; - } - -} +/** + * 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.eventbus.event.RolloutGroupPropertyChangeEvent; +import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper; +import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder; +import org.eclipse.hawkbit.repository.model.Rollout; +import org.eclipse.hawkbit.repository.model.RolloutGroup; +import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; +import org.eclipse.persistence.descriptors.DescriptorEvent; + +/** + * JPA entity definition of persisting a group of an rollout. + * + */ +@Entity +@Table(name = "sp_rolloutgroup", indexes = { + @Index(name = "sp_idx_rolloutgroup_01", columnList = "tenant,name") }, uniqueConstraints = @UniqueConstraint(columnNames = { + "name", "rollout", "tenant" }, name = "uk_rolloutgroup")) +// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for +// sub entities +@SuppressWarnings("squid:S2160") +public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup,EventAwareEntity { + + 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 = 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; + + @Column(name = "success_action", nullable = false) + private RolloutGroupSuccessAction successAction = RolloutGroupSuccessAction.NEXTGROUP; + + @Column(name = "success_action_exp", length = 512, nullable = false) + private String successActionExp; + + @Column(name = "error_condition") + private RolloutGroupErrorCondition errorCondition; + + @Column(name = "error_condition_exp", length = 512) + private String errorConditionExp; + + @Column(name = "error_action") + private RolloutGroupErrorAction errorAction; + + @Column(name = "error_action_exp", length = 512) + private String errorActionExp; + + @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 getRolloutTargetGroup() { + return rolloutTargetGroup; + } + + @Override + public RolloutGroup getParent() { + return parent; + } + + 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; + } + + public void setTotalTargets(final long totalTargets) { + this.totalTargets = totalTargets; + } + + public void setSuccessAction(final RolloutGroupSuccessAction successAction) { + this.successAction = successAction; + } + + 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() + "]"; + } + + @Override + public void fireCreateEvent(final JpaRolloutGroup jpaRolloutGroup, final DescriptorEvent descriptorEvent) { + + } + + @Override + public void fireUpdateEvent(final JpaRolloutGroup jpaRolloutGroup, final DescriptorEvent descriptorEvent) { + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> EventBusHolder.getInstance().getEventBus(). + post(new RolloutGroupPropertyChangeEvent(jpaRolloutGroup, + EntityPropertyChangeHelper.getChangeSet(RolloutGroup.class, descriptorEvent)))); + } + + @Override + public void fireDeleteEvent(final JpaRolloutGroup jpaRolloutGroup, final DescriptorEvent descriptorEvent) { + + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java index 183405470..f6a2b8346 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java @@ -1,234 +1,257 @@ -/** - * 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.jpa.model.helper.SecurityChecker; -import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder; -import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder; -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.TargetInfo; -import org.eclipse.hawkbit.repository.model.TargetTag; -import org.eclipse.persistence.annotations.CascadeOnDelete; -import org.springframework.data.domain.Persistable; - -/** - * JPA implementation of {@link Target}. - * - */ -@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") }) -// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for -// sub entities -@SuppressWarnings("squid:S2160") -public class JpaTarget extends AbstractJpaNamedEntity implements Persistable, Target { - private static final long serialVersionUID = 1L; - - @Column(name = "controller_id", length = 64) - @Size(min = 1) - @NotNull - private String controllerId; - - @Transient - private boolean entityNew; - - @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 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 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; - - /** - * 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; - - @CascadeOnDelete - @OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.REMOVE, CascadeType.PERSIST }) - @JoinColumn(name = "target_Id", insertable = false, updatable = false) - private final List rolloutTargetGroup = new ArrayList<>(); - - /** - * Constructor. - * - * @param controllerId - * controller ID of the {@link Target} - */ - public JpaTarget(final String controllerId) { - this(controllerId, SecurityTokenGeneratorHolder.getInstance().generateToken()); - } - - /** - * Constructor. - * - * @param controllerId - * controller ID of the {@link Target} - * @param securityToken - * for target authentication if enabled - */ - public JpaTarget(final String controllerId, final String securityToken) { - this.controllerId = controllerId; - setName(controllerId); - this.securityToken = securityToken; - 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 getTags() { - return tags; - } - - public void setAssignedDistributionSet(final DistributionSet assignedDistributionSet) { - this.assignedDistributionSet = (JpaDistributionSet) assignedDistributionSet; - } - - public void setControllerId(final String controllerId) { - this.controllerId = controllerId; - } - - public void setTags(final Set tags) { - this.tags = tags; - } - - @Override - public List getActions() { - return actions; - } - - @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 - */ - public void setTargetInfo(final TargetInfo targetInfo) { - this.targetInfo = (JpaTargetInfo) targetInfo; - } - - /** - * @return the securityToken if the current security context contains the - * necessary permission {@link SpPermission#READ_TARGET_SEC_TOKEN} - * or the current context is executed as system code, otherwise - * {@code null}. - */ - @Override - public String getSecurityToken() { - if (SystemSecurityContextHolder.getInstance().getSystemSecurityContext().isCurrentThreadSystemCode() - || SecurityChecker.hasPermission(SpPermission.READ_TARGET_SEC_TOKEN)) { - return securityToken; - } - return null; - } - - /** - * @param securityToken - * the securityToken to set - */ - public void setSecurityToken(final String securityToken) { - this.securityToken = securityToken; - } - - @Override - public String toString() { - return "Target [controllerId=" + controllerId + ", getId()=" + getId() + "]"; - } - -} +/** + * 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.eventbus.event.TargetCreatedEvent; +import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent; +import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityChecker; +import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder; +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.TargetInfo; +import org.eclipse.hawkbit.repository.model.TargetTag; +import org.eclipse.persistence.annotations.CascadeOnDelete; +import org.eclipse.persistence.descriptors.DescriptorEvent; +import org.springframework.data.domain.Persistable; + +/** + * JPA implementation of {@link Target}. + * + */ +@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") }) +// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for +// sub entities +@SuppressWarnings("squid:S2160") +public class JpaTarget extends AbstractJpaNamedEntity implements Persistable, Target, EventAwareEntity { + private static final long serialVersionUID = 1L; + + @Column(name = "controller_id", length = 64) + @Size(min = 1) + @NotNull + private String controllerId; + + @Transient + private boolean entityNew; + + @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 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 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; + + /** + * 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; + + @CascadeOnDelete + @OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.REMOVE, CascadeType.PERSIST }) + @JoinColumn(name = "target_Id", insertable = false, updatable = false) + private final List rolloutTargetGroup = new ArrayList<>(); + + /** + * Constructor. + * + * @param controllerId + * controller ID of the {@link Target} + */ + public JpaTarget(final String controllerId) { + this(controllerId, SecurityTokenGeneratorHolder.getInstance().generateToken()); + } + + /** + * Constructor. + * + * @param controllerId + * controller ID of the {@link Target} + * @param securityToken + * for target authentication if enabled + */ + public JpaTarget(final String controllerId, final String securityToken) { + this.controllerId = controllerId; + setName(controllerId); + this.securityToken = securityToken; + 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 getTags() { + return tags; + } + + public void setAssignedDistributionSet(final DistributionSet assignedDistributionSet) { + this.assignedDistributionSet = (JpaDistributionSet) assignedDistributionSet; + } + + public void setControllerId(final String controllerId) { + this.controllerId = controllerId; + } + + public void setTags(final Set tags) { + this.tags = tags; + } + + @Override + public List getActions() { + return actions; + } + + @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 + */ + public void setTargetInfo(final TargetInfo targetInfo) { + this.targetInfo = (JpaTargetInfo) targetInfo; + } + + /** + * @return the securityToken if the current security context contains the + * necessary permission {@link SpPermission#READ_TARGET_SEC_TOKEN} + * or the current context is executed as system code, otherwise + * {@code null}. + */ + @Override + public String getSecurityToken() { + if (SystemSecurityContextHolder.getInstance().getSystemSecurityContext().isCurrentThreadSystemCode() + || 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() + "]"; + } + + @Override + public void fireCreateEvent(final JpaTarget jpaTarget, final DescriptorEvent descriptorEvent) { + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () ->EventBusHolder.getInstance().getEventBus().post(new TargetCreatedEvent(jpaTarget))); + } + + @Override + public void fireUpdateEvent(final JpaTarget jpaTarget,final DescriptorEvent descriptorEvent) { + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () -> EventBusHolder.getInstance().getEventBus().post(new TargetUpdatedEvent(jpaTarget))); + + } + + @Override + public void fireDeleteEvent(final JpaTarget jpaTarget, final DescriptorEvent descriptorEvent) { + + + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java index 0606def4f..a21c7547f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java @@ -1,324 +1,344 @@ -/** - * 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.exception.InvalidTargetAddressException; -import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder; -import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.PollStatus; -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.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, TargetInfo { - private static final long serialVersionUID = 1L; - - private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class); - - @Id - private Long targetId; - - @Transient - private boolean entityNew; - - @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; - - @Column(name = "last_target_query") - private Long lastTargetQuery; - - @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 controllerAttributes = Collections.synchronizedMap(new HashMap()); - - // 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 target address to set - * - * @throws IllegalArgumentException - * If the given string violates RFC 2396 - */ - @Override - public void setAddress(final String address) { - // check if this is a real URI - if (address != null) { - try { - URI.create(address); - } catch (final IllegalArgumentException e) { - throw new InvalidTargetAddressException( - "The given address " + address + " violates the RFC-2396 specification", e); - } - } - - 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 getControllerAttributes() { - return controllerAttributes; - } - - @Override - 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); - }); - } - - @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; - } -} +/** + * 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.EntityListeners; +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.eventbus.event.TargetInfoUpdateEvent; +import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException; +import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.PollStatus; +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.tenancy.configuration.DurationHelper; +import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; +import org.eclipse.persistence.annotations.CascadeOnDelete; +import org.eclipse.persistence.descriptors.DescriptorEvent; +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 +@EntityListeners(EntityPropertyChangeListener.class) +public class JpaTargetInfo implements Persistable, TargetInfo, EventAwareEntity { + private static final long serialVersionUID = 1L; + + private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class); + + @Id + private Long targetId; + + @Transient + private boolean entityNew; + + @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; + + @Column(name = "last_target_query") + private Long lastTargetQuery; + + @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 controllerAttributes = Collections.synchronizedMap(new HashMap()); + + // 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 target address to set + * + * @throws IllegalArgumentException + * If the given string violates RFC 2396 + */ + @Override + public void setAddress(final String address) { + // check if this is a real URI + if (address != null) { + try { + URI.create(address); + } catch (final IllegalArgumentException e) { + throw new InvalidTargetAddressException( + "The given address " + address + " violates the RFC-2396 specification", e); + } + } + + 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 getControllerAttributes() { + return controllerAttributes; + } + + @Override + 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); + }); + } + + @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; + } + + @Override + public void fireCreateEvent(final JpaTargetInfo jpaTargetInfo,final DescriptorEvent descriptorEvent) { + // there is no target info created event + } + + @Override + public void fireUpdateEvent(final JpaTargetInfo jpaTargetInfo, final DescriptorEvent descriptorEvent) { + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () -> EventBusHolder.getInstance().getEventBus().post(new TargetInfoUpdateEvent(jpaTargetInfo))); + } + + @Override + public void fireDeleteEvent(final JpaTargetInfo jpaTargetInfo, final DescriptorEvent descriptorEvent) { + } +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java new file mode 100644 index 000000000..71c374c5f --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java @@ -0,0 +1,42 @@ +/** + * 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.helper; + +import java.util.Map; +import java.util.stream.Collectors; + +import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent; +import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; +import org.eclipse.persistence.descriptors.DescriptorEvent; +import org.eclipse.persistence.internal.sessions.ObjectChangeSet; +import org.eclipse.persistence.queries.UpdateObjectQuery; +import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord; + +public class EntityPropertyChangeHelper { + + + public static Map.Values> getChangeSet( + final Class clazz, final DescriptorEvent event) { + final T rolloutGroup = clazz.cast(event.getObject()); + final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()) + .getObjectChangeSet(); + return changeSet + .getChanges() + .stream() + .filter(record -> record instanceof DirectToFieldChangeRecord) + .map(record -> (DirectToFieldChangeRecord) record) + .collect( + Collectors.toMap( + record -> record.getAttribute(), + record -> new AbstractPropertyChangeEvent( + rolloutGroup, null).new Values(record + .getOldValue(), record.getNewValue()))); + } + +}