Skip to contentMethod: afterSetter(JoinPoint)
1: /**
2: * Copyright (C) 2020 Czech Technical University in Prague
3: *
4: * This program is free software: you can redistribute it and/or modify it under
5: * the terms of the GNU General Public License as published by the Free Software
6: * Foundation, either version 3 of the License, or (at your option) any
7: * later version.
8: *
9: * This program is distributed in the hope that it will be useful, but WITHOUT
10: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12: * details. You should have received a copy of the GNU General Public License
13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
14: */
15: package cz.cvut.kbss.jopa.model;
16:
17: import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
18: import cz.cvut.kbss.jopa.model.metamodel.EntityType;
19: import cz.cvut.kbss.jopa.model.metamodel.FieldSpecification;
20: import cz.cvut.kbss.jopa.sessions.UnitOfWorkImpl;
21: import cz.cvut.kbss.jopa.sessions.validator.AttributeModificationValidator;
22: import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
23: import org.aspectj.lang.JoinPoint;
24: import org.aspectj.lang.annotation.*;
25: import org.slf4j.Logger;
26: import org.slf4j.LoggerFactory;
27:
28: import java.lang.reflect.Field;
29:
30: @Aspect
31: public class BeanListenerAspect {
32:
33: private static final Logger LOG = LoggerFactory.getLogger(BeanListenerAspect.class);
34:
35: public interface Manageable {
36: void setPersistenceContext(UnitOfWorkImpl uow);
37:
38: UnitOfWorkImpl getPersistenceContext();
39: }
40:
41: public static class ManageableImpl implements Manageable {
42: private transient UnitOfWorkImpl persistenceContext;
43:
44: @Override
45: public void setPersistenceContext(UnitOfWorkImpl uow) {
46: this.persistenceContext = uow;
47: }
48:
49: @Override
50: public UnitOfWorkImpl getPersistenceContext() {
51: return persistenceContext;
52: }
53: }
54:
55: @DeclareMixin(value = "!is(InterfaceType) && (@cz.cvut.kbss.jopa.model.annotations.OWLClass *)")
56: public static Manageable createImpl() {
57: return new ManageableImpl();
58: }
59:
60: @Pointcut("get( @(cz.cvut.kbss.jopa.model.annotations.OWLObjectProperty " +
61: "|| cz.cvut.kbss.jopa.model.annotations.OWLDataProperty " +
62: "|| cz.cvut.kbss.jopa.model.annotations.OWLAnnotationProperty " +
63: "|| cz.cvut.kbss.jopa.model.annotations.Types " +
64: "|| cz.cvut.kbss.jopa.model.annotations.Properties ) * * ) " +
65: "&& (within(@cz.cvut.kbss.jopa.model.annotations.OWLClass *) || within(@cz.cvut.kbss.jopa.model.annotations.MappedSuperclass *))")
66: void getter() {
67: }
68:
69: @Pointcut("set( @(cz.cvut.kbss.jopa.model.annotations.OWLObjectProperty " +
70: "|| cz.cvut.kbss.jopa.model.annotations.OWLDataProperty " +
71: "|| cz.cvut.kbss.jopa.model.annotations.OWLAnnotationProperty " +
72: "|| cz.cvut.kbss.jopa.model.annotations.Types || cz.cvut.kbss.jopa.model.annotations.Properties ) * * ) " +
73: "&& (within(@cz.cvut.kbss.jopa.model.annotations.OWLClass *) || within(@cz.cvut.kbss.jopa.model.annotations.MappedSuperclass *))")
74: void setter() {
75: }
76:
77: /**
78: * Ties the specified instance to its persistence context, so that the advices can identify it easily.
79: *
80: * @param instance The managed instance
81: * @param persistenceContext Persistence context which is managing it
82: */
83: public void register(Object instance, UnitOfWorkImpl persistenceContext) {
84: ((Manageable) instance).setPersistenceContext(persistenceContext);
85: }
86:
87: /**
88: * Disconnects the specified instance from its persistence context.
89: *
90: * @param instance The instance to remove
91: * @see #register(Object, UnitOfWorkImpl)
92: */
93: public void deregister(Object instance) {
94: ((Manageable) instance).setPersistenceContext(null);
95: }
96:
97: @AfterReturning("setter()")
98: public void afterSetter(JoinPoint thisJoinPoint) {
99: // Persist changes done during transaction and check for inferred attribute modification
100: final Object entity = thisJoinPoint.getTarget();
101:• if (!(entity instanceof Manageable)) {
102: return;
103: }
104: final UnitOfWorkImpl persistenceContext = ((Manageable) entity).getPersistenceContext();
105:• if (persistenceContext == null || !persistenceContext.isInTransaction()) {
106: return;
107: }
108:
109: try {
110: final FieldSpecification<?, ?> fieldSpec = getFieldSpecification(entity,
111: thisJoinPoint.getSignature().getName(), persistenceContext);
112: AttributeModificationValidator.verifyCanModify(fieldSpec);
113: persistenceContext.attributeChanged(entity, fieldSpec.getJavaField());
114: } catch (SecurityException e) {
115: LOG.error(e.getMessage(), e);
116: throw new OWLPersistenceException(e.getMessage());
117: }
118: }
119:
120: private FieldSpecification<?, ?> getFieldSpecification(Object entity, String fieldName,
121: UnitOfWorkImpl persistenceContext) {
122: final EntityType<?> et = persistenceContext.getMetamodel().entity(entity.getClass());
123: assert et != null;
124: return et.getFieldSpecification(fieldName);
125: }
126:
127: @Before("getter()")
128: public void beforeGetter(JoinPoint thisJoinPoint) {
129: // Load lazy loaded entity field
130: final Object entity = thisJoinPoint.getTarget();
131: if (!(entity instanceof Manageable)) {
132: return;
133: }
134: final UnitOfWorkImpl persistenceContext = ((Manageable) entity).getPersistenceContext();
135: if (persistenceContext == null || !persistenceContext.contains(entity)) {
136: return;
137: }
138: final FieldSpecification<?, ?> fieldSpec = getFieldSpecification(entity, thisJoinPoint.getSignature().getName(),
139: persistenceContext);
140: final Field field = fieldSpec.getJavaField();
141: if (EntityPropertiesUtils.isFieldTransient(field)) {
142: return;
143: }
144: persistenceContext.loadEntityField(entity, field);
145: }
146: }