All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.memority.toolkit.rule.api.RuleDefinition Maven / Gradle / Ivy

Go to download

This artifact provides the API classes that are necessary to implement the contracts of Memority configuration Rules.

There is a newer version: 3.43.1
Show newest version
/*
 * Copyright (c) 2016-2023 Memority. All Rights Reserved.
 *
 * This file is part of Memority Toolkit API , a Memority project.
 *
 * This file is released under the Memority Public Artifacts End-User License Agreement,
 * see 
 * Unauthorized copying of this file, via any medium is strictly prohibited.
 */
package com.memority.toolkit.rule.api;

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.eclipse.persistence.oxm.annotations.XmlCDATA;
import org.eclipse.persistence.oxm.annotations.XmlReadOnly;
import org.hibernate.validator.constraints.Length;

import javax.validation.Valid;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.*;
import java.io.Serializable;
import java.util.regex.Pattern;

/**
 * RuleDefinition is a serializable object used to describe a Rule.
 * 

It contains:

*
    *
  1. A description of the rule, either: *
      *
    • a script in Groovy
    • *
    • a classLabel (class) describing the builtin Java class to use
    • *
    • or a delegateRef (ref) pointing to the externally configured Rule to use
    • *
    *
  2. *
  3. an optional configuration (config) for java rules
  4. *
*/ @JsonInclude(JsonInclude.Include.NON_NULL) @XmlRootElement(name = XmlConstants.NAME_ELEMENT_RULEDEFINITION) @XmlType(name = XmlConstants.NAME_TYPE_RULEDEFINITION) @XmlAccessorType(XmlAccessType.PROPERTY) @EqualsAndHashCode public class RuleDefinition implements Serializable { private static final Pattern RULE_SPEC_JAVARULE_PATTERN = Pattern.compile("^[a-zA-Z0-9_]+[a-zA-Z0-9\\-_]*[a-zA-Z0-9]+:.*$"); @Length(max = 1_048_576) //to be coherent with HBM private String script; private String delegateRef; private String classLabel; @Valid private RuleConfiguration configuration; private LegacyParams legacyParams; @SuppressWarnings({"unused", "squid:S2637"}) // for serialization protected RuleDefinition() { } public RuleDefinition(String script, String classLabel, String delegateRef, RuleConfiguration configuration) { this(script, classLabel, delegateRef, configuration, null, null, null); } @JsonCreator public RuleDefinition( // new, simplified configuration serialization @JsonProperty(value = "script") String script, @JsonProperty(value = "class") String classLabel, @JsonProperty(value = "ref") String delegateRef, @JsonProperty(value = "config") RuleConfiguration config, // old school configuration serialization (some stuff we do not even care about // anymore, such as type and category) @JsonProperty(value = "engineType") RuleEngineType engineType, @JsonProperty(value = "ruleSpec") String ruleSpec, @JsonProperty(value = "configuration") RuleConfiguration configuration) { if (ruleSpec != null) { // Old style this.legacyParams = new LegacyParams(engineType, ruleSpec, configuration); this.setupFromLegacyParams(); } else { this.setDelegateRef(delegateRef); this.setClassLabel(classLabel); this.setScript(script); this.configuration = config; } } private void setupFromLegacyParams() { if (this.legacyParams == null) { return; } RuleEngineType ruleEngineType = this.legacyParams.ruleEngineType; String ruleSpec = this.legacyParams.ruleSpec; String content = ruleSpec; if (ruleEngineType == RuleEngineType.JAVA && ruleSpec != null && RULE_SPEC_JAVARULE_PATTERN.matcher(ruleSpec.trim()).matches()) { // Extract label as first part of rule spec content = ruleSpec.substring(0, ruleSpec.indexOf(':')); } switch (this.legacyParams.ruleEngineType) { case GROOVY: setScript(content); break; case JAVA: setClassLabel(content); // In case of JSON, the ruleConfiguration in legacy will be set (handled as the old 'configuration' // json property) // In case of XML however, the property was already 'config' and it's not mapped to legacy, so we // are careful to propagate the legacy configuration _only_ if there is one if (this.legacyParams.ruleConfiguration != null) { setConfig(this.legacyParams.ruleConfiguration); } break; case DELEGATE: setDelegateRef(content); break; } // Erase legacy params into oblivion this.legacyParams = null; } /** * Get the configured engine type for this rule definition. * * @throws IllegalStateException if the engine type cannot be infered (this error is ignored when resolving relations and is catched by validation). * @return The rule engine type. */ @XmlTransient @JsonIgnore public RuleEngineType getEngineType() { if (StringUtils.isNotBlank(this.script)) { return RuleEngineType.GROOVY; } else if (StringUtils.isNotBlank(this.classLabel)) { return RuleEngineType.JAVA; } else if (StringUtils.isNotBlank(this.delegateRef)) { return RuleEngineType.DELEGATE; } else { throw new IllegalStateException("RuleDefinition should have either a script, class label or delegate ref. Cannot infer engine type!"); } } @XmlAttribute(name = "engineType") @XmlReadOnly @JsonProperty(access = JsonProperty.Access.READ_ONLY) @Deprecated public RuleEngineType getLegacyRuleEngineType() { return this.legacyParams == null ? null : this.legacyParams.ruleEngineType; } @Deprecated public void setLegacyRuleEngineType(RuleEngineType ruleEngineType) { if (this.legacyParams == null) { this.legacyParams = new LegacyParams(); } this.legacyParams.ruleEngineType = ruleEngineType; } @XmlElement(name = "spec") @XmlReadOnly @JsonProperty(access = JsonProperty.Access.READ_ONLY) @Deprecated public String getLegacyRuleSpec() { return this.legacyParams == null ? null : this.legacyParams.ruleSpec; } /** * This method is here solely with the purpose of supporting old style deserialization * * @param ruleSpec the serialized representation */ @Deprecated public void setLegacyRuleSpec(String ruleSpec) { if (this.legacyParams == null) { this.legacyParams = new LegacyParams(); } this.legacyParams.ruleSpec = ruleSpec; } @XmlTransient @JsonProperty(value = "configuration", access = JsonProperty.Access.READ_ONLY) @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class") @Deprecated public RuleConfiguration getLegacyRuleConfiguration() { return this.legacyParams == null ? null : this.legacyParams.ruleConfiguration; } /** * This method is here solely with the purpose of supporting old style deserialization * * @param ruleConfiguration the rule configuration */ @Deprecated public void setLegacyRuleConfiguration(RuleConfiguration ruleConfiguration) { if (this.legacyParams == null) { this.legacyParams = new LegacyParams(); } this.legacyParams.ruleConfiguration = ruleConfiguration; } /** * This method is there to infer correct content in case of legacy XML deserialization, * where the engine inferring properties (script, class, ref) have not been set. */ void afterUnmarshal(Unmarshaller u, Object parent) { setupFromLegacyParams(); } @XmlElement(name = "config") @JsonProperty("config") @JsonTypeInfo( use = JsonTypeInfo.Id.CUSTOM, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "class", defaultImpl = RuleConfiguration.EmptyRuleConfiguration.class // required to handle missing 'class' but present 'config' ) @JsonTypeIdResolver(RuleConfiguration.RuleConfigurationTypeIdResolver.class) public RuleConfiguration getConfig() { return configuration; } public void setConfig(RuleConfiguration configuration) { this.configuration = configuration; } @XmlAttribute(name = "class") @JsonProperty("class") public String getClassLabel() { return classLabel; } public void setClassLabel(String classLabel) { // Workaround issue in Jackson deserialization when there is a 'config' property but class is actually null. this.classLabel = "null".equals(classLabel) ? null : classLabel; } @XmlAttribute(name = "ref") @JsonProperty("ref") public String getDelegateRef() { return delegateRef; } public void setDelegateRef(String delegateRef) { this.delegateRef = delegateRef; } @XmlCDATA @JsonProperty("script") public String getScript() { return this.script; } public void setScript(String script) { this.script = script; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); } @Data @NoArgsConstructor @AllArgsConstructor private static class LegacyParams { RuleEngineType ruleEngineType; String ruleSpec; RuleConfiguration ruleConfiguration; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy