splitted database from account
This commit is contained in:
@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright 2016 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* 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.db;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.ejb.Lock;
|
||||
import javax.ejb.LockType;
|
||||
import javax.ejb.TransactionAttribute;
|
||||
import javax.ejb.TransactionAttributeType;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Order;
|
||||
import javax.persistence.criteria.Path;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.transaction.Transactional;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class AbstractController<T> {
|
||||
|
||||
@Inject
|
||||
@ApplicationPU
|
||||
protected EntityManager em;
|
||||
|
||||
private final Class<T> entityClass;
|
||||
|
||||
public AbstractController(Class<T> clazz) {
|
||||
this.entityClass = clazz;
|
||||
}
|
||||
|
||||
protected Predicate getFilterCondition(CriteriaBuilder cb, Root<T> root, Map<String, Object> filters) {
|
||||
return getFilterCondition(cb, root, filters, null);
|
||||
}
|
||||
|
||||
protected Predicate getFilterCondition(CriteriaBuilder cb, Root<T> root, Map<String, Object> filters, Map<String, Object> excludeFilters) {
|
||||
Predicate filterCondition = null;
|
||||
filterCondition = getFilterCondition(filterCondition, cb, root, filters, true);
|
||||
filterCondition = getFilterCondition(filterCondition, cb, root, excludeFilters, false);
|
||||
return filterCondition;
|
||||
}
|
||||
|
||||
protected Predicate addFilterCondition(CriteriaBuilder cb, Predicate filterCondition, Predicate addCondition) {
|
||||
if (addCondition == null) {
|
||||
return filterCondition;
|
||||
}
|
||||
if (filterCondition == null) {
|
||||
filterCondition = addCondition;
|
||||
} else {
|
||||
filterCondition = cb.and(filterCondition, addCondition);
|
||||
}
|
||||
return filterCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* extends the given filterCondition by the addtional filters
|
||||
*
|
||||
* @param filterCondition the current filter condition
|
||||
* @param cb the criteria builder to use
|
||||
* @param root the root of the object to search for
|
||||
* @param filters the filters to apply
|
||||
* @param include if set to true, the filter is used as include filter
|
||||
* (equals, in). If set to false, the filter is inverted and used as exclude
|
||||
* filter (not equals, not in etc)
|
||||
* @return
|
||||
*/
|
||||
protected Predicate getFilterCondition(Predicate filterCondition, CriteriaBuilder cb, Root<T> root, Map<String, Object> filters, boolean include) {
|
||||
String wildCard = "%";
|
||||
if (filters != null) {
|
||||
for (Map.Entry<String, Object> filter : filters.entrySet()) {
|
||||
if (!"".equals(filter.getValue())) {
|
||||
Path<String> path = getPathElement(root, filter);
|
||||
|
||||
// check for differnt types
|
||||
// 1st String, either from Enum Status or from other free text string
|
||||
if (String.class.equals(filter.getValue().getClass())) {
|
||||
switch (filter.getKey()) {
|
||||
default:
|
||||
String filterValue = filter.getValue().toString();
|
||||
Predicate predicate;
|
||||
if (filterValue.equals("{NULL}")) {
|
||||
if (include) {
|
||||
predicate = cb.isNull(path);
|
||||
} else {
|
||||
predicate = cb.isNotNull(path);
|
||||
}
|
||||
} else {
|
||||
filterValue = filterValue.trim();
|
||||
filterValue = filterValue.replace("?", "_");
|
||||
filterValue = filterValue.replace("*", "%");
|
||||
|
||||
String[] values = filterValue.split("\\s+"); // split by whitespaces
|
||||
Predicate[] partSearchPredicates = new Predicate[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
String value = wildCard + values[i] + wildCard;
|
||||
if (include) {
|
||||
partSearchPredicates[i] = cb.like(cb.upper(path), value.toUpperCase(Locale.US), '\\');
|
||||
} else {
|
||||
partSearchPredicates[i] = cb.notLike(cb.upper(path), value.toUpperCase(Locale.US), '\\');
|
||||
}
|
||||
}
|
||||
predicate = cb.and(partSearchPredicates); // all parts must be available
|
||||
}
|
||||
filterCondition = addFilterCondition(cb, filterCondition, predicate);
|
||||
}
|
||||
} // 2nd for arrays, received from e.g. project selections
|
||||
else if (filter.getValue().getClass().isArray()) {
|
||||
Predicate condition = null;
|
||||
Object[] values = (Object[]) filter.getValue();
|
||||
if (values.length > 0) {
|
||||
for (Object value : values) {
|
||||
if (include) {
|
||||
Predicate equalPredicate = cb.equal(path, value);
|
||||
if (condition == null) {
|
||||
condition = equalPredicate;
|
||||
} else {
|
||||
condition = cb.or(condition, equalPredicate);
|
||||
}
|
||||
} else {
|
||||
Predicate equalPredicate = cb.notEqual(path, value);
|
||||
if (condition == null) {
|
||||
condition = equalPredicate;
|
||||
} else {
|
||||
condition = cb.and(condition, equalPredicate);
|
||||
}
|
||||
}
|
||||
}
|
||||
filterCondition = addFilterCondition(cb, filterCondition, condition);
|
||||
}
|
||||
} else { // at last object comparison
|
||||
if (include) {
|
||||
filterCondition = addFilterCondition(cb, filterCondition, cb.equal(path, filter.getValue()));
|
||||
} else {
|
||||
filterCondition = addFilterCondition(cb, filterCondition, cb.notEqual(path, filter.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return filterCondition;
|
||||
}
|
||||
|
||||
private Path<String> getPathElement(Root<T> root, Map.Entry<String, Object> filter) {
|
||||
String[] pathElements = StringUtils.split(filter.getKey(), '.');
|
||||
Path<String> path = null;
|
||||
for (String element : pathElements) {
|
||||
if (path == null) {
|
||||
path = root.get(element);
|
||||
} else {
|
||||
path = path.get(element);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
public void applyUpdateableChanges(Updateable updateable, boolean onCreate, String updatedBy) throws ControllerException {
|
||||
if (onCreate) {
|
||||
updateable.setCreatedBy(updatedBy);
|
||||
updateable.setCreatedOn(new Date());
|
||||
}
|
||||
updateable.setLastUpdatedBy(updatedBy);
|
||||
updateable.setLastUpdatedOn(new Date());
|
||||
}
|
||||
|
||||
public T attach(T entity) {
|
||||
return em.merge(entity);
|
||||
}
|
||||
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public T create(T entity, String createdBy) throws ControllerException {
|
||||
if (Updateable.class.isAssignableFrom(entity.getClass())) {
|
||||
Updateable updateable = (Updateable) entity;
|
||||
applyUpdateableChanges(updateable, true, createdBy);
|
||||
}
|
||||
em.persist(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public T update(T entity, String updatedBy) throws ControllerException {
|
||||
if (Updateable.class.isAssignableFrom(entity.getClass())) {
|
||||
Updateable updateable = (Updateable) entity;
|
||||
applyUpdateableChanges(updateable, false, updatedBy);
|
||||
}
|
||||
return em.merge(entity);
|
||||
}
|
||||
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public void delete(T entity, String deletedBy) throws ControllerException {
|
||||
em.remove(attach(entity));
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
public T find(Object id) {
|
||||
return em.find(entityClass, id);
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
public List<T> findAll() {
|
||||
return findAll(new ArrayList<>());
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
public List<T> findAll(String... orderFields) {
|
||||
return findAll(Arrays.asList(orderFields));
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
public List<T> findAll(List<String> orderFields) {
|
||||
final CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
final CriteriaQuery<T> criteria = cb.createQuery(entityClass);
|
||||
|
||||
final Root<T> r = criteria.from(entityClass);
|
||||
|
||||
List<Order> orderList = new ArrayList<>();
|
||||
orderFields.stream().forEachOrdered(field -> orderList.add(cb.asc(r.get(field))));
|
||||
final TypedQuery<T> query = em.createQuery(criteria.orderBy(orderList));
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
public List<T> find(Map<String, Object> filters, List<String> orderFields) {
|
||||
final CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
final CriteriaQuery<T> criteria = cb.createQuery(entityClass);
|
||||
|
||||
final Root<T> r = criteria.from(entityClass);
|
||||
Predicate filterCondition = getFilterCondition(cb, r, filters);
|
||||
if (filterCondition != null) {
|
||||
criteria.where(filterCondition);
|
||||
}
|
||||
List<Order> orderList = new ArrayList<>();
|
||||
orderFields.stream().forEachOrdered(field -> orderList.add(cb.asc(r.get(field))));
|
||||
final TypedQuery<T> query = em.createQuery(criteria.orderBy(orderList));
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns null, if the list is empty or null itself. Returns the one
|
||||
* element if there is exactly one element in the list. Otherwise an
|
||||
* exception is thrown
|
||||
*
|
||||
* @param resultList
|
||||
* @return
|
||||
* @throws ControllerException
|
||||
*/
|
||||
public T ensureSingleElement(List<T> resultList) throws ControllerException {
|
||||
if ((resultList == null) || (resultList.isEmpty())) {
|
||||
return null;
|
||||
}
|
||||
if (resultList.size() > 1) {
|
||||
throw new ControllerException(ControllerException.CAUSE_TOO_MANY_ROWS, "More than one element found in list - expected exactly one");
|
||||
}
|
||||
return resultList.get(0);
|
||||
}
|
||||
|
||||
private <T> SingularAttribute<? super T, ?> getIdAttribute() {
|
||||
Metamodel m = em.getEntityManagerFactory().getMetamodel();
|
||||
IdentifiableType<T> of = (IdentifiableType<T>) m.managedType(entityClass);
|
||||
// of.getDeclaredId(entityClass).getJavaMember().
|
||||
return of.getId(of.getIdType().getJavaType());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2019 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* 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.db;
|
||||
|
||||
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 <joern at muehlencord.de>
|
||||
* @param <T> an entity which needs to extend EndDateable
|
||||
*/
|
||||
public abstract class AbstractEnddateableController<T extends EndDateable<T>> extends AbstractController<T> {
|
||||
|
||||
private final Class<T> endDateableClass;
|
||||
|
||||
public AbstractEnddateableController(Class<T> clazz) {
|
||||
super(clazz);
|
||||
this.endDateableClass = clazz;
|
||||
}
|
||||
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
@Override
|
||||
public void delete(T entity, String deletedBy) throws ControllerException {
|
||||
T entityToUpdate = attach(entity);
|
||||
if (Updateable.class.isAssignableFrom(entityToUpdate.getClass())) {
|
||||
Updateable updateable = (Updateable) entityToUpdate;
|
||||
applyUpdateableChanges(updateable, false, deletedBy);
|
||||
}
|
||||
entityToUpdate.setValidTo(DateUtil.getCurrentTimeInUTC());
|
||||
em.merge(entityToUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public T create(T entity, String createdBy) throws ControllerException {
|
||||
entity.setValidFrom(DateUtil.getCurrentTimeInUTC());
|
||||
return super.create(entity, createdBy);
|
||||
}
|
||||
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
@Override
|
||||
public T update(T entity, String createdBy) throws ControllerException {
|
||||
T newEntity = entity.cloneEndDateable();
|
||||
delete(entity, createdBy);
|
||||
return create(newEntity, createdBy);
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
@Override
|
||||
public List<T> findAll(List<String> orderFields) {
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
final CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
final CriteriaQuery<T> criteria = cb.createQuery(endDateableClass);
|
||||
final Root<T> 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<Order> orderList = new ArrayList<>();
|
||||
orderFields.stream().forEachOrdered(field -> orderList.add(cb.asc(root.get(field))));
|
||||
final TypedQuery<T> query = em.createQuery(criteria.orderBy(orderList));
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
}
|
||||
36
db/src/main/java/de/muehlencord/shared/db/ApplicationPU.java
Normal file
36
db/src/main/java/de/muehlencord/shared/db/ApplicationPU.java
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2018 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.db;
|
||||
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.ElementType.PARAMETER;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import java.lang.annotation.Retention;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Qualifier
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD, FIELD, PARAMETER, TYPE})
|
||||
public @interface ApplicationPU {
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package de.muehlencord.shared.db;
|
||||
|
||||
import javax.annotation.Priority;
|
||||
import javax.inject.Inject;
|
||||
import javax.interceptor.AroundInvoke;
|
||||
import javax.interceptor.Interceptor;
|
||||
import javax.interceptor.InvocationContext;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.transaction.Transactional;
|
||||
import static javax.transaction.Transactional.TxType.REQUIRED;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Transactional(value = REQUIRED)
|
||||
@Interceptor
|
||||
@Priority(value = ApplicationTransactionJoinInterceptor.PRIORITY)
|
||||
public class ApplicationTransactionJoinInterceptor {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationTransactionJoinInterceptor.class);
|
||||
|
||||
// attach behind the interceptor of the container
|
||||
public static final int PRIORITY = Interceptor.Priority.PLATFORM_BEFORE + 250;
|
||||
|
||||
@Inject
|
||||
@ApplicationPU
|
||||
private EntityManager em;
|
||||
|
||||
@AroundInvoke
|
||||
public Object joinTransaction(InvocationContext context) throws Exception {
|
||||
if (em == null) {
|
||||
return context.proceed();
|
||||
} else {
|
||||
if (em.isJoinedToTransaction()) {
|
||||
LOGGER.trace("transaction already joined");
|
||||
} else {
|
||||
LOGGER.trace("joining transaction");
|
||||
em.joinTransaction();
|
||||
}
|
||||
}
|
||||
return context.proceed();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.db;
|
||||
|
||||
import javax.ejb.ApplicationException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@ApplicationException(rollback=true)
|
||||
public class ControllerException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 5190280225284514859L;
|
||||
public static final int CAUSE_ALREADY_EXISTS = 1;
|
||||
public static final int CAUSE_NOT_FOUND = 2;
|
||||
public static final int CAUSE_CANNOT_PERSIST = 3;
|
||||
public static final int CAUSE_TOO_MANY_ROWS = 4;
|
||||
public static final int CAUSE_CANNOT_DELETE = 5;
|
||||
|
||||
private final int causeCode;
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>ControllerException</code> without detail
|
||||
* message.
|
||||
*
|
||||
* @param cause the reason code
|
||||
* @param message an explanation
|
||||
*/
|
||||
public ControllerException(int cause, String message) {
|
||||
super(message);
|
||||
this.causeCode = cause;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param causeCode
|
||||
* @param message
|
||||
* @param cause
|
||||
*/
|
||||
public ControllerException(int causeCode, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.causeCode = causeCode;
|
||||
}
|
||||
|
||||
public int getCauseCode() {
|
||||
return causeCode;
|
||||
}
|
||||
}
|
||||
37
db/src/main/java/de/muehlencord/shared/db/EndDateable.java
Normal file
37
db/src/main/java/de/muehlencord/shared/db/EndDateable.java
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2019 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* 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.db;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Enddateable entities are not deleted but an enddate is set to "now"
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public interface EndDateable<T> {
|
||||
|
||||
T cloneEndDateable();
|
||||
|
||||
Date getValidFrom();
|
||||
|
||||
Date getValidTo();
|
||||
|
||||
void setValidFrom(Date validFrom);
|
||||
|
||||
void setValidTo(Date validTo);
|
||||
|
||||
}
|
||||
29
db/src/main/java/de/muehlencord/shared/db/Updateable.java
Normal file
29
db/src/main/java/de/muehlencord/shared/db/Updateable.java
Normal file
@ -0,0 +1,29 @@
|
||||
package de.muehlencord.shared.db;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* This interface is used for Entities which provide createdOn / createdBy
|
||||
* lastUpatedBy / lastUpdatedOn fields. The AbstractController uses this interface
|
||||
* to automatically update the fields on creation / update.
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public interface Updateable {
|
||||
|
||||
void setCreatedBy(String createdBy);
|
||||
|
||||
String getCreatedBy();
|
||||
|
||||
void setCreatedOn(Date createdOn);
|
||||
|
||||
Date getCreatedOn();
|
||||
|
||||
void setLastUpdatedBy(String lastUpdatedBy);
|
||||
|
||||
String getLastUpdatedBy();
|
||||
|
||||
void setLastUpdatedOn(Date lastUpdatedOn);
|
||||
|
||||
Date getLastUpdatedOn();
|
||||
}
|
||||
Reference in New Issue
Block a user