diff --git a/account/src/main/java/de/muehlencord/shared/account/business/AbstractController.java b/account/src/main/java/de/muehlencord/shared/account/business/AbstractController.java index c169190..67373a5 100644 --- a/account/src/main/java/de/muehlencord/shared/account/business/AbstractController.java +++ b/account/src/main/java/de/muehlencord/shared/account/business/AbstractController.java @@ -74,12 +74,13 @@ public abstract class AbstractController { @TransactionAttribute(TransactionAttributeType.REQUIRED) @Transactional @Lock(LockType.WRITE) - public void create(T entity) throws ControllerException { + public T create(T entity) throws ControllerException { if (Updateable.class.isAssignableFrom(entity.getClass())) { Updateable updateable = (Updateable) entity; applyUpdateableChanges(updateable, true); } em.persist(entity); + return entity; } @TransactionAttribute(TransactionAttributeType.REQUIRED) diff --git a/account/src/main/java/de/muehlencord/shared/account/business/AbstractEnddateableController.java b/account/src/main/java/de/muehlencord/shared/account/business/AbstractEnddateableController.java new file mode 100644 index 0000000..8e0935e --- /dev/null +++ b/account/src/main/java/de/muehlencord/shared/account/business/AbstractEnddateableController.java @@ -0,0 +1,106 @@ +/* + * Copyright 2019 Joern Muehlencord . + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.muehlencord.shared.account.business; + +import de.muehlencord.shared.account.util.EndDateable; +import de.muehlencord.shared.account.util.Updateable; +import de.muehlencord.shared.util.DateUtil; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import javax.ejb.Lock; +import javax.ejb.LockType; +import javax.ejb.TransactionAttribute; +import javax.ejb.TransactionAttributeType; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.transaction.Transactional; + +/** + * + * @author Joern Muehlencord + * @param an entity which needs to extend EndDateable + */ +public abstract class AbstractEnddateableController> extends AbstractController { + + private final Class endDateableClass; + + public AbstractEnddateableController(Class clazz) { + super(clazz); + this.endDateableClass = clazz; + } + + @TransactionAttribute(TransactionAttributeType.REQUIRED) + @Transactional + @Lock(LockType.WRITE) + @Override + public void delete(T entity) throws ControllerException { + T entityToUpdate = attach(entity); + if (Updateable.class.isAssignableFrom(entityToUpdate.getClass())) { + Updateable updateable = (Updateable) entityToUpdate; + applyUpdateableChanges(updateable, false); + } + entityToUpdate.setValidTo(DateUtil.getCurrentTimeInUTC()); + em.merge(entityToUpdate); + } + + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRED) + @Transactional + @Lock(LockType.WRITE) + public T create(T entity) throws ControllerException { + entity.setValidFrom(DateUtil.getCurrentTimeInUTC()); + return super.create(entity); + } + + @TransactionAttribute(TransactionAttributeType.REQUIRED) + @Transactional + @Lock(LockType.WRITE) + @Override + public T update(T entity) throws ControllerException { + T newEntity = entity.cloneEndDateable(); + delete(entity); + return create (newEntity); + } + + @Lock(LockType.READ) + @Override + public List findAll(List orderFields) { + Date now = DateUtil.getCurrentTimeInUTC(); + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery criteria = cb.createQuery(endDateableClass); + final Root root = criteria.from(endDateableClass); + + Predicate alreadyValid = cb.lessThanOrEqualTo(root.get("validFrom"), now); + + Predicate validToNotSet = cb.isNull(root.get("validTo")); + Predicate isBeforeValidTo = cb.greaterThanOrEqualTo(root.get("validTo"), now); + Predicate stillValid = cb.or (isBeforeValidTo, validToNotSet); + Predicate isValid = cb.and(alreadyValid, stillValid); + criteria.where(isValid); + + List orderList = new ArrayList<>(); + orderFields.stream().forEachOrdered(field -> orderList.add(cb.asc(root.get(field)))); + final TypedQuery query = em.createQuery(criteria.orderBy(orderList)); + + return query.getResultList(); + } + +} diff --git a/account/src/main/java/de/muehlencord/shared/account/util/EndDateable.java b/account/src/main/java/de/muehlencord/shared/account/util/EndDateable.java new file mode 100644 index 0000000..5bc9579 --- /dev/null +++ b/account/src/main/java/de/muehlencord/shared/account/util/EndDateable.java @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Joern Muehlencord . + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.muehlencord.shared.account.util; + +import java.util.Date; + +/** + * Enddateable entities are not deleted but an enddate is set to "now" + * + * @author Joern Muehlencord + */ +public interface EndDateable { + + T cloneEndDateable(); + + Date getValidFrom(); + + Date getValidTo(); + + void setValidFrom(Date validFrom); + + void setValidTo(Date validTo); + +}