es.prodevelop.pui9.service.MultiValuedAttribute Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of es.prodevelop.pui9.services Show documentation
Show all versions of es.prodevelop.pui9.services Show documentation
Support for business layer (BO)
package es.prodevelop.pui9.service;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.commons.lang3.tuple.Pair;
import es.prodevelop.pui9.components.PuiApplicationContext;
import es.prodevelop.pui9.exceptions.PuiDaoDeleteException;
import es.prodevelop.pui9.exceptions.PuiDaoFindException;
import es.prodevelop.pui9.exceptions.PuiDaoInsertException;
import es.prodevelop.pui9.exceptions.PuiServiceDeleteException;
import es.prodevelop.pui9.exceptions.PuiServiceException;
import es.prodevelop.pui9.exceptions.PuiServiceInsertException;
import es.prodevelop.pui9.exceptions.PuiServiceUpdateException;
import es.prodevelop.pui9.filter.FilterBuilder;
import es.prodevelop.pui9.login.PuiUserSession;
import es.prodevelop.pui9.model.dao.interfaces.ITableDao;
import es.prodevelop.pui9.model.dto.DtoRegistry;
import es.prodevelop.pui9.model.dto.interfaces.ITableDto;
/**
* This class is used in the {@link AbstractService} classes to configure the
* multivalued attributes. For each multivalued attribute configuration, you
* must provide:
*
* - The Java Field name of the multivalued attribute
* - A list of pairs of table Java Fields, indicating at left the Java Field
* of the local table and at right the Java Field of the multivalued table used
* to make the relationship between the two tables (local and multivalued)
* - A list of pairs of table Java Fields, indicating at left the Java Field
* of the referenced table and at right the Java Field of the multivalued table
* used to make the relationship between the two tables (referenced and
* multivalued)
* - The DAO class of the referenced table: A DAO that extends from
* ITableDao
* - The DAO class of the multivalued table: A DAO that extends from
* ITableDao
*
*
* @param Local Table DTO
* @param Referenced Table DTO PK
* @param Referenced Table DTO
* @param Referenced DAO
* @param Multivalued Table DTO PK
* @param Multivalued Table DTO
* @param Multivalued Table DAO
*
* @author Marc Gil - [email protected]
*/
public class MultiValuedAttribute, MTDPK extends ITableDto, MTD extends MTDPK, MD extends ITableDao> {
private String fieldName;
private List> localFields;
private List> referencedFields;
private Class referencedDaoClass;
private Class multivaluedDaoClass;
private RD referencedDao;
private MD multivaluedDao;
public MultiValuedAttribute(String fieldName, List> localFields,
List> referencedFields, Class referencedDaoClass, Class multivaluedDaoClass) {
this.fieldName = fieldName;
this.localFields = localFields;
this.referencedFields = referencedFields;
this.referencedDaoClass = referencedDaoClass;
this.multivaluedDaoClass = multivaluedDaoClass;
}
/**
* Populate the multivalued field of the given DTO with the values
*
* @param local The registry to populate the multivalued field
*/
void populate(LTD local) {
List referencedList = getReferencedFromDatabase(local);
setFieldValue(local, fieldName, referencedList);
}
/**
* Insert all the multivalued registries
*
* @param local The local registry
* @throws PuiServiceInsertException If any exception is thrown while inserting
* the multivalued registries
*/
void insert(LTD local) throws PuiServiceInsertException {
for (RTD referenced : getReferencedFromField(local)) {
MTD multivalued = createMultivalued(local, referenced);
if (multivalued == null) {
throw new PuiServiceInsertException(
new PuiServiceException(new Exception("Error while creating multivalued attribute")));
}
try {
if (!getMultivaluedDao().exists(multivalued.createPk())) {
getMultivaluedDao().insert(multivalued);
}
afterInsertMultivalued(local, referenced, multivalued);
} catch (PuiDaoInsertException | PuiDaoFindException e) {
throw new PuiServiceInsertException(e);
}
}
}
/**
* Update all the multivalued registries. The way to manage the multivalued
* registries, is to delete and insert them again
*
* @param local The registry to update its multivalued registries
* @throws PuiServiceUpdateException If any exception is thrown while updating
* the multivalued registries
*/
void update(LTD local) throws PuiServiceUpdateException {
try {
delete(local, false);
insert(local);
} catch (PuiServiceDeleteException | PuiServiceInsertException e) {
throw new PuiServiceUpdateException(e);
}
}
/**
* Delete all the multivalued registries
*
* @param local The registry to delete its multivalued registries
* @param deleteAll If true, all the multivalued registries will be deleted
* (delete action); if false, only those that are not present
* in the list of the DTO (update action)
* @throws PuiServiceUpdateException If any exception is thrown while deleting
* the multivalued registries
*/
void delete(LTD local, boolean deleteAll) throws PuiServiceDeleteException {
List referencedFromFieldList = getReferencedFromField(local);
List referencedFromDbList = getReferencedFromDatabase(local);
first: for (RTD referencedDb : referencedFromDbList) {
if (!deleteAll) {
for (RTD referencedLocal : referencedFromFieldList) {
if (areEqualsReferenced(referencedDb, referencedLocal)) {
continue first;
}
}
}
MTD multivalued = createMultivalued(local, referencedDb);
if (multivalued == null) {
continue;
}
try {
beforeDeleteMultivalued(local, referencedDb, multivalued);
getMultivaluedDao().delete(multivalued.createPk());
afterDeleteMultivalued(local, referencedDb, multivalued);
} catch (PuiDaoDeleteException e) {
throw new PuiServiceDeleteException(e);
}
}
}
/**
* Do something after create a multivalued registry
*
* @param local The local registry
* @param referenced The referenced registry
* @param multivalued The multivalued registry
*/
protected void afterCreateMultivalued(LTD local, RTD referenced, MTD multivalued) {
// nothing to do
}
/**
* Do something after inserting a multivalued registry
*
* @param local The local registry
* @param referenced The referenced registry
* @param multivalued The multivalued registry
*/
protected void afterInsertMultivalued(LTD local, RTD referenced, MTD multivalued) {
// nothing to do
}
/**
* Do something before deleting a multivalued registry
*
* @param local The local registry
* @param referenced The referenced registry
* @param multivalued The multivalued registry
*/
protected void beforeDeleteMultivalued(LTD local, RTD referenced, MTD multivalued) {
// nothing to do
}
/**
* Do something after deleting a multivalued registry
*
* @param local The local registry
* @param referenced The referenced registry
* @param multivalued The multivalued registry
*/
protected void afterDeleteMultivalued(LTD local, RTD referenced, MTD multivalued) {
// nothing to do
}
/**
* Get the list of referenced values for the given DTO
*
* @param local The DTO that we want to get the referenced list of values
* @return The list of referenced registries in the other side of the
* multivalued relationship
*/
private List getReferencedFromDatabase(LTD local) {
List multivaluedList;
if (hasValidFieldValues(local)) {
multivaluedList = getMultivaluedListFromDatabase(local);
} else {
multivaluedList = Collections.emptyList();
}
return getReferencedListFromMultivaluedList(multivaluedList);
}
/**
* Get the list of referenced values from the field of the DTO
*
* @param local The DTO that we want to get the referenced list of values
* @return The list of referenced registries in the other side of the
* multivalued relationship
*/
@SuppressWarnings("unchecked")
private List getReferencedFromField(LTD local) {
List referencedList = (List) getFieldValue(local, fieldName);
if (referencedList == null) {
referencedList = Collections.emptyList();
}
return referencedList;
}
/**
* Get the list of registries of the multivalued table for the given DTO
*
* @param local The DTO to obtain its related multivalued registries
* @return The list of related multivalued registries
*/
private List getMultivaluedListFromDatabase(LTD local) {
FilterBuilder filterBuilder = FilterBuilder.newAndFilter();
for (Pair localField : localFields) {
Object value = getFieldValue(local, localField.getLeft());
if (value == null) {
break;
}
if (value instanceof String) {
filterBuilder.addEqualsExact(localField.getRight(), (String) value);
} else {
filterBuilder.addEquals(localField.getRight(), value);
}
}
List multivaluedList;
try {
multivaluedList = getMultivaluedDao().findWhere(filterBuilder, PuiUserSession.getSessionLanguage());
} catch (PuiDaoFindException e) {
multivaluedList = Collections.emptyList();
}
return multivaluedList;
}
/**
* Get the list of referenced registries from the given multivalued list
*
* @param multivaluedList The list of multivalued registries
* @return The list of referenced registries
*/
private List getReferencedListFromMultivaluedList(List multivaluedList) {
FilterBuilder filterBuilder = FilterBuilder.newOrFilter();
for (MTD multivalued : multivaluedList) {
FilterBuilder filterBuilder2 = FilterBuilder.newAndFilter();
for (Pair refencedField : referencedFields) {
Object value = getFieldValue(multivalued, refencedField.getRight());
if (value instanceof String) {
filterBuilder2.addEqualsExact(refencedField.getLeft(), (String) value);
} else {
filterBuilder2.addEquals(refencedField.getLeft(), value);
}
}
filterBuilder.addGroup(filterBuilder2);
}
List referencedList = Collections.emptyList();
if (filterBuilder.isEmpty()) {
return referencedList;
}
try {
referencedList = getReferencedDao().findWhere(filterBuilder, PuiUserSession.getSessionLanguage());
} catch (PuiDaoFindException e) {
// do nothing
}
return referencedList;
}
/**
* Check if the two given referenced objects are the same or not (based on the
* PK)
*
* @param refOne One referenced object
* @param refTwo Other referenced object
* @return true if are equals; false if not
*/
private boolean areEqualsReferenced(ITableDto refOne, ITableDto refTwo) {
boolean equals = true;
for (Pair referencedField : referencedFields) {
Object valOne = getFieldValue(refOne, referencedField.getLeft());
Object valTwo = getFieldValue(refTwo, referencedField.getLeft());
equals &= Objects.equals(valOne, valTwo);
}
return equals;
}
/**
* Check if the given DTO has valid field values to participate in the
* multivalued table
*
* @param local The DTO
* @return true if all the attributes of the DTO that participates in the
* multivalued table have any value; false if not
*/
private boolean hasValidFieldValues(ITableDto local) {
boolean valid = true;
for (Pair localField : localFields) {
Object value = getFieldValue(local, localField.getLeft());
valid &= value != null;
}
return valid;
}
/**
* Create a Multivalued registry from the local and referenced registry
*
* @param local The local registry
* @param referenced The referenced registry
* @return The multivalued registry
*/
private MTD createMultivalued(LTD local, RTD referenced) {
try {
MTD multivalued = getMultivaluedDao().getDtoClass().newInstance();
for (Pair localField : localFields) {
Object value = getFieldValue(local, localField.getLeft());
setFieldValue(multivalued, localField.getRight(), value);
}
for (Pair referencedField : referencedFields) {
Object value = getFieldValue(referenced, referencedField.getLeft());
setFieldValue(multivalued, referencedField.getRight(), value);
}
afterCreateMultivalued(local, referenced, multivalued);
return multivalued;
} catch (InstantiationException | IllegalAccessException e) {
return null;
}
}
/**
* Get the value of the given field for the given registry
*
* @param dto The registry to retrieve a value
* @param fieldName The field to retrieve its value
* @return The value of the field
*/
private Object getFieldValue(ITableDto dto, String fieldName) {
try {
Field field = getField(dto.getClass(), fieldName);
return FieldUtils.readField(field, dto);
} catch (Exception e) {
return null;
}
}
private Field getField(Class extends ITableDto> dtoClass, String fieldName) {
try {
Field field = DtoRegistry.getJavaFieldFromFieldName(dtoClass, fieldName);
if (field == null) {
field = FieldUtils.getDeclaredField(dtoClass, fieldName, true);
}
return field;
} catch (Exception e) {
return null;
}
}
/**
* Set a value to a field
*
* @param dto The registry to be set a value
* @param fieldName The field to set a new value
* @param value The value to be set
*/
private void setFieldValue(ITableDto dto, String fieldName, Object value) {
try {
FieldUtils.writeField(dto, fieldName, value, true);
} catch (Exception e) {
// do nothing
}
}
/**
* Obtain the bean of the referenced table
*
* @return The referenced table bean
*/
private RD getReferencedDao() {
if (referencedDao == null) {
referencedDao = PuiApplicationContext.getInstance().getBean(referencedDaoClass);
}
return referencedDao;
}
/**
* Obtain the bean of the multivalued table
*
* @return The multivalued table bean
*/
private MD getMultivaluedDao() {
if (multivaluedDao == null) {
multivaluedDao = PuiApplicationContext.getInstance().getBean(multivaluedDaoClass);
}
return multivaluedDao;
}
@Override
public String toString() {
return "Multivalued field: " + fieldName;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy