Skip to content

Commit

Permalink
entity: add new entity-listener tag
Browse files Browse the repository at this point in the history
Allow entities to declare listeners that'll be invoked during lifecycle.
This allows to perform consistency checks in a more reliable way than
overriding repository save() method as listeners are called even in case
of cascading persist.
Annotation has been modified to allow avoiding imports since for
@EntityListeners we need to pass .class which doesn't play well with
autoimport. Alternative would have been to import and append '.class' to
annotation param by the mean of another boolean parameter.
  • Loading branch information
Sébastien Le Ray committed Apr 9, 2018
1 parent 6f84823 commit 36c9e28
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 15 deletions.
24 changes: 24 additions & 0 deletions axelor-core/src/main/resources/domain-models.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,14 @@
<xsd:documentation>Entity represent domain model.</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="entity-listener" type="dm:EntityListener" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
Define class containing annotated methods (@PrePersist, etc.) that will be called
during entity lifecycle.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="string" type="dm:String">
<xsd:annotation>
Expand Down Expand Up @@ -1143,4 +1151,20 @@
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>

<xsd:complexType name="EntityListener">
<xsd:attribute name="listenerClass" use="required">
<xsd:simpleType>
<xsd:annotation>
<xsd:documentation>
FQDN of the listener class
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:pattern
value="(([a-z][a-zA-Z0-9_]+)(\.[a-z][a-zA-Z0-9_]+)*\.)?([A-Z][a-zA-Z0-9_]+)" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:schema>
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Annotation {
boolean empty

Entity entity

ImportManager importManager

Annotation(Entity entity, String name) {
Expand All @@ -37,7 +37,7 @@ class Annotation {
this(entity.importManager, name, empty)
this.entity = entity
}

Annotation(ImportManager importer, String name, boolean empty) {
this.importManager = importer
this.name = "@" + importer.importType(name)
Expand Down Expand Up @@ -91,13 +91,17 @@ class Annotation {
}

Annotation add(String param, List<?> values, boolean quote, boolean unwrapSingle) {
add(param, values, quote, unwrapSingle, true);
}

Annotation add(String param, List<?> values, boolean quote, boolean unwrapSingle, boolean importTypes) {
if (values == null)
return this;

values = values.collect {
if (it instanceof Annotation)
return it
quote ? this.quote(it) : importManager.importType(it)
quote ? this.quote(it) : (importTypes ? importManager.importType(it) : it)
}

def value = unwrapSingle && values.size() == 1 ? values[0] : wrap(values)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import com.axelor.common.Inflector
import com.axelor.tools.x2j.Utils

class Entity {

private static Set<String> INTERNAL_PACKAGES = [
'com.axelor.auth.db',
'com.axelor.meta.db',
Expand All @@ -38,7 +38,7 @@ class Entity {
String module

String namespace

String repoNamespace

String tablePrefix
Expand Down Expand Up @@ -75,16 +75,18 @@ class Entity {

List<String> finders

List<String> listeners

Map<String, Property> propertyMap

Property nameField

private Repository repository

private ImportManager importManager

private String extraImports

private String extraCode

private Track track
Expand Down Expand Up @@ -149,12 +151,13 @@ class Entity {
repository = new Repository(this)
repository.concrete = node.@repository != "abstract"
}

properties = []
propertyMap = [:]
constraints = []
indexes = []
finders = []
listeners = []
extraCode = null

if (interfaces) {
Expand Down Expand Up @@ -202,6 +205,9 @@ class Entity {
case "track":
track = new Track(this, it)
break
case "entity-listener":
listeners += it.'@listenerClass'.text() + '.class'
break
default:
Property field = new Property(this, it)
if (modelClass && !field.simple) {
Expand Down Expand Up @@ -232,7 +238,7 @@ class Entity {
properties.add(propertyMap.get("attrs"));
}
}

Repository getRepository() {
return this.repository
}
Expand All @@ -247,7 +253,7 @@ class Entity {
}

void merge(Entity other) {

for (Property prop : other.properties) {
Property existing = propertyMap.get(prop.name)
if (isCompatible(existing, prop)) {
Expand All @@ -263,10 +269,11 @@ class Entity {
}
}
}

indexes.addAll(other.indexes)
constraints.addAll(other.constraints)
finders.addAll(other.finders)
listeners.addAll(other.listeners)

if (other.track) {
if (track == null || other.track.replace) {
Expand Down Expand Up @@ -309,7 +316,7 @@ class Entity {
if (!interfaces || interfaces.trim() == "") return ""
return " implements " + interfaces
}

String getExtendsImplementStmt() {
if (modelClass) {
importType('javax.persistence.Transient')
Expand All @@ -319,7 +326,7 @@ class Entity {
}
return " extends " + getBaseClass() + getImplementStmt()
}

String getAbstractStmt() {
return modelClass ? "abstract " : ""
}
Expand Down Expand Up @@ -380,7 +387,7 @@ class Entity {
String getExtraCode() {
return stripCode(extraCode, "\n\t");
}

String getExtraImports() {
if (!extraImports || extraImports.trim().isEmpty()) return "";
return "\n" + Utils.stripCode(extraImports, "\n") + "\n"
Expand All @@ -389,7 +396,7 @@ class Entity {
private List<Property> getHashables() {
return properties.findAll { p -> p.hashKey }
}

boolean isModelClass() {
return modelClass;
}
Expand Down Expand Up @@ -487,6 +494,7 @@ class Entity {
all += $strategy()
all += $track()
all += $mappedSuperClass()
all += $listeners()

return all.grep { it != null }.flatten()
.grep { Annotation a -> !a.empty }
Expand Down Expand Up @@ -569,6 +577,12 @@ class Entity {
return track.$track()
}

Annotation $listeners() {
if(listeners.empty) return null;
return new Annotation(this, "javax.persistence.EntityListeners")
.add("value", listeners, false, false, false)
}

@Override
String toString() {
def names = fields.collect { it.name }
Expand Down

0 comments on commit 36c9e28

Please sign in to comment.