use of org.meveo.model.crm.EntityReferenceWrapper in project meveo by meveo-org.
the class CustomEntityInstanceService method list.
public List<CustomEntityInstance> list(String cetCode, Map<String, Object> values) {
QueryBuilder qb = new QueryBuilder(getEntityClass(), "cei", null);
qb.addCriterion("cei.cetCode", "=", cetCode, true);
final List<CustomEntityInstance> resultList = qb.getTypedQuery(getEntityManager(), CustomEntityInstance.class).getResultList();
var ownValues = new HashMap<>(values);
for (var entry : values.entrySet()) {
if (entry.getValue() instanceof EntityReferenceWrapper) {
ownValues.remove(entry.getKey());
}
}
if (ownValues != null && !ownValues.isEmpty()) {
return resultList.stream().filter(customEntityInstance -> filterOnValues(ownValues, customEntityInstance)).collect(Collectors.toList());
}
return resultList;
}
use of org.meveo.model.crm.EntityReferenceWrapper in project meveo by meveo-org.
the class FilteringJobBean method execute.
/**
* Execute the jobInstance.
*
* @param result The result execution
* @param jobInstance the jobInstance to execute
*/
@SuppressWarnings("unchecked")
@Interceptors({ JobLoggingInterceptor.class, PerformanceInterceptor.class })
@TransactionAttribute(TransactionAttributeType.NEVER)
public void execute(JobExecutionResultImpl result, JobInstance jobInstance) {
ScriptInterface scriptInterface = null;
Map<String, Object> context = null;
try {
Long nbRuns = new Long(1);
Long waitingMillis = new Long(0);
try {
nbRuns = (Long) customFieldInstanceService.getCFValue(jobInstance, "nbRuns");
waitingMillis = (Long) customFieldInstanceService.getCFValue(jobInstance, "waitingMillis");
if (nbRuns == -1) {
nbRuns = (long) Runtime.getRuntime().availableProcessors();
}
} catch (Exception e) {
nbRuns = new Long(1);
waitingMillis = new Long(0);
log.warn("Cant get customFields for " + jobInstance.getJobTemplate(), e.getMessage());
}
String filterCode = ((EntityReferenceWrapper) customFieldInstanceService.getCFValue(jobInstance, "FilteringJob_filter")).getCode();
String scriptCode = ((EntityReferenceWrapper) customFieldInstanceService.getCFValue(jobInstance, "FilteringJob_script")).getCode();
String recordVariableName = (String) customFieldInstanceService.getCFValue(jobInstance, "FilteringJob_recordVariableName");
try {
scriptInterface = scriptInstanceService.getScriptInstance(scriptCode);
} catch (EntityNotFoundException | InvalidScriptException e) {
result.registerError(e.getMessage());
return;
}
context = (Map<String, Object>) customFieldInstanceService.getCFValue(jobInstance, "FilteringJob_variables");
if (context == null) {
context = new HashMap<String, Object>();
}
Filter filter = filterService.findByCode(filterCode);
if (filter == null) {
result.registerError("Cant find filter : " + filterCode);
return;
}
scriptInterface.init(context);
List<? extends IEntity> filtredEntities = filterService.filteredListAsObjects(filter);
int nbItemsToProcess = filtredEntities == null ? 0 : filtredEntities.size();
result.setNbItemsToProcess(nbItemsToProcess);
List<Future<String>> futures = new ArrayList<Future<String>>();
SubListCreator subListCreator = new SubListCreator(filtredEntities, nbRuns.intValue());
log.debug("NbItemsToProcess:{}, block to run{}, nbThreads:{}.", nbItemsToProcess, subListCreator.getBlocToRun(), nbRuns);
MeveoUser lastCurrentUser = currentUser.unProxy();
while (subListCreator.isHasNext()) {
futures.add(filtringJobAsync.launchAndForget((List<? extends IEntity>) subListCreator.getNextWorkSet(), result, scriptInterface, recordVariableName, lastCurrentUser));
if (subListCreator.isHasNext()) {
try {
Thread.sleep(waitingMillis.longValue());
} catch (InterruptedException e) {
log.error("", e);
}
}
}
// Wait for all async methods to finish
for (Future<String> future : futures) {
try {
future.get();
} catch (InterruptedException e) {
// It was cancelled from outside - no interest
} catch (ExecutionException e) {
Throwable cause = e.getCause();
result.registerError(cause.getMessage());
result.addReport(cause.getMessage());
log.error("Failed to execute async method", cause);
}
}
} catch (Exception e) {
log.error("Error on execute", e);
result.setReport("error:" + e.getMessage());
} finally {
try {
scriptInterface.finalize(context);
} catch (Exception e) {
log.error("Error on finally execute", e);
result.setReport("finalize error:" + e.getMessage());
}
}
}
use of org.meveo.model.crm.EntityReferenceWrapper in project meveo by meveo-org.
the class NativePersistenceService method castValue.
/**
* Convert value of unknown data type to a target data type. A value of type
* list is considered as already converted value, as would come only from WS.
*
* @param value Value to convert
* @param targetClass Target data type class to convert to
* @param expectedList Is return value expected to be a list. If value is not a
* list and is a string a value will be parsed as comma
* separated string and each value will be converted
* accordingly. If a single value is passed, it will be
* added to a list.
* @param datePatterns Optional. Date patterns to apply to a date type field.
* Conversion is attempted in that order until a valid date
* is matched.If no values are provided, a standard date and
* time and then date only patterns will be applied.
* @return A converted data type
* @throws ValidationException Value can not be cast to a target class
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Object castValue(Object value, Class targetClass, boolean expectedList, String[] datePatterns) throws ValidationException {
if (StringUtils.isBlank(value)) {
return null;
}
if (value.equals(true)) {
return 1;
} else if (value.equals(false)) {
return 0;
}
// Nothing to cast - same data type
if (targetClass.isAssignableFrom(value.getClass()) && !expectedList) {
return value;
}
// separated string and convert each value separately
if (expectedList) {
if (value instanceof Collection) {
Collection<?> collectionValue = (Collection<?>) value;
// Convert entity references wrapper list to list of string
{
List<String> entityReferences = collectionValue.stream().filter(EntityReferenceWrapper.class::isInstance).map(EntityReferenceWrapper.class::cast).map(EntityReferenceWrapper::getUuid).filter(Objects::nonNull).collect(Collectors.toList());
if (!entityReferences.isEmpty()) {
return entityReferences;
}
}
// Convert entity references wrapper list to list of long
{
List<Long> entityReferences = collectionValue.stream().filter(EntityReferenceWrapper.class::isInstance).map(EntityReferenceWrapper.class::cast).map(EntityReferenceWrapper::getId).filter(Objects::nonNull).collect(Collectors.toList());
if (!entityReferences.isEmpty()) {
return entityReferences;
}
}
return value;
} else if (value instanceof String) {
try {
// First try to parse json
return JacksonUtil.fromString((String) value, List.class);
} catch (Exception e) {
// If it fails, parse comma separated string
List valuesConverted = new ArrayList<>();
String[] valueItems = ((String) value).split(",");
for (String valueItem : valueItems) {
Object valueConverted = castValue(valueItem, targetClass, false, datePatterns);
if (valueConverted != null) {
valuesConverted.add(valueConverted);
} else {
throw new ValidationException("Filter value " + value + " does not match " + targetClass.getSimpleName());
}
}
return valuesConverted;
}
} else {
// A single value list
Object valueConverted = castValue(value, targetClass, false, datePatterns);
if (valueConverted != null) {
return Collections.singletonList(valueConverted);
} else {
throw new ValidationException("Filter value " + value + " does not match " + targetClass.getSimpleName());
}
}
} else {
if (value instanceof Collection) {
return JacksonUtil.toString(value);
}
}
Number numberVal = null;
BigDecimal bdVal = null;
String stringVal = null;
Boolean booleanVal = null;
Date dateVal = null;
List listVal = null;
if (value instanceof BigDecimal) {
bdVal = (BigDecimal) value;
} else if (value instanceof Number) {
numberVal = (Number) value;
} else if (value instanceof Boolean) {
booleanVal = (Boolean) value;
} else if (value instanceof Date) {
dateVal = (Date) value;
} else if (value instanceof String) {
stringVal = (String) value;
} else if (value instanceof List) {
listVal = (List) value;
} else if (value instanceof Map) {
stringVal = JacksonUtil.toString(value);
} else if (value instanceof File) {
stringVal = ((File) value).getAbsolutePath();
} else {
throw new ValidationException("Unrecognized data type for value " + value + " type " + value.getClass());
}
try {
if (targetClass == String.class) {
if (value instanceof Map) {
return stringVal;
}
if (stringVal != null || listVal != null) {
return value;
} else {
return value.toString();
}
} else if (targetClass == Boolean.class || (targetClass.isPrimitive() && targetClass.getName().equals("boolean"))) {
if (booleanVal != null) {
return value;
} else {
return Boolean.parseBoolean(value.toString());
}
} else if (targetClass == Date.class || targetClass == Instant.class) {
if (dateVal != null || listVal != null) {
return value;
} else if (numberVal != null) {
return Instant.ofEpochMilli(numberVal.longValue());
} else if (stringVal != null) {
// Use provided date patterns or try default patterns if they were not provided
if (datePatterns != null) {
for (String datePattern : datePatterns) {
Instant date = DateUtils.parseDateWithPattern(stringVal, datePattern);
if (date != null) {
return date;
}
}
} else {
// first try with date and time and then only with date format
Instant date = DateUtils.parseDateWithPattern(stringVal, DateUtils.DATE_TIME_PATTERN);
if (date == null) {
date = DateUtils.parseDateWithPattern(stringVal, paramBean.getDateTimeFormat());
}
if (date == null) {
date = DateUtils.parseDateWithPattern(stringVal, DateUtils.DATE_PATTERN);
}
if (date == null) {
date = DateUtils.parseDateWithPattern(stringVal, paramBean.getDateFormat());
}
return date;
}
}
} else if (targetClass.isEnum()) {
if (listVal != null || targetClass.isAssignableFrom(value.getClass())) {
return value;
} else if (stringVal != null) {
Enum enumVal = ReflectionUtils.getEnumFromString((Class<? extends Enum>) targetClass, stringVal);
if (enumVal != null) {
return enumVal;
}
}
} else if (targetClass == Integer.class || (targetClass.isPrimitive() && targetClass.getName().equals("int"))) {
if (numberVal != null || bdVal != null || listVal != null) {
return value;
} else if (stringVal != null) {
return Integer.parseInt(stringVal);
}
} else if (targetClass == Long.class || (targetClass.isPrimitive() && targetClass.getName().equals("long"))) {
if (numberVal != null || bdVal != null || listVal != null) {
return value;
} else if (stringVal != null) {
return Long.parseLong(stringVal);
}
} else if (targetClass == Byte.class || (targetClass.isPrimitive() && targetClass.getName().equals("byte"))) {
if (numberVal != null || bdVal != null || listVal != null) {
return value;
} else if (stringVal != null) {
return Byte.parseByte(stringVal);
}
} else if (targetClass == Short.class || (targetClass.isPrimitive() && targetClass.getName().equals("short"))) {
if (numberVal != null || bdVal != null || listVal != null) {
return value;
} else if (stringVal != null) {
return Short.parseShort(stringVal);
}
} else if (targetClass == Double.class || (targetClass.isPrimitive() && targetClass.getName().equals("double"))) {
if (numberVal != null || bdVal != null || listVal != null) {
return value;
} else if (stringVal != null) {
return Double.parseDouble(stringVal);
}
} else if (targetClass == Float.class || (targetClass.isPrimitive() && targetClass.getName().equals("float"))) {
if (numberVal != null || bdVal != null || listVal != null) {
return value;
} else if (stringVal != null) {
return Float.parseFloat(stringVal);
}
} else if (targetClass == BigDecimal.class) {
if (numberVal != null || bdVal != null || listVal != null) {
return value;
} else if (stringVal != null) {
return new BigDecimal(stringVal);
}
}
} catch (NumberFormatException e) {
// Swallow - validation will take care of it later
}
return value;
}
use of org.meveo.model.crm.EntityReferenceWrapper in project meveo by meveo-org.
the class NativePersistenceService method findIdByUniqueValues.
/**
* Find a record uuid in table using its exact values
*
* @param sqlConnectionCode Code of the sql configuration
* @param customTemplate Template related to the table
* @param queryValues Values used to filter the result
* @param fields
* @return The uuid of the record if it was found or null if it was not
*/
public String findIdByUniqueValues(String sqlConnectionCode, CustomModelObject customTemplate, Map<String, Object> queryValues, Collection<CustomFieldTemplate> fields) {
String result = null;
String tableName = PostgresReserverdKeywords.escapeAndFormat(customTemplate.getDbTableName());
if (queryValues.isEmpty()) {
throw new IllegalArgumentException("Query values should not be empty");
}
StringBuilder q = new StringBuilder();
q.append("SELECT uuid FROM {h-schema}" + tableName + " as a\n");
Map<Integer, Object> queryParamers = new HashMap<>();
Map<String, Object> uniqueValues = new HashMap<>();
for (CustomFieldTemplate cft : fields) {
if (cft.isUnique()) {
Object uniqueValue = Optional.ofNullable(queryValues.get(cft.getCode())).orElse(queryValues.get(cft.getDbFieldname()));
// Don't use inherited values
if (uniqueValue != null && cft.getAppliesTo().equals(customTemplate.getAppliesTo())) {
uniqueValues.put(cft.getDbFieldname(), uniqueValue);
}
}
}
if (uniqueValues.isEmpty()) {
result = null;
} else {
AtomicInteger i = new AtomicInteger(1);
uniqueValues.forEach((key, value) -> {
key = PostgresReserverdKeywords.escapeAndFormat(key);
if (!(value instanceof Collection) && !(value instanceof File) && !(value instanceof Map)) {
if (value instanceof EntityReferenceWrapper) {
value = ((EntityReferenceWrapper) value).getUuid();
}
if (i.get() == 1) {
q.append("WHERE a." + key + " = ?\n");
} else {
q.append("AND a." + key + " = ?\n");
}
queryParamers.put(i.getAndIncrement(), value);
}
});
QueryBuilder builder = new QueryBuilder();
builder.setSqlString(q.toString());
Session session = crossStorageTransaction.getHibernateSession(sqlConnectionCode);
NativeQuery<Map<String, Object>> query = builder.getNativeQuery(session, true);
queryParamers.forEach((k, v) -> query.setParameter(k, v));
try {
Map<String, Object> singleResult = query.getSingleResult();
result = (String) singleResult.get("uuid");
} catch (NoResultException | NonUniqueResultException e) {
result = null;
} catch (Exception e) {
log.error("Error executing query {}", query.getQueryString());
throw e;
}
}
if (result == null && customTemplate instanceof CustomEntityTemplate) {
CustomEntityTemplate cet = (CustomEntityTemplate) customTemplate;
CustomEntityTemplate superTemplate = cet.getSuperTemplate();
if (superTemplate != null) {
if (HibernateUtils.isLazyLoaded(superTemplate)) {
superTemplate = customEntityTemplateService.findById(superTemplate.getId(), List.of("superTemplate"));
}
result = findIdByUniqueValues(sqlConnectionCode, superTemplate, queryValues, fields);
}
}
return result;
}
use of org.meveo.model.crm.EntityReferenceWrapper in project meveo by meveo-org.
the class CustomFieldInstanceService method setCFValue.
/**
* Set a Custom field value on an entity.
*
* @param entity Entity
* @param cfCode Custom field value code
* @param value Value to set
* @return custom field value
* @throws BusinessException business exception.
*/
@SuppressWarnings("unchecked")
public CustomFieldValue setCFValue(ICustomFieldEntity entity, String cfCode, Object value) throws BusinessException {
log.trace("Setting CF value. Code: {}, entity {} value {}", cfCode, entity, value);
String repository = "default";
CustomEntityTemplate cet = null;
if (entity instanceof CustomEntityInstance) {
cet = ((CustomEntityInstance) entity).getCet();
repository = ((CustomEntityInstance) entity).getRepository() != null ? ((CustomEntityInstance) entity).getRepository().getCode() : "default";
}
// Can not set the value if field is versionable without a date
CustomFieldTemplate cft = cfTemplateService.findByCodeAndAppliesTo(cfCode, entity);
if (cft == null) {
throw new BusinessException("Custom field template with code " + cfCode + " not found found for entity " + entity);
}
// Handle serialized map values
if ((cft.getStorageType() == CustomFieldStorageTypeEnum.MAP || cft.getStorageType() == CustomFieldStorageTypeEnum.MATRIX) && value instanceof String) {
value = JacksonUtil.fromString((String) value, Map.class);
}
if (cft.isVersionable()) {
throw new RuntimeException("Can not determine a period for Custom Field " + entity.getClass().getSimpleName() + "/" + cfCode + " value if no date or date range is provided");
}
// Handle cases when appProvider was passed instead of a real Provider entity. The class in this case is org.meveo.model.crm.Provider$Proxy$_$$_WeldClientProxy
if (entity instanceof Provider && entity.getClass().getSimpleName().contains("Proxy")) {
entity = providerService.findById(appProvider.getId());
}
CustomFieldValue cfValue = null;
if (entity.getCfValues() != null) {
cfValue = entity.getCfValues().getCfValue(cfCode);
}
log.trace("Setting CF value1. Code: {}, cfValue {}", cfCode, cfValue);
// No existing CF value. Create CF value with new value. Assign(persist) NULL value only if cft.defaultValue is present
if (cfValue == null) {
if (cft.getFieldType() == CustomFieldTypeEnum.ENTITY) {
/* Don't wrap primitive entity references */
if (cft.getStoragesNullSafe().contains(DBStorageType.NEO4J)) {
String cetCode = cft.getEntityClazzCetCode();
CustomEntityTemplate refCet = customEntityTemplateService.findByCode(cetCode);
if (refCet == null) {
throw new org.meveo.exceptions.EntityDoesNotExistsException(CustomEntityTemplate.class, cetCode);
}
if (refCet.getNeo4JStorageConfiguration() != null && refCet.getNeo4JStorageConfiguration().isPrimitiveEntity()) {
return entity.getCfValuesNullSafe().setValue(cfCode, value);
}
}
if (customFieldTemplateService.isReferenceJpaEntity(cft.getEntityClazzCetCode())) {
if (cft.getStorageType() == CustomFieldStorageTypeEnum.LIST) {
try {
var collectionValue = JacksonUtil.convert(value, new TypeReference<List<EntityReferenceWrapper>>() {
});
cfValue = entity.getCfValuesNullSafe().setValue(cfCode, collectionValue, EntityReferenceWrapper.class);
} catch (Exception e) {
// FIXME: Handle these cases
log.warn("Unhandled data : {}", value.toString());
}
} else {
EntityReferenceWrapper entityReferenceWrapper = new EntityReferenceWrapper();
entityReferenceWrapper.setClassnameCode(cft.getEntityClazzCetCode());
if (value instanceof EntityReferenceWrapper) {
entityReferenceWrapper = (EntityReferenceWrapper) value;
} else if (value instanceof String) {
entityReferenceWrapper.setUuid((String) value);
entityReferenceWrapper.setCode((String) value);
} else if (value instanceof BusinessEntity) {
entityReferenceWrapper.setCode(((BusinessEntity) value).getCode());
entityReferenceWrapper.setId(((BusinessEntity) value).getId());
} else if (StringUtils.isNumeric(String.valueOf(value))) {
entityReferenceWrapper.setId(Long.parseLong(String.valueOf(value)));
} else if (value instanceof BaseEntity) {
JpaUtils.extractNaturalId(value).ifPresent(entityReferenceWrapper::setCode);
entityReferenceWrapper.setId(((BaseEntity) value).getId());
}
cfValue = entity.getCfValuesNullSafe().setValue(cfCode, entityReferenceWrapper);
}
} else {
EntityReferenceWrapper entityReferenceWrapper = new EntityReferenceWrapper();
entityReferenceWrapper.setClassnameCode(cft.getEntityClazzCetCode());
entityReferenceWrapper.setRepository(repository);
if (value instanceof Map) {
Map<String, Object> valueAsMap = (Map<String, Object>) value;
entityReferenceWrapper.setCode((String) valueAsMap.get("code"));
entityReferenceWrapper.setUuid((String) valueAsMap.get("uuid"));
if (entityReferenceWrapper.getUuid() == null) {
entityReferenceWrapper.setUuid((String) valueAsMap.get("meveo_uuid"));
}
} else if (value instanceof String) {
entityReferenceWrapper.setUuid((String) value);
fetchCode(cft, (String) value, entityReferenceWrapper);
} else if (value instanceof EntityReferenceWrapper) {
entityReferenceWrapper = (EntityReferenceWrapper) value;
}
if (entityReferenceWrapper.getUuid() != null) {
cfValue = entity.getCfValuesNullSafe().setValue(cfCode, entityReferenceWrapper);
} else if (value instanceof Collection) {
List<EntityReferenceWrapper> entityReferences = new ArrayList<>();
List<Map<String, Object>> entityValues = new ArrayList<>();
for (Object item : (Collection<?>) value) {
EntityReferenceWrapper itemWrapper = new EntityReferenceWrapper();
itemWrapper.setClassnameCode(cft.getEntityClazzCetCode());
if (item instanceof Map) {
Map<String, Object> valueAsMap = (Map<String, Object>) item;
itemWrapper.setCode((String) valueAsMap.get("code"));
itemWrapper.setUuid((String) valueAsMap.get("uuid"));
if (itemWrapper.getUuid() == null) {
itemWrapper.setUuid((String) valueAsMap.get("meveo_uuid"));
}
if (itemWrapper.getUuid() == null) {
entityValues.add(valueAsMap);
}
} else if (item instanceof String) {
itemWrapper.setUuid((String) item);
itemWrapper.setCode((String) item);
// Try to fetch code
fetchCode(cft, (String) item, itemWrapper);
} else if (item instanceof EntityReferenceWrapper) {
itemWrapper = (EntityReferenceWrapper) item;
}
if (itemWrapper.getUuid() != null || itemWrapper.getCode() != null) {
entityReferences.add(itemWrapper);
}
}
// If entity references list is empty, the entities referenced are probably being created
if (!entityReferences.isEmpty()) {
cfValue = entity.getCfValuesNullSafe().setValue(cfCode, entityReferences);
} else if (!entityValues.isEmpty()) {
cfValue = entity.getCfValuesNullSafe().setValue(cfCode, entityValues);
}
} else {
entity.getCfValuesNullSafe().setValue(cfCode, value);
}
}
if (value instanceof CustomEntityInstance) {
cfValue = entity.getCfValuesNullSafe().setValue(cfCode, value);
}
} else {
cfValue = entity.getCfValuesNullSafe().setValue(cfCode, value);
}
log.trace("Setting CF value 2. Code: {}, cfValue {}", cfCode, cfValue);
// Existing CFI found. Update with new value or NULL value only if cft.defaultValue is present
} else if (value != null || cft.getDefaultValue() != null) {
try {
cfValue.setValue(value);
} catch (IllegalArgumentException e) {
log.error("Error setting value for field template with code " + cfCode + " for entity " + entity + " : " + e.getMessage());
throw e;
}
// Existing CF value found, but new value is null, so remove CF value all together
} else {
entity.getCfValues().removeValue(cfCode);
return null;
}
return cfValue;
}
Aggregations