use of org.broadleafcommerce.openadmin.web.rulebuilder.MVELTranslationException in project BroadleafCommerce by BroadleafCommerce.
the class PhraseTranslator method createExpression.
public Expression createExpression(String phrase) throws MVELTranslationException {
String[] components = extractComponents(phrase);
String field = components[0];
String operator = components[1];
String value = components[2];
boolean isNegation = false;
if (field.startsWith("!") || phrase.startsWith("!")) {
isNegation = true;
}
boolean isIgnoreCase = false;
boolean isCollectionCase = false;
if (phrase.contains(DataDTOToMVELTranslator.COLLECTION_OPERATOR)) {
isCollectionCase = true;
}
// remove null check syntax
field = field.replaceAll("\\.\\?", ".");
// keep for backwards compatibility with legacy generated MVEL
String legacyCaseInsensitivityKey = "MVEL.eval(\"toUpperCase()\",";
String newCaseInsensitivityKey = "MvelHelper.toUpperCase(";
String caseInsensitivityKey;
if (field.contains(legacyCaseInsensitivityKey) || value.contains(legacyCaseInsensitivityKey)) {
caseInsensitivityKey = legacyCaseInsensitivityKey;
} else {
caseInsensitivityKey = newCaseInsensitivityKey;
}
if (field.contains(caseInsensitivityKey)) {
isIgnoreCase = true;
field = field.substring(field.indexOf(caseInsensitivityKey) + caseInsensitivityKey.length(), field.length() - 1);
}
while (value.contains(caseInsensitivityKey)) {
int caseIndex = value.indexOf(caseInsensitivityKey);
value = value.substring(0, caseIndex) + value.substring(caseIndex + caseInsensitivityKey.length());
if (value.contains("\")")) {
value = value.substring(0, value.indexOf("\")") + 1) + value.substring(value.indexOf("\")") + 2);
} else {
value = value.substring(0, value.indexOf(")")) + value.substring(value.indexOf(")") + 1);
}
}
if (value.startsWith("[") && value.endsWith("]") && !isCollectionCase) {
value = value.substring(1, value.length() - 1);
String[] temps = value.split(",");
for (int j = 0; j < temps.length; j++) {
if (temps[j].startsWith("\"") && temps[j].endsWith("\"")) {
temps[j] = temps[j].substring(1, temps[j].length() - 1);
}
}
StringBuffer sb = new StringBuffer();
sb.append("[");
for (int j = 0; j < temps.length; j++) {
sb.append(temps[j]);
if (j < temps.length - 1) {
sb.append(",");
}
}
sb.append("]");
value = sb.toString();
}
// keep for backwards compatibility with legacy generated MVEL
String legacyDateFormatKey = "java.text.DateFormat.getDateTimeInstance(3,3).parse(";
String newDateFormatKey = "MvelHelper.convertField(\"DATE\",\"";
String dateFormatKey;
if (value.contains(legacyDateFormatKey)) {
dateFormatKey = legacyDateFormatKey;
} else {
dateFormatKey = newDateFormatKey;
}
if (value.startsWith(dateFormatKey)) {
value = value.substring(dateFormatKey.length(), value.length() - 1);
// convert the date into admin display format
try {
if (value.startsWith("\"")) {
value = value.substring(1, value.length());
}
if (value.endsWith("\"")) {
value = value.substring(0, value.length() - 1);
}
value = RuleBuilderFormatUtil.formatDate(RuleBuilderFormatUtil.parseDate(value));
} catch (ParseException e) {
throw new MVELTranslationException(MVELTranslationException.INCOMPATIBLE_DATE_VALUE, "Unable to convert " + "the persisted date value(" + value + ") to the admin display format.");
}
}
int entityKeyIndex = field.indexOf(".");
if (entityKeyIndex < 0) {
throw new MVELTranslationException(MVELTranslationException.NO_FIELD_FOUND_IN_RULE, "Could not identify a " + "valid property field value in the expression: (" + phrase + ")");
}
if (value.startsWith(caseInsensitivityKey)) {
value = value.substring(caseInsensitivityKey.length(), value.length() - 1);
}
String entityKey = field.substring(0, entityKeyIndex);
boolean isFieldComparison = false;
if (value.startsWith("\"") && value.endsWith("\"")) {
value = value.substring(1, value.length() - 1);
} else if (value.startsWith(entityKey + ".")) {
isFieldComparison = true;
value = value.substring(entityKey.length() + 1, value.length());
}
field = field.substring(entityKeyIndex + 1, field.length());
// If this is a Money field, then DataDTOToMVELTranslator.formatValue() will append .getAmount() onto the end
// of the field name. We need to remove that as it should not be considered part of the field name, but we still
// want to support other method invocations in MVEL expressions (like for getProductAttributes())
String moneyAmountMethod = ".getAmount()";
int amountMethodPos = field.lastIndexOf(moneyAmountMethod);
if (amountMethodPos >= 0) {
field = field.substring(0, amountMethodPos);
}
// Same as above, but for Enumeration types
String typeMethod = ".getType()";
int typeMethodPos = field.lastIndexOf(typeMethod);
if (typeMethodPos >= 0) {
field = field.substring(0, typeMethodPos);
}
Expression expression = new Expression();
expression.setField(field);
BLCOperator operatorId = getOperator(field, operator, value, isNegation, isFieldComparison, isIgnoreCase);
expression.setOperator(operatorId);
expression.setValue(value);
return expression;
}
use of org.broadleafcommerce.openadmin.web.rulebuilder.MVELTranslationException in project BroadleafCommerce by BroadleafCommerce.
the class RuleFieldPersistenceProvider method updateQuantityRule.
protected boolean updateQuantityRule(EntityManager em, DataDTOToMVELTranslator translator, String entityKey, String fieldService, String jsonPropertyValue, Collection<QuantityBasedRule> criteriaList, Class<?> memberType, Object parent, String mappedBy, Property property) {
boolean dirty = false;
if (!StringUtils.isEmpty(jsonPropertyValue)) {
// avoid lazy init exception on the criteria list for criteria created during an add
criteriaList.size();
DataWrapper dw = ruleFieldExtractionUtility.convertJsonToDataWrapper(jsonPropertyValue);
if (dw != null && StringUtils.isEmpty(dw.getError())) {
List<QuantityBasedRule> updatedRules = new ArrayList<QuantityBasedRule>();
for (DataDTO dto : dw.getData()) {
if (dto.getPk() != null && !CollectionUtils.isEmpty(criteriaList)) {
checkId: {
// Update Existing Criteria
for (QuantityBasedRule quantityBasedRule : criteriaList) {
// make compatible with enterprise module
boolean isParentRelated = sandBoxHelper.isRelatedToParentCatalogIds(quantityBasedRule, dto.getPk());
boolean isMatch = isParentRelated || dto.getPk().equals(quantityBasedRule.getId());
if (isMatch) {
String mvel;
// don't update if the data has not changed
if (!quantityBasedRule.getQuantity().equals(dto.getQuantity())) {
dirty = true;
}
try {
mvel = ruleFieldExtractionUtility.convertDTOToMvelString(translator, entityKey, dto, fieldService);
if (!quantityBasedRule.getMatchRule().equals(mvel)) {
dirty = true;
}
} catch (MVELTranslationException e) {
throw new RuntimeException(e);
}
if (!dirty && extensionManager != null) {
ExtensionResultHolder<Boolean> resultHolder = new ExtensionResultHolder<Boolean>();
ExtensionResultStatusType result = extensionManager.getProxy().establishDirtyState(quantityBasedRule, resultHolder);
if (ExtensionResultStatusType.NOT_HANDLED != result && resultHolder.getResult() != null) {
dirty = resultHolder.getResult();
}
}
if (dirty) {
// pre-merge (can result in a clone for enterprise)
quantityBasedRule = em.merge(quantityBasedRule);
// update the quantity based rule
quantityBasedRule.setQuantity(dto.getQuantity());
quantityBasedRule.setMatchRule(mvel);
quantityBasedRule = em.merge(quantityBasedRule);
}
updatedRules.add(quantityBasedRule);
break checkId;
}
}
throw new IllegalArgumentException("Unable to update the rule of type (" + memberType.getName() + ") because an update was requested for id (" + dto.getPk() + "), which does not exist.");
}
} else {
// Create a new Criteria
QuantityBasedRule quantityBasedRule;
try {
quantityBasedRule = (QuantityBasedRule) memberType.newInstance();
quantityBasedRule.setQuantity(dto.getQuantity());
quantityBasedRule.setMatchRule(ruleFieldExtractionUtility.convertDTOToMvelString(translator, entityKey, dto, fieldService));
if (StringUtils.isEmpty(quantityBasedRule.getMatchRule()) && !StringUtils.isEmpty(dw.getRawMvel())) {
quantityBasedRule.setMatchRule(dw.getRawMvel());
}
PropertyUtils.setNestedProperty(quantityBasedRule, mappedBy, parent);
} catch (Exception e) {
throw new RuntimeException(e);
}
em.persist(quantityBasedRule);
dto.setPk(quantityBasedRule.getId());
Object contained = findContainedRuleIfApplicable(quantityBasedRule);
if (contained != null) {
dto.setContainedPk((Long) em.unwrap(Session.class).getIdentifier(contained));
}
if (extensionManager != null) {
ExtensionResultHolder resultHolder = new ExtensionResultHolder();
extensionManager.getProxy().postAdd(quantityBasedRule, resultHolder);
if (resultHolder.getResult() != null) {
quantityBasedRule = (QuantityBasedRule) resultHolder.getResult();
}
}
if (cascadeExtensionManager != null) {
ExtensionResultHolder resultHolder = new ExtensionResultHolder();
cascadeExtensionManager.getProxy().postCascadeAdd(quantityBasedRule, dto, resultHolder);
if (resultHolder.getResult() != null) {
quantityBasedRule = (QuantityBasedRule) resultHolder.getResult();
}
}
updatedRules.add(quantityBasedRule);
dirty = true;
}
}
// if an item was not included in the comprehensive submit from the client, we can assume that the
// listing was deleted, so we remove it here.
Iterator<QuantityBasedRule> itr = criteriaList.iterator();
// Since this class explicitly removes the quantity based rule - we must also preserve the id of the element
// as the CacheInvalidationProducer will need this in order to remove each collection member cache instance as well.
BroadleafRequestContext context = BroadleafRequestContext.getBroadleafRequestContext();
context.getAdditionalProperties().put("deletedQuantityBasedRules", new HashSet<QuantityBasedRule>());
while (itr.hasNext()) {
checkForRemove: {
QuantityBasedRule original = itr.next();
for (QuantityBasedRule quantityBasedRule : updatedRules) {
Long id = sandBoxHelper.getOriginalId(quantityBasedRule);
boolean isMatch = original.getId().equals(id) || original.getId().equals(quantityBasedRule.getId());
if (isMatch) {
break checkForRemove;
}
}
((Set<QuantityBasedRule>) context.getAdditionalProperties().get("deletedQuantityBasedRules")).add(original);
em.remove(original);
itr.remove();
dirty = true;
}
}
ObjectMapper mapper = new ObjectMapper();
String json;
try {
json = mapper.writeValueAsString(dw);
} catch (Exception e) {
throw new RuntimeException(e);
}
property.setValue(json);
}
}
return dirty;
}
use of org.broadleafcommerce.openadmin.web.rulebuilder.MVELTranslationException in project BroadleafCommerce by BroadleafCommerce.
the class RuleFieldValidator method validate.
@Override
public PropertyValidationResult validate(PopulateValueRequest populateValueRequest, Serializable instance) {
if (canHandleValidation(populateValueRequest)) {
DataDTOToMVELTranslator translator = new DataDTOToMVELTranslator();
EntityManager em = populateValueRequest.getPersistenceManager().getDynamicEntityDao().getStandardEntityManager();
if (SupportedFieldType.RULE_SIMPLE.equals(populateValueRequest.getMetadata().getFieldType()) || SupportedFieldType.RULE_SIMPLE_TIME.equals(populateValueRequest.getMetadata().getFieldType())) {
// AntiSamy HTML encodes the rule JSON - pass the unHTMLEncoded version
DataWrapper dw = ruleFieldExtractionUtility.convertJsonToDataWrapper(populateValueRequest.getProperty().getUnHtmlEncodedValue());
if (dw != null && StringUtils.isNotEmpty(dw.getError())) {
return new PropertyValidationResult(false, "Could not serialize JSON from rule builder: " + dw.getError());
}
if (dw == null || StringUtils.isEmpty(dw.getError())) {
try {
String mvel = ruleFieldExtractionUtility.convertSimpleMatchRuleJsonToMvel(translator, RuleIdentifier.ENTITY_KEY_MAP.get(populateValueRequest.getMetadata().getRuleIdentifier()), populateValueRequest.getMetadata().getRuleIdentifier(), dw);
} catch (MVELTranslationException e) {
return new PropertyValidationResult(false, getMvelParsingErrorMesage(dw, e));
}
}
}
if (SupportedFieldType.RULE_WITH_QUANTITY.equals(populateValueRequest.getMetadata().getFieldType())) {
Collection<QuantityBasedRule> existingRules;
try {
existingRules = (Collection<QuantityBasedRule>) populateValueRequest.getFieldManager().getFieldValue(instance, populateValueRequest.getProperty().getName());
} catch (FieldNotAvailableException e) {
return new PropertyValidationResult(false, "Could not access rule field on Java object to set values");
} catch (IllegalAccessException e) {
return new PropertyValidationResult(false, "Could not access rule field on Java object to set values");
}
String entityKey = RuleIdentifier.ENTITY_KEY_MAP.get(populateValueRequest.getMetadata().getRuleIdentifier());
String jsonPropertyValue = populateValueRequest.getProperty().getUnHtmlEncodedValue();
String fieldService = populateValueRequest.getMetadata().getRuleIdentifier();
if (!StringUtils.isEmpty(jsonPropertyValue)) {
DataWrapper dw = ruleFieldExtractionUtility.convertJsonToDataWrapper(jsonPropertyValue);
if (dw != null && StringUtils.isNotEmpty(dw.getError())) {
return new PropertyValidationResult(false, "Could not serialize JSON from rule builder: " + dw.getError());
}
if (dw != null && StringUtils.isEmpty(dw.getError())) {
for (DataDTO dto : dw.getData()) {
if (dto.getPk() != null) {
boolean foundIdToUpdate = false;
for (QuantityBasedRule quantityBasedRule : existingRules) {
Long sandBoxVersionId = sandBoxHelper.getSandBoxVersionId(quantityBasedRule.getClass(), dto.getPk());
if (sandBoxVersionId == null) {
sandBoxVersionId = dto.getPk();
}
if (sandBoxVersionId.equals(quantityBasedRule.getId()) || sandBoxHelper.isRelatedToParentCatalogIds(quantityBasedRule, dto.getPk())) {
foundIdToUpdate = true;
try {
String mvel = ruleFieldExtractionUtility.convertDTOToMvelString(translator, entityKey, dto, fieldService);
} catch (MVELTranslationException e) {
return new PropertyValidationResult(false, getMvelParsingErrorMesage(dw, e));
}
}
}
if (!foundIdToUpdate) {
return new PropertyValidationResult(false, "Tried to update QuantityBasedRule with ID " + dto.getPk() + " but that rule does not exist");
}
} else {
// This is a new rule, just validate that it parses successfully
try {
ruleFieldExtractionUtility.convertDTOToMvelString(translator, entityKey, dto, fieldService);
} catch (MVELTranslationException e) {
return new PropertyValidationResult(false, getMvelParsingErrorMesage(dw, e));
}
}
}
}
}
}
}
return new PropertyValidationResult(true);
}
Aggregations