diff --git a/modules/core/test/com/haulmont/cuba/namepattern/NamePatternTest.java b/modules/core/test/com/haulmont/cuba/namepattern/NamePatternTest.java
new file mode 100644
index 0000000000..b7f4902551
--- /dev/null
+++ b/modules/core/test/com/haulmont/cuba/namepattern/NamePatternTest.java
@@ -0,0 +1,85 @@
+package com.haulmont.cuba.namepattern;
+
+import com.haulmont.cuba.testmodel.namepattern.MethodNamePatternEntity;
+import com.haulmont.cuba.testmodel.namepattern.SpelNamePatternEntity;
+import com.haulmont.cuba.testmodel.namepattern.SimpleNamePatternEntity;
+import com.haulmont.cuba.testsupport.TestContainer;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author Rushan Zagidullin
+ * @since 17.07.2018
+ */
+public class NamePatternTest {
+
+ @ClassRule
+ public static TestContainer container = TestContainer.Common.INSTANCE;
+
+ SimpleNamePatternEntity simpleNamePatternEntity1;
+ SimpleNamePatternEntity simpleNamePatternEntity2;
+ MethodNamePatternEntity methodNamePatternEntity1;
+ MethodNamePatternEntity methodNamePatternEntity2;
+ SpelNamePatternEntity spelNamePatternEntity1;
+ SpelNamePatternEntity spelNamePatternEntity2;
+
+ @SuppressWarnings("IncorrectCreateEntity")
+ @Before
+ public void setUp() {
+ simpleNamePatternEntity1 = new SimpleNamePatternEntity();
+ simpleNamePatternEntity1.setName("name1");
+
+ simpleNamePatternEntity2 = new SimpleNamePatternEntity();
+ simpleNamePatternEntity2.setName(null);
+
+ methodNamePatternEntity1 = new MethodNamePatternEntity();
+ methodNamePatternEntity1.setName("name1");
+
+ methodNamePatternEntity2 = new MethodNamePatternEntity();
+ methodNamePatternEntity2.setName(null);
+
+ spelNamePatternEntity1 = new SpelNamePatternEntity();
+ spelNamePatternEntity1.setName("name1");
+ spelNamePatternEntity1.setNumber(5);
+ spelNamePatternEntity1.setNumber2(null);
+
+ spelNamePatternEntity2 = new SpelNamePatternEntity();
+ spelNamePatternEntity2.setName("name2");
+ spelNamePatternEntity2.setNumber(null);
+ spelNamePatternEntity2.setNumber2(null);
+ }
+
+ @Test
+ public void testSimpleNamePatternEntity1() {
+ assertEquals("name1", simpleNamePatternEntity1.getInstanceName());
+ }
+
+ @Test
+ public void testSimpleNamePatternEntity2() {
+ assertEquals("", simpleNamePatternEntity2.getInstanceName());
+ }
+
+ @Test
+ public void testMethodNamePatternEntity1() {
+ assertEquals("name1", methodNamePatternEntity1.getInstanceName());
+ }
+
+ @Test
+ public void testMethodNamePatternEntity2() {
+ assertNull(methodNamePatternEntity2.getInstanceName());
+ }
+
+ @Test
+ public void testComplexNamePatternEntity1() {
+ assertEquals("Hello, my name is name1. Sum of numbers = 5", spelNamePatternEntity1.getInstanceName());
+ }
+
+ @Test
+ public void testComplexNamePatternEntity2() {
+ assertEquals("Hello, my name is name2. Sum of numbers = 0", spelNamePatternEntity2.getInstanceName());
+ }
+}
diff --git a/modules/core/test/com/haulmont/cuba/namepattern/NamePatternTestBean.java b/modules/core/test/com/haulmont/cuba/namepattern/NamePatternTestBean.java
new file mode 100644
index 0000000000..49e94fbbf3
--- /dev/null
+++ b/modules/core/test/com/haulmont/cuba/namepattern/NamePatternTestBean.java
@@ -0,0 +1,31 @@
+package com.haulmont.cuba.namepattern;
+
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * @author Rushan Zagidullin
+ * @since 17.07.2018
+ */
+@Component("cuba_NamePatternTestBean")
+public class NamePatternTestBean {
+ public int sum(Integer... values) {
+ return Optional.ofNullable(values)
+ .map(ints -> Arrays.stream(ints)
+ .filter(Objects::nonNull)
+ .mapToInt(Integer::intValue)
+ .sum())
+ .orElse(0);
+ }
+
+ public String concat(String... values) {
+ return Optional.ofNullable(values)
+ .map(strings -> Arrays.stream(strings)
+ .collect(Collectors.joining()))
+ .orElse("");
+ }
+}
diff --git a/modules/core/test/com/haulmont/cuba/testmodel/namepattern/MethodNamePatternEntity.java b/modules/core/test/com/haulmont/cuba/testmodel/namepattern/MethodNamePatternEntity.java
new file mode 100644
index 0000000000..6c388c4162
--- /dev/null
+++ b/modules/core/test/com/haulmont/cuba/testmodel/namepattern/MethodNamePatternEntity.java
@@ -0,0 +1,34 @@
+package com.haulmont.cuba.testmodel.namepattern;
+
+import com.haulmont.chile.core.annotations.NamePattern;
+import com.haulmont.cuba.core.entity.StandardEntity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+/**
+ * @author Rushan Zagidullin
+ * @since 17.07.2018
+ */
+@NamePattern("#formatName|name")
+@Table(name = "TEST_METHOD_NAME_PATTERN_ENTITY")
+@Entity(name = "test$MethodNamePatternEntity")
+public class MethodNamePatternEntity extends StandardEntity {
+ private static final long serialVersionUID = -833743669993760614L;
+
+ @Column(name = "NAME")
+ protected String name;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String formatName() {
+ return getName();
+ }
+}
\ No newline at end of file
diff --git a/modules/core/test/com/haulmont/cuba/testmodel/namepattern/SimpleNamePatternEntity.java b/modules/core/test/com/haulmont/cuba/testmodel/namepattern/SimpleNamePatternEntity.java
new file mode 100644
index 0000000000..c463c72f47
--- /dev/null
+++ b/modules/core/test/com/haulmont/cuba/testmodel/namepattern/SimpleNamePatternEntity.java
@@ -0,0 +1,30 @@
+package com.haulmont.cuba.testmodel.namepattern;
+
+import com.haulmont.chile.core.annotations.NamePattern;
+import com.haulmont.cuba.core.entity.StandardEntity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+/**
+ * @author Rushan Zagidullin
+ * @since 17.07.2018
+ */
+@NamePattern("%s|name")
+@Table(name = "TEST_SIMPLE_NAME_PATTERN_ENTITY")
+@Entity(name = "test$SimpleNamePatternEntity")
+public class SimpleNamePatternEntity extends StandardEntity {
+ private static final long serialVersionUID = -833743669993760614L;
+
+ @Column(name = "NAME")
+ protected String name;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
\ No newline at end of file
diff --git a/modules/core/test/com/haulmont/cuba/testmodel/namepattern/SpelNamePatternEntity.java b/modules/core/test/com/haulmont/cuba/testmodel/namepattern/SpelNamePatternEntity.java
new file mode 100644
index 0000000000..1a81f09d3e
--- /dev/null
+++ b/modules/core/test/com/haulmont/cuba/testmodel/namepattern/SpelNamePatternEntity.java
@@ -0,0 +1,52 @@
+package com.haulmont.cuba.testmodel.namepattern;
+
+import com.haulmont.chile.core.annotations.NamePattern;
+import com.haulmont.cuba.core.entity.StandardEntity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+/**
+ * @author Rushan Zagidullin
+ * @since 17.07.2018
+ */
+@NamePattern("#{@cuba_NamePatternTestBean.concat('Hello, my name is ', name, '. Sum of numbers = ', @cuba_NamePatternTestBean.sum(number, number2))}|name")
+@Table(name = "TEST_SPEL_NAME_PATTERN_ENTITY")
+@Entity(name = "test$SpelNamePatternEntity")
+public class SpelNamePatternEntity extends StandardEntity {
+ private static final long serialVersionUID = -833743669993760614L;
+
+ @Column(name = "NAME")
+ protected String name;
+
+ @Column(name = "NUMBER")
+ protected Integer number;
+
+ @Column(name = "NUMBER_2")
+ protected Integer number2;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Integer getNumber() {
+ return number;
+ }
+
+ public void setNumber(Integer number) {
+ this.number = number;
+ }
+
+ public Integer getNumber2() {
+ return number2;
+ }
+
+ public void setNumber2(Integer number2) {
+ this.number2 = number2;
+ }
+}
\ No newline at end of file
diff --git a/modules/core/test/cuba-test-persistence.xml b/modules/core/test/cuba-test-persistence.xml
index b79535257d..6dce56295e 100644
--- a/modules/core/test/cuba-test-persistence.xml
+++ b/modules/core/test/cuba-test-persistence.xml
@@ -91,5 +91,9 @@
com.haulmont.cuba.testmodel.jpa_cascade.JpaCascadeItem
com.haulmont.cuba.testmodel.not_persistent.CustomerWithNonPersistentRef
+
+ com.haulmont.cuba.testmodel.namepattern.MethodNamePatternEntity
+ com.haulmont.cuba.testmodel.namepattern.SimpleNamePatternEntity
+ com.haulmont.cuba.testmodel.namepattern.SpelNamePatternEntity
\ No newline at end of file
diff --git a/modules/global/src/com/haulmont/chile/core/model/utils/InstanceUtils.java b/modules/global/src/com/haulmont/chile/core/model/utils/InstanceUtils.java
index e681a77b34..ea2190a709 100644
--- a/modules/global/src/com/haulmont/chile/core/model/utils/InstanceUtils.java
+++ b/modules/global/src/com/haulmont/chile/core/model/utils/InstanceUtils.java
@@ -25,8 +25,16 @@
import com.haulmont.cuba.core.global.DevelopmentException;
import com.haulmont.cuba.core.global.Messages;
import com.haulmont.cuba.core.global.MetadataTools;
+import com.haulmont.cuba.core.sys.AppContext;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
+import org.springframework.context.expression.BeanFactoryResolver;
+import org.springframework.expression.BeanResolver;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.common.TemplateParserContext;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
import javax.annotation.Nullable;
import java.lang.reflect.InvocationTargetException;
@@ -226,6 +234,9 @@ public static String getInstanceName(Instance instance) {
throw new RuntimeException("Error getting instance name", e);
}
}
+ if (rec.isSpEL) {
+ return evaluateSpEL(instance, rec.format);
+ }
// lazy initialized messages, used only for enum values
Messages messages = null;
@@ -252,6 +263,15 @@ public static String getInstanceName(Instance instance) {
}
}
+ public static String evaluateSpEL(Instance instance, String format) {
+ ExpressionParser parser = new SpelExpressionParser();
+ StandardEvaluationContext evaluationContext = new StandardEvaluationContext(instance);
+ BeanResolver beanResolver = new BeanFactoryResolver(AppContext.getApplicationContext());
+ evaluationContext.setBeanResolver(beanResolver);
+ Expression expression = parser.parseExpression(format, new TemplateParserContext());
+ return expression.getValue(evaluationContext, String.class);
+ }
+
/**
* Parse a name pattern defined by {@link NamePattern} annotation.
* @param metaClass entity meta-class
@@ -272,10 +292,13 @@ public static NamePatternRec parseNamePattern(MetaClass metaClass) {
String format = StringUtils.substring(pattern, 0, pos);
String trimmedFormat = format.trim();
- String methodName = trimmedFormat.startsWith("#") ? trimmedFormat.substring(1) : null;
+ boolean isSpEL = trimmedFormat.startsWith("#{");
+ String methodName = trimmedFormat.startsWith("#") && !isSpEL ?
+ trimmedFormat.substring(1) :
+ null;
String fieldsStr = StringUtils.substring(pattern, pos + 1);
String[] fields = INSTANCE_NAME_SPLIT_PATTERN.split(fieldsStr);
- return new NamePatternRec(format, methodName, fields);
+ return new NamePatternRec(format, methodName, fields, isSpEL);
}
public static class NamePatternRec {
@@ -291,11 +314,16 @@ public static class NamePatternRec {
* Array of property names
*/
public final String[] fields;
+ /**
+ * Is name pattern described as SpEL
+ */
+ public final boolean isSpEL;
- public NamePatternRec(String format, String methodName, String[] fields) {
+ public NamePatternRec(String format, String methodName, String[] fields, boolean isSpEL) {
this.fields = fields;
this.format = format;
this.methodName = methodName;
+ this.isSpEL = isSpEL;
}
}