You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2020/11/19 14:10:28 UTC

[cayenne] branch master updated (9b465cc -> d846a40)

This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git.


    from 9b465cc  CAY-2691 MySQL driver 8.0.x stores LocalDateTime differently than 5.1.x
     new c5de542  Added the ability to create callbacks via annotations
     new c84f394  Added annotations map
     new b25e5ac  Merge remote-tracking branch 'parent/pr/439' into asf-master
     new d846a40  CAY-2692 Add entity lifecycle callbacks via annotated methods

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 RELEASE-NOTES.txt                                  |  1 +
 .../org/apache/cayenne/map/EntityResolver.java     | 38 ++++++++++
 .../java/org/apache/cayenne/map/AnnotationIT.java  | 82 ++++++++++++++++++++++
 .../testdo/annotation/ArtistAnnotation.java}       | 60 ++++++++++------
 .../testdo/annotation/auto/_ArtistAnnotation.java  | 68 +++++++++---------
 .../cayenne/unit/di/server/CayenneProjects.java    |  1 +
 .../cayenne/unit/di/server/SchemaBuilder.java      |  3 +-
 .../cayenne-project.xml}                           |  2 +-
 .../resources/annotation/datamapAnnotation.map.xml | 17 +++++
 9 files changed, 212 insertions(+), 60 deletions(-)
 create mode 100644 cayenne-server/src/test/java/org/apache/cayenne/map/AnnotationIT.java
 copy cayenne-server/src/{main/java/org/apache/cayenne/validation/ValidationException.java => test/java/org/apache/cayenne/testdo/annotation/ArtistAnnotation.java} (50%)
 copy cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java => cayenne-server/src/test/java/org/apache/cayenne/testdo/annotation/auto/_ArtistAnnotation.java (52%)
 copy cayenne-server/src/test/resources/{cayenne-compound.xml => annotation/cayenne-project.xml} (90%)
 create mode 100644 cayenne-server/src/test/resources/annotation/datamapAnnotation.map.xml


[cayenne] 02/04: Added annotations map

Posted by nt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit c84f39435a91b8e98ec5e4cb2e199569ddadd8ea
Author: andreykravchenko <an...@objectstyle.com>
AuthorDate: Thu Nov 12 12:26:08 2020 +0300

    Added annotations map
---
 .../org/apache/cayenne/map/EntityResolver.java     | 42 ++++++++++++----------
 1 file changed, 23 insertions(+), 19 deletions(-)

diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
index ebe7171..cb66101 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
@@ -22,10 +22,9 @@ package org.apache.cayenne.map;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
+import java.util.*;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.cayenne.Persistent;
@@ -147,23 +146,14 @@ public class EntityResolver implements MappingNamespace, Serializable {
             for (ObjEntity entity : getObjEntities()) {
                 Class<?> entityClass = entity.getJavaClass();
 
+                Map<Class, LifecycleEvent> annotationsMap = createAnnotationsMap();
+
                 for (Method m : entityClass.getDeclaredMethods()) {
-                    if (m.isAnnotationPresent(PostAdd.class)) {
-                        callbackRegistry.addCallback(LifecycleEvent.POST_ADD, entityClass, m.getName());
-                    } else if (m.isAnnotationPresent(PrePersist.class)) {
-                        callbackRegistry.addCallback(LifecycleEvent.PRE_PERSIST, entityClass, m.getName());
-                    } else if (m.isAnnotationPresent(PostPersist.class)) {
-                        callbackRegistry.addCallback(LifecycleEvent.POST_PERSIST, entityClass, m.getName());
-                    } else if (m.isAnnotationPresent(PreUpdate.class)) {
-                        callbackRegistry.addCallback(LifecycleEvent.PRE_UPDATE, entityClass, m.getName());
-                    } else if (m.isAnnotationPresent(PostUpdate.class)) {
-                        callbackRegistry.addCallback(LifecycleEvent.POST_UPDATE, entityClass, m.getName());
-                    } else if (m.isAnnotationPresent(PreRemove.class)) {
-                        callbackRegistry.addCallback(LifecycleEvent.PRE_REMOVE, entityClass, m.getName());
-                    } else if (m.isAnnotationPresent(PostRemove.class)) {
-                        callbackRegistry.addCallback(LifecycleEvent.POST_REMOVE, entityClass, m.getName());
-                    } else if (m.isAnnotationPresent(PostLoad.class)) {
-                        callbackRegistry.addCallback(LifecycleEvent.POST_LOAD, entityClass, m.getName());
+                    Annotation[] annotations = m.getAnnotations();
+                    for (int i = 0; i < annotations.length; i++) {
+                        if (annotationsMap.containsKey(annotations[i].annotationType())) {
+                            callbackRegistry.addCallback(annotationsMap.get(annotations[i].annotationType()), entityClass, m.getName());
+                        }
                     }
                 }
 
@@ -622,4 +612,18 @@ public class EntityResolver implements MappingNamespace, Serializable {
     public void setValueComparisionStrategyFactory(ValueComparisonStrategyFactory valueComparisonStrategyFactory) {
         this.valueComparisonStrategyFactory = valueComparisonStrategyFactory;
     }
+
+    private Map<Class, LifecycleEvent> createAnnotationsMap() {
+        Map<Class, LifecycleEvent> annotationsMap = new HashMap<>();
+        annotationsMap.put(PostAdd.class, LifecycleEvent.POST_ADD);
+        annotationsMap.put(PrePersist.class, LifecycleEvent.PRE_PERSIST);
+        annotationsMap.put(PostPersist.class, LifecycleEvent.POST_PERSIST);
+        annotationsMap.put(PreUpdate.class, LifecycleEvent.PRE_UPDATE);
+        annotationsMap.put(PostUpdate.class, LifecycleEvent.POST_UPDATE);
+        annotationsMap.put(PreRemove.class, LifecycleEvent.PRE_REMOVE);
+        annotationsMap.put(PostRemove.class, LifecycleEvent.POST_REMOVE);
+        annotationsMap.put(PostLoad.class, LifecycleEvent.POST_LOAD);
+
+        return annotationsMap;
+    }
 }


[cayenne] 04/04: CAY-2692 Add entity lifecycle callbacks via annotated methods

Posted by nt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit d846a408ca432a533fbeaaeb822051f27e8cc32d
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Thu Nov 19 16:37:45 2020 +0300

    CAY-2692 Add entity lifecycle callbacks via annotated methods
---
 RELEASE-NOTES.txt                                  |  1 +
 .../org/apache/cayenne/map/EntityResolver.java     | 56 +++++++++++++---------
 2 files changed, 35 insertions(+), 22 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 50e0896..3874d10 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -14,6 +14,7 @@ Date:
 Changes/New Features:
 
 CAY-2689 ServerRuntime API: missing some variants of the performInTransaction() method
+CAY-2692 Add entity lifecycle callbacks via annotated methods
 
 Bug Fixes:
 
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
index cb66101..19deb97 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
@@ -24,12 +24,25 @@ import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
-import java.util.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
-import org.apache.cayenne.annotation.*;
+
+import org.apache.cayenne.annotation.PostAdd;
+import org.apache.cayenne.annotation.PostLoad;
+import org.apache.cayenne.annotation.PostPersist;
+import org.apache.cayenne.annotation.PostRemove;
+import org.apache.cayenne.annotation.PostUpdate;
+import org.apache.cayenne.annotation.PrePersist;
+import org.apache.cayenne.annotation.PreRemove;
+import org.apache.cayenne.annotation.PreUpdate;
 import org.apache.cayenne.reflect.ClassDescriptor;
 import org.apache.cayenne.reflect.ClassDescriptorMap;
 import org.apache.cayenne.reflect.FaultFactory;
@@ -56,6 +69,19 @@ public class EntityResolver implements MappingNamespace, Serializable {
     protected static final Logger logger = LoggerFactory.getLogger(EntityResolver.class);
     protected static AtomicLong incrementer = new AtomicLong();
 
+    protected static final Map<LifecycleEvent, Class<? extends Annotation>> LIFECYCLE_EVENT_MAP;
+    static {
+        LIFECYCLE_EVENT_MAP = new EnumMap<>(LifecycleEvent.class);
+        LIFECYCLE_EVENT_MAP.put(LifecycleEvent.POST_ADD, PostAdd.class);
+        LIFECYCLE_EVENT_MAP.put(LifecycleEvent.PRE_PERSIST, PrePersist.class);
+        LIFECYCLE_EVENT_MAP.put(LifecycleEvent.POST_PERSIST, PostPersist.class);
+        LIFECYCLE_EVENT_MAP.put(LifecycleEvent.PRE_UPDATE, PreUpdate.class);
+        LIFECYCLE_EVENT_MAP.put(LifecycleEvent.POST_UPDATE, PostUpdate.class);
+        LIFECYCLE_EVENT_MAP.put(LifecycleEvent.PRE_REMOVE, PreRemove.class);
+        LIFECYCLE_EVENT_MAP.put(LifecycleEvent.POST_REMOVE, PostRemove.class);
+        LIFECYCLE_EVENT_MAP.put(LifecycleEvent.POST_LOAD, PostLoad.class);
+    }
+
     protected Collection<DataMap> maps;
     protected transient MappingNamespace mappingCache;
     protected EntityResolver clientEntityResolver;
@@ -146,17 +172,16 @@ public class EntityResolver implements MappingNamespace, Serializable {
             for (ObjEntity entity : getObjEntities()) {
                 Class<?> entityClass = entity.getJavaClass();
 
-                Map<Class, LifecycleEvent> annotationsMap = createAnnotationsMap();
-
+                // load annotated methods
                 for (Method m : entityClass.getDeclaredMethods()) {
-                    Annotation[] annotations = m.getAnnotations();
-                    for (int i = 0; i < annotations.length; i++) {
-                        if (annotationsMap.containsKey(annotations[i].annotationType())) {
-                            callbackRegistry.addCallback(annotationsMap.get(annotations[i].annotationType()), entityClass, m.getName());
+                    LIFECYCLE_EVENT_MAP.forEach((eventType, annotationType) -> {
+                        if(m.getDeclaredAnnotation(annotationType) != null) {
+                            callbackRegistry.addCallback(eventType, entityClass, m.getName());
                         }
-                    }
+                    });
                 }
 
+                // load callback defined in the model
                 CallbackDescriptor[] callbacks = entity.getCallbackMap().getCallbacks();
                 for (CallbackDescriptor callback : callbacks) {
                     for (String method : callback.getCallbackMethods()) {
@@ -613,17 +638,4 @@ public class EntityResolver implements MappingNamespace, Serializable {
         this.valueComparisonStrategyFactory = valueComparisonStrategyFactory;
     }
 
-    private Map<Class, LifecycleEvent> createAnnotationsMap() {
-        Map<Class, LifecycleEvent> annotationsMap = new HashMap<>();
-        annotationsMap.put(PostAdd.class, LifecycleEvent.POST_ADD);
-        annotationsMap.put(PrePersist.class, LifecycleEvent.PRE_PERSIST);
-        annotationsMap.put(PostPersist.class, LifecycleEvent.POST_PERSIST);
-        annotationsMap.put(PreUpdate.class, LifecycleEvent.PRE_UPDATE);
-        annotationsMap.put(PostUpdate.class, LifecycleEvent.POST_UPDATE);
-        annotationsMap.put(PreRemove.class, LifecycleEvent.PRE_REMOVE);
-        annotationsMap.put(PostRemove.class, LifecycleEvent.POST_REMOVE);
-        annotationsMap.put(PostLoad.class, LifecycleEvent.POST_LOAD);
-
-        return annotationsMap;
-    }
 }


[cayenne] 01/04: Added the ability to create callbacks via annotations

Posted by nt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit c5de542a0f3977dae9835262c898c983b49fbe3e
Author: andreykravchenko <an...@objectstyle.com>
AuthorDate: Thu Nov 5 13:14:42 2020 +0300

    Added the ability to create callbacks via annotations
---
 .../org/apache/cayenne/map/EntityResolver.java     |  22 +++++
 .../java/org/apache/cayenne/map/AnnotationIT.java  |  82 ++++++++++++++++
 .../testdo/annotation/ArtistAnnotation.java        |  70 +++++++++++++
 .../testdo/annotation/auto/_ArtistAnnotation.java  | 108 +++++++++++++++++++++
 .../cayenne/unit/di/server/CayenneProjects.java    |   1 +
 .../cayenne/unit/di/server/SchemaBuilder.java      |   3 +-
 .../test/resources/annotation/cayenne-project.xml  |   7 ++
 .../resources/annotation/datamapAnnotation.map.xml |  17 ++++
 8 files changed, 309 insertions(+), 1 deletion(-)

diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
index 8b945da..ebe7171 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityResolver.java
@@ -22,6 +22,7 @@ package org.apache.cayenne.map;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -29,6 +30,7 @@ import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
+import org.apache.cayenne.annotation.*;
 import org.apache.cayenne.reflect.ClassDescriptor;
 import org.apache.cayenne.reflect.ClassDescriptorMap;
 import org.apache.cayenne.reflect.FaultFactory;
@@ -145,6 +147,26 @@ public class EntityResolver implements MappingNamespace, Serializable {
             for (ObjEntity entity : getObjEntities()) {
                 Class<?> entityClass = entity.getJavaClass();
 
+                for (Method m : entityClass.getDeclaredMethods()) {
+                    if (m.isAnnotationPresent(PostAdd.class)) {
+                        callbackRegistry.addCallback(LifecycleEvent.POST_ADD, entityClass, m.getName());
+                    } else if (m.isAnnotationPresent(PrePersist.class)) {
+                        callbackRegistry.addCallback(LifecycleEvent.PRE_PERSIST, entityClass, m.getName());
+                    } else if (m.isAnnotationPresent(PostPersist.class)) {
+                        callbackRegistry.addCallback(LifecycleEvent.POST_PERSIST, entityClass, m.getName());
+                    } else if (m.isAnnotationPresent(PreUpdate.class)) {
+                        callbackRegistry.addCallback(LifecycleEvent.PRE_UPDATE, entityClass, m.getName());
+                    } else if (m.isAnnotationPresent(PostUpdate.class)) {
+                        callbackRegistry.addCallback(LifecycleEvent.POST_UPDATE, entityClass, m.getName());
+                    } else if (m.isAnnotationPresent(PreRemove.class)) {
+                        callbackRegistry.addCallback(LifecycleEvent.PRE_REMOVE, entityClass, m.getName());
+                    } else if (m.isAnnotationPresent(PostRemove.class)) {
+                        callbackRegistry.addCallback(LifecycleEvent.POST_REMOVE, entityClass, m.getName());
+                    } else if (m.isAnnotationPresent(PostLoad.class)) {
+                        callbackRegistry.addCallback(LifecycleEvent.POST_LOAD, entityClass, m.getName());
+                    }
+                }
+
                 CallbackDescriptor[] callbacks = entity.getCallbackMap().getCallbacks();
                 for (CallbackDescriptor callback : callbacks) {
                     for (String method : callback.getCallbackMethods()) {
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/AnnotationIT.java b/cayenne-server/src/test/java/org/apache/cayenne/map/AnnotationIT.java
new file mode 100644
index 0000000..232cfc4
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/AnnotationIT.java
@@ -0,0 +1,82 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.map;
+
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.reflect.LifecycleCallbackRegistry;
+import org.apache.cayenne.testdo.annotation.ArtistAnnotation;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.junit.Test;
+
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.2
+ */
+@UseServerRuntime(CayenneProjects.ANNOTATION)
+public class AnnotationIT extends ServerCase {
+
+    @Inject
+    private ObjectContext objectContext;
+
+    @Test
+    public void testAvailableCallback() {
+
+        LifecycleCallbackRegistry lifecycleCallbackRegistry = objectContext.getEntityResolver().getCallbackRegistry();
+
+        assertFalse(lifecycleCallbackRegistry.isEmpty(LifecycleEvent.POST_ADD));
+        assertFalse(lifecycleCallbackRegistry.isEmpty(LifecycleEvent.PRE_PERSIST));
+        assertFalse(lifecycleCallbackRegistry.isEmpty(LifecycleEvent.POST_PERSIST));
+        assertFalse(lifecycleCallbackRegistry.isEmpty(LifecycleEvent.POST_LOAD));
+        assertFalse(lifecycleCallbackRegistry.isEmpty(LifecycleEvent.PRE_UPDATE));
+        assertFalse(lifecycleCallbackRegistry.isEmpty(LifecycleEvent.POST_UPDATE));
+        assertFalse(lifecycleCallbackRegistry.isEmpty(LifecycleEvent.PRE_REMOVE));
+        assertFalse(lifecycleCallbackRegistry.isEmpty(LifecycleEvent.POST_REMOVE));
+    }
+
+    @Test
+    public void testWorkCallback() {
+        ArtistAnnotation artist = objectContext.newObject(ArtistAnnotation.class);
+        assertEquals(artist.getPostCallback(), "testPostAdd");
+        assertNull(artist.getPreCallback());
+
+        objectContext.commitChanges();
+        assertEquals(artist.getPostCallback(), "testPostPersist");
+        assertEquals(artist.getPreCallback(), "testPrePersist");
+
+        artist = ObjectSelect.query(ArtistAnnotation.class).selectFirst(objectContext);
+        assertEquals(artist.getPostCallback(), "testPostLoad");
+
+        artist.setPostCallback(null);
+        objectContext.commitChanges();
+        assertEquals(artist.getPostCallback(), "testPostUpdate");
+        assertEquals(artist.getPreCallback(), "testPreUpdate");
+
+        objectContext.deleteObject(artist);
+        assertEquals(artist.getPreCallback(), "testPreRemove");
+        objectContext.commitChanges();
+        assertEquals(artist.getPostCallback(), "testPostRemove");
+    }
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/annotation/ArtistAnnotation.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/annotation/ArtistAnnotation.java
new file mode 100644
index 0000000..6435524
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/annotation/ArtistAnnotation.java
@@ -0,0 +1,70 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.testdo.annotation;
+
+import org.apache.cayenne.annotation.*;
+import org.apache.cayenne.testdo.annotation.auto._ArtistAnnotation;
+
+public class ArtistAnnotation extends _ArtistAnnotation {
+
+    private static final long serialVersionUID = 1L;
+
+    @PostAdd
+    protected void testPostAdd() {
+        postCallback = "testPostAdd";
+    }
+
+    @PostPersist
+    protected void testPostPersist() {
+        postCallback = "testPostPersist";
+    }
+
+    @PrePersist
+    protected void testPrePersist() {
+        preCallback = "testPrePersist";
+    }
+
+    @PostUpdate
+    protected void testPostUpdate() {
+        postCallback = "testPostUpdate";
+    }
+
+    @PreUpdate
+    protected void testPreUpdate() {
+        preCallback = "testPreUpdate";
+    }
+
+    @PostLoad
+    protected void testPostLoad() {
+        postCallback = "testPostLoad";
+    }
+
+    @PostRemove
+    protected void testPostRemove() {
+        postCallback = "testPostRemove";
+    }
+
+    @PreRemove
+    protected void testPreRemove() {
+        preCallback = "testPreRemove";
+    }
+
+    @Override
+    protected void onPostAdd() { }
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/annotation/auto/_ArtistAnnotation.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/annotation/auto/_ArtistAnnotation.java
new file mode 100644
index 0000000..5e52750
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/annotation/auto/_ArtistAnnotation.java
@@ -0,0 +1,108 @@
+package org.apache.cayenne.testdo.annotation.auto;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.StringProperty;
+
+/**
+ * Class _Artist was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _ArtistAnnotation extends BaseDataObject {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final String ID_PK_COLUMN = "ID";
+
+    public static final StringProperty<String> POST_CALLBACK = PropertyFactory.createString("postCallback", String.class);
+    public static final StringProperty<String> PRE_CALLBACK = PropertyFactory.createString("preCallback", String.class);
+
+    protected String postCallback;
+    protected String preCallback;
+
+
+    public void setPostCallback(String postCallback) {
+        beforePropertyWrite("postCallback", this.postCallback, postCallback);
+        this.postCallback = postCallback;
+    }
+
+    public String getPostCallback() {
+        beforePropertyRead("postCallback");
+        return this.postCallback;
+    }
+
+    public void setPreCallback(String preCallback) {
+        beforePropertyWrite("preCallback", this.preCallback, preCallback);
+        this.preCallback = preCallback;
+    }
+
+    public String getPreCallback() {
+        beforePropertyRead("preCallback");
+        return this.preCallback;
+    }
+
+    protected abstract void onPostAdd();
+
+    @Override
+    public Object readPropertyDirectly(String propName) {
+        if(propName == null) {
+            throw new IllegalArgumentException();
+        }
+
+        switch(propName) {
+            case "postCallback":
+                return this.postCallback;
+            case "preCallback":
+                return this.preCallback;
+            default:
+                return super.readPropertyDirectly(propName);
+        }
+    }
+
+    @Override
+    public void writePropertyDirectly(String propName, Object val) {
+        if(propName == null) {
+            throw new IllegalArgumentException();
+        }
+
+        switch (propName) {
+            case "postCallback":
+                this.postCallback = (String)val;
+                break;
+            case "preCallback":
+                this.preCallback = (String)val;
+                break;
+            default:
+                super.writePropertyDirectly(propName, val);
+        }
+    }
+
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        writeSerialized(out);
+    }
+
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        readSerialized(in);
+    }
+
+    @Override
+    protected void writeState(ObjectOutputStream out) throws IOException {
+        super.writeState(out);
+        out.writeObject(this.postCallback);
+        out.writeObject(this.preCallback);
+    }
+
+    @Override
+    protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        super.readState(in);
+        this.postCallback = (String)in.readObject();
+        this.preCallback = (String)in.readObject();
+    }
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
index 3d7d1e5..ccb392e 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
@@ -87,4 +87,5 @@ public class CayenneProjects {
     public static final String LAZY_ATTRIBUTES_PROJECT = "cayenne-lazy-attributes.xml";
     public static final String CAY_2666 = "cay2666/cayenne-cay-2666.xml";
     public static final String CAY_2641 = "cay2641/cayenne-cay-2641.xml";
+    public static final String ANNOTATION = "annotation/cayenne-project.xml";
 }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
index 8067005..bc154c6 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
@@ -82,7 +82,8 @@ public class SchemaBuilder {
 			"qualified.map.xml", "quoted-identifiers.map.xml", "inheritance-single-table1.map.xml",
 			"inheritance-vertical.map.xml", "oneway-rels.map.xml", "unsupported-distinct-types.map.xml",
 			"array-type.map.xml", "cay-2032.map.xml", "weighted-sort.map.xml", "hybrid-data-object.map.xml",
-			"java8.map.xml", "inheritance-with-enum.map.xml", "lazy-attributes.map.xml", "cay2666/datamap.map.xml", "cay2641/datamapLazy.map.xml" };
+			"java8.map.xml", "inheritance-with-enum.map.xml", "lazy-attributes.map.xml", "cay2666/datamap.map.xml", "cay2641/datamapLazy.map.xml",
+			"annotation/datamapAnnotation.map.xml" };
 
 	// hardcoded dependent entities that should be excluded
 	// if LOBs are not supported
diff --git a/cayenne-server/src/test/resources/annotation/cayenne-project.xml b/cayenne-server/src/test/resources/annotation/cayenne-project.xml
new file mode 100644
index 0000000..92f7f35
--- /dev/null
+++ b/cayenne-server/src/test/resources/annotation/cayenne-project.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/domain https://cayenne.apache.org/schema/10/domain.xsd"
+	 project-version="10">
+	<map name="datamapAnnotation"/>
+</domain>
diff --git a/cayenne-server/src/test/resources/annotation/datamapAnnotation.map.xml b/cayenne-server/src/test/resources/annotation/datamapAnnotation.map.xml
new file mode 100644
index 0000000..724ede8
--- /dev/null
+++ b/cayenne-server/src/test/resources/annotation/datamapAnnotation.map.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap https://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.testdo.annotation"/>
+	<db-entity name="artist_annotation">
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+		<db-attribute name="PostCallback" type="VARCHAR" length="15"/>
+		<db-attribute name="PreCallback" type="VARCHAR" length="15"/>
+	</db-entity>
+	<obj-entity name="ArtistAnnotation" className="org.apache.cayenne.testdo.annotation.ArtistAnnotation" dbEntityName="artist_annotation">
+		<obj-attribute name="postCallback" type="java.lang.String" db-attribute-path="PostCallback"/>
+		<obj-attribute name="preCallback" type="java.lang.String" db-attribute-path="PreCallback"/>
+		<post-add method-name="onPostAdd"/>
+	</obj-entity>
+</data-map>


[cayenne] 03/04: Merge remote-tracking branch 'parent/pr/439' into asf-master

Posted by nt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit b25e5acc2926933c9d07b6ef8fcadbcb5f9d0b92
Merge: 9b465cc c84f394
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Thu Nov 19 16:06:19 2020 +0300

    Merge remote-tracking branch 'parent/pr/439' into asf-master

 .../org/apache/cayenne/map/EntityResolver.java     |  32 +++++-
 .../java/org/apache/cayenne/map/AnnotationIT.java  |  82 ++++++++++++++++
 .../testdo/annotation/ArtistAnnotation.java        |  70 +++++++++++++
 .../testdo/annotation/auto/_ArtistAnnotation.java  | 108 +++++++++++++++++++++
 .../cayenne/unit/di/server/CayenneProjects.java    |   1 +
 .../cayenne/unit/di/server/SchemaBuilder.java      |   3 +-
 .../test/resources/annotation/cayenne-project.xml  |   7 ++
 .../resources/annotation/datamapAnnotation.map.xml |  17 ++++
 8 files changed, 316 insertions(+), 4 deletions(-)