use of org.meveo.model.customEntities.CustomTableRecord in project meveo by meveo-org.
the class NativePersistenceService method updateValue.
/**
* Update field value in a table
*
* @param sqlConnectionCode Code of the sql repository
* @param tableName Table name to update
* @param uuid Record identifier
* @param fieldName Field to update
* @param value New value
* @throws BusinessException General exception
*/
@Transactional(value = TxType.SUPPORTS)
public void updateValue(String sqlConnectionCode, String tableName, String uuid, String fieldName, Object value) throws BusinessException {
var finalValue = value instanceof Collection ? value = JacksonUtil.toString(value) : value;
String cetCode = tableName;
var finalTableName = PostgresReserverdKeywords.escapeAndFormat(tableName);
var finalFieldName = PostgresReserverdKeywords.escapeAndFormat(fieldName);
StringBuilder sql = new StringBuilder();
if (finalValue == null) {
sql.append("update " + finalTableName + " set " + finalFieldName + "= null where uuid = ?");
} else {
sql.append("update " + finalTableName + " set " + finalFieldName + "= ? where uuid = ?");
}
var session = crossStorageTransaction.getHibernateSession(sqlConnectionCode);
session.doWork(connection -> {
if (!sqlConnectionCode.equals(SqlConfiguration.DEFAULT_SQL_CONNECTION)) {
if (!sqlConnectionProvider.getSqlConfiguration(sqlConnectionCode).isXAResource())
connection.setAutoCommit(false);
}
try (var statement = connection.prepareStatement(sql.toString())) {
if (finalValue == null) {
statement.setString(1, uuid);
} else {
setParameterValue(statement, 1, finalValue);
statement.setString(2, uuid);
}
statement.executeUpdate();
if (!sqlConnectionCode.equals(SqlConfiguration.DEFAULT_SQL_CONNECTION)) {
if (!sqlConnectionProvider.getSqlConfiguration(sqlConnectionCode).isXAResource())
connection.commit();
}
CustomTableRecord record = new CustomTableRecord();
record.setUuid(uuid);
record.setCetCode(cetCode);
customTableRecordUpdate.fire(record);
} catch (Exception e) {
log.error("Failed to update value in table {}/{}/{}", tableName, fieldName, uuid);
if (!sqlConnectionCode.equals(SqlConfiguration.DEFAULT_SQL_CONNECTION)) {
if (!sqlConnectionProvider.getSqlConfiguration(sqlConnectionCode).isXAResource())
connection.rollback();
}
throw e;
}
});
}
use of org.meveo.model.customEntities.CustomTableRecord in project meveo by meveo-org.
the class NativePersistenceService method update.
/**
* Update a record in a table. Record is identified by an "uuid" field value.
* @param sqlConnectionCode Code of the {@link SqlConfiguration} to use
*
* @param cei the {@link CustomEntityInstance}. The cf values must
* contain the field uuid.
* @param isFiltered if true process only the fields with storage=SQL
* @param removeNullValues if true, remove the null values
* @throws BusinessException General exception
*/
public void update(String sqlConnectionCode, CustomEntityInstance cei, boolean isFiltered, Collection<CustomFieldTemplate> cfts, boolean removeNullValues) throws BusinessException {
// Update data in parent template
if (cei.getCet().getSuperTemplate() != null && cei.getCet().getSuperTemplate().storedIn(DBStorageType.SQL)) {
var parentCfts = customFieldTemplateService.findByAppliesTo(cei.getCet().getSuperTemplate().getAppliesTo()).values();
var parentCei = new CustomEntityInstance();
parentCei.setCet(cei.getCet().getSuperTemplate());
parentCei.setCfValues(cei.getCfValues());
parentCei.setUuid(cei.getUuid());
update(sqlConnectionCode, parentCei, true, parentCfts, removeNullValues);
}
String tableName = PostgresReserverdKeywords.escapeAndFormat(cei.getTableName());
Map<String, Object> sqlValues = cei.getCfValuesAsValues(isFiltered ? DBStorageType.SQL : null, cfts, removeNullValues);
var appliesTo = CustomEntityTemplate.getAppliesTo(cei.getCetCode());
Map<String, CustomFieldTemplate> cftsMap = cfts.stream().filter(cft -> cft.getAppliesTo().equals(appliesTo)).collect(Collectors.toMap(cft -> cft.getCode(), cft -> cft));
// remove inherited data
for (String sqlValueKey : List.copyOf(sqlValues.keySet())) {
if (sqlValueKey.equals("uuid"))
continue;
if (!cftsMap.containsKey(sqlValueKey)) {
sqlValues.remove(sqlValueKey);
}
}
final Map<String, Object> values = serializeValues(convertValue(sqlValues, cftsMap, removeNullValues, null), cftsMap);
for (String key : cftsMap.keySet()) {
if (key != null && !values.keySet().contains(key) && cftsMap.get(key).getStorageType().equals(CustomFieldStorageTypeEnum.LIST)) {
values.put(key, new ArrayList<>());
}
}
if (sqlValues.get(FIELD_ID) == null) {
throw new BusinessException("'uuid' field value not provided to update values in native table");
}
if (sqlValues.size() < 2) {
// Nothing to update a there is only "uuid" value inside the map
return;
}
StringBuilder sql = new StringBuilder();
try {
sql.append("UPDATE ").append(tableName).append(" SET ");
boolean first = true;
for (String fieldName : values.keySet()) {
String fieldNameInSQL = PostgresReserverdKeywords.escapeAndFormat(fieldName);
if (fieldName.equals(FIELD_ID)) {
continue;
}
if (!first) {
sql.append(",");
}
if (values.get(fieldName) == null) {
sql.append(fieldNameInSQL).append(" = NULL");
} else {
sql.append(fieldNameInSQL).append(" = ? ");
}
first = false;
}
sql.append(" WHERE uuid='" + cei.getUuid() + "'");
Session hibernateSession = crossStorageTransaction.getHibernateSession(sqlConnectionCode);
hibernateSession.doWork(connection -> {
if (!sqlConnectionCode.equals(SqlConfiguration.DEFAULT_SQL_CONNECTION)) {
if (!sqlConnectionProvider.getSqlConfiguration(sqlConnectionCode).isXAResource())
connection.setAutoCommit(false);
}
setSchema(sqlConnectionCode, connection);
try (PreparedStatement ps = connection.prepareStatement(sql.toString())) {
int parameterIndex = 1;
for (String fieldName : values.keySet()) {
Object fieldValue = values.get(fieldName);
if (fieldValue != null && fieldName != "uuid") {
setParameterValue(ps, parameterIndex++, fieldValue);
}
}
ps.executeUpdate();
if (!sqlConnectionCode.equals(SqlConfiguration.DEFAULT_SQL_CONNECTION)) {
if (!sqlConnectionProvider.getSqlConfiguration(sqlConnectionCode).isXAResource())
connection.commit();
}
} catch (Exception e) {
log.error("Native SQL update failed: {}", e.getMessage());
if (!sqlConnectionCode.equals(SqlConfiguration.DEFAULT_SQL_CONNECTION)) {
if (!sqlConnectionProvider.getSqlConfiguration(sqlConnectionCode).isXAResource())
connection.rollback();
}
}
});
CustomTableRecord record = new CustomTableRecord();
record.setUuid((String) values.get(FIELD_ID));
record.setCetCode(cei.getTableName());
customTableRecordUpdate.fire(record);
} catch (Exception e) {
log.error("Failed to insert values into table {} {} sql {}", tableName, values, sql, e);
throw e;
}
}
use of org.meveo.model.customEntities.CustomTableRecord in project meveo by meveo-org.
the class NativePersistenceService method remove.
/**
* Delete a record
*
* @param tableName Table name to update
* @param uuid Record identifier
* @throws BusinessException General exception
*/
public void remove(String sqlConnectionCode, CustomEntityTemplate template, String uuid) throws BusinessException {
// Remove record in children tables
var subTemplates = customEntityTemplateService.getSubTemplates(template);
subTemplates.forEach(subT -> removeRecord(sqlConnectionCode, uuid, tableName(subT)));
// Remove in own table
removeRecord(sqlConnectionCode, uuid, tableName(template));
// Remove record in parent table
if (template.getSuperTemplate() != null) {
CustomEntityTemplate parentTemplate = customEntityTemplateService.findById(template.getSuperTemplate().getId());
remove(sqlConnectionCode, parentTemplate, uuid);
} else {
CustomTableRecord record = new CustomTableRecord();
record.setCetCode(template.getCode());
record.setUuid(uuid);
customTableRecordRemoved.fire(record);
}
}
use of org.meveo.model.customEntities.CustomTableRecord in project meveo by meveo-org.
the class NativePersistenceService method remove.
/**
* Delete multiple records
*
* @param tableName Table name to update
* @param ids A set of record identifiers
* @throws BusinessException General exception
*/
public void remove(String sqlConnectionCode, CustomEntityTemplate template, Collection<String> ids) throws BusinessException {
// Remove record in children tables
var subTemplates = customEntityTemplateService.getSubTemplates(template);
subTemplates.forEach(subT -> removeRecords(sqlConnectionCode, tableName(subT), ids));
// Remove in own table
removeRecords(sqlConnectionCode, tableName(template), ids);
// Remove record in parent table
if (template.getSuperTemplate() != null) {
CustomEntityTemplate parentTemplate = customEntityTemplateService.findById(template.getSuperTemplate().getId());
remove(sqlConnectionCode, parentTemplate, ids);
} else {
for (String id : ids) {
CustomTableRecord record = new CustomTableRecord();
record.setCetCode(template.getCode());
record.setUuid(id);
customTableRecordRemoved.fire(record);
}
}
}
use of org.meveo.model.customEntities.CustomTableRecord in project meveo by meveo-org.
the class ElasticSearchIndexPopulationService method convertEntityToJson.
/**
* Convert entity to a map of values that is accepted by Elastic Search as document to be stored and indexed.
*
* @param entity Entity to store in Elastic Search
* @param cftIndexable Sets to track CFTs that are indexable. Used in massive initial ES population.
* @param cftNotIndexable Sets to track CFTs that are not indexable. Used in massive initial ES population.
* @param type Index type used to distinguish one entity type from another inside the same index. Optional, 'entityType' value wont be set if not provided.
* @return A map of values
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public Map<String, Object> convertEntityToJson(ISearchable entity, Set<String> cftIndexable, Set<String> cftNotIndexable, String type) {
Map<String, Object> jsonValueMap = new HashMap<String, Object>();
if (type != null) {
jsonValueMap.put(ElasticSearchConfiguration.MAPPING_FIELD_TYPE, type);
}
// A special case where values are already present as a map
if (entity instanceof CustomTableRecord) {
jsonValueMap.putAll(((CustomTableRecord) entity).getValues());
return jsonValueMap;
}
// Maps fields between entity and json.
Map<String, String> fields = esConfiguration.getFields(entity);
String fieldNameTo = null;
String fieldNameFrom = null;
for (Entry<String, String> fieldInfo : fields.entrySet()) {
fieldNameTo = fieldInfo.getKey();
fieldNameFrom = fieldInfo.getValue();
// log.trace("Mapping {} to {}", fieldNameFrom, fieldNameTo);
Object value = null;
try {
// Obtain field value from entity
if (!fieldNameFrom.contains(".")) {
// log.trace("Fetching value of property {}", fieldNameFrom);
if (fieldNameFrom.endsWith("()")) {
value = MethodUtils.invokeMethod(entity, fieldNameFrom.substring(0, fieldNameFrom.length() - 2));
} else {
value = FieldUtils.readField(entity, fieldNameFrom, true);
}
if (value != null && value instanceof HibernateProxy) {
value = ((HibernateProxy) value).getHibernateLazyInitializer().getImplementation();
}
// log.trace("Value retrieved: {}", value);
} else {
String[] fieldNames = fieldNameFrom.split("\\.");
Object fieldValue = entity;
for (String fieldName : fieldNames) {
// log.trace("Fetching value of property {}", fieldName);
if (fieldValue == null) {
break;
}
if (fieldName.endsWith("()")) {
// log.trace("Invoking method {}.{}", fieldValue.getClass().getSimpleName(), fieldName);
fieldValue = MethodUtils.invokeMethod(fieldValue, true, fieldName.substring(0, fieldName.length() - 2), ArrayUtils.EMPTY_OBJECT_ARRAY, null);
} else {
// log.trace("Reading property {}.{}", fieldValue.getClass().getSimpleName(), fieldName);
fieldValue = FieldUtils.readField(fieldValue, fieldName, true);
}
if (fieldValue == null) {
break;
}
if (fieldValue instanceof HibernateProxy) {
// log.trace("Fetching value through HibernateProxy {}.{}", fieldValue.getClass().getSimpleName(), fieldName);
fieldValue = ((HibernateProxy) fieldValue).getHibernateLazyInitializer().getImplementation();
}
// log.trace("Value retrieved: {}", fieldValue);
}
value = fieldValue;
// log.trace("Final value retrieved, {}: {}", fieldNameFrom, value);
}
// Process value further in case of certain data types - date, list or entity
if (value != null) {
if (value instanceof Timestamp) {
value = ((Timestamp) value).getTime();
} else if (value instanceof java.sql.Date) {
value = ((java.sql.Date) value).getTime();
} else if (value instanceof Collection && !((Collection) value).isEmpty()) {
List values = new ArrayList<>();
for (Object val : ((Collection) value)) {
if (val instanceof Timestamp) {
values.add(((Timestamp) val).getTime());
} else if (val instanceof java.sql.Date) {
values.add(((java.sql.Date) val).getTime());
} else if (val.getClass().isAnnotationPresent(Embeddable.class)) {
values.add(convertObjectToFieldMap(val));
} else if (val instanceof IEntity) {
values.add(val.toString());
} else {
values.add(val);
}
}
value = values;
} else if (value.getClass().isAnnotationPresent(Embeddable.class)) {
value = convertObjectToFieldMap(value);
} else if (value instanceof IEntity) {
value = value.toString();
}
}
// Set value to json preserving the field hierarchy
if (!fieldNameTo.contains(".")) {
jsonValueMap.put(fieldNameTo, value);
} else {
String[] fieldNames = fieldNameTo.split("\\.");
String fieldName = null;
Map<String, Object> mapEntry = jsonValueMap;
int length = fieldNames.length;
for (int i = 0; i < length; i++) {
fieldName = fieldNames[i];
if (i < length - 1) {
if (!mapEntry.containsKey(fieldName)) {
mapEntry.put(fieldName, new HashMap<String, Object>());
}
mapEntry = (Map<String, Object>) mapEntry.get(fieldName);
} else {
mapEntry.put(fieldName, value);
}
}
}
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
log.error("Failed to access field {} of {}", fieldInfo.getValue(), ReflectionUtils.getCleanClassName(entity.getClass().getSimpleName()));
}
}
// Set custom field values if applicable
if (entity instanceof ICustomFieldEntity && ((ICustomFieldEntity) entity).getCfValues() != null && ((ICustomFieldEntity) entity).getCfValuesAsValues() != null) {
ICustomFieldEntity cfEntity = (ICustomFieldEntity) entity;
// At the moment does not handle versioned values - just take the today's value
for (Entry<String, Object> cfValueInfo : cfEntity.getCfValuesAsValues().entrySet()) {
String cfCode = cfValueInfo.getKey();
Object value = cfValueInfo.getValue();
if (value instanceof Map || value instanceof EntityReferenceWrapper) {
value = JacksonUtil.toString(value);
}
if (cftIndexable != null && cftIndexable.contains(entity.getClass().getName() + "_" + cfCode)) {
jsonValueMap.put(cfCode, value);
} else if (cftNotIndexable != null && cftNotIndexable.contains(entity.getClass().getName() + "_" + cfCode)) {
continue;
} else {
CustomFieldTemplate cft = customFieldTemplateService.findByCodeAndAppliesTo(cfCode, (ICustomFieldEntity) entity);
if (cft != null && cft.getIndexType() != null) {
if (cftIndexable != null) {
cftIndexable.add(entity.getClass().getName() + "_" + cfCode);
}
jsonValueMap.put(cfCode, value);
} else if (cftNotIndexable != null) {
cftNotIndexable.add(entity.getClass().getName() + "_" + cfCode);
}
}
}
}
// log.trace("Returning jsonValueMap: {}", jsonValueMap);
return jsonValueMap;
}
Aggregations