]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.common/src/org/simantics/db/common/changeset/GenericChangeListener.java
Use Logger in DependencyChanges & related mechanisms
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / changeset / GenericChangeListener.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.common.changeset;
13
14 import java.lang.reflect.Constructor;
15 import java.lang.reflect.InvocationTargetException;
16
17 import org.simantics.db.ChangeSet;
18 import org.simantics.db.MetadataI;
19 import org.simantics.db.ReadGraph;
20 import org.simantics.db.Session;
21 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
22 import org.simantics.db.event.ChangeEvent;
23 import org.simantics.db.event.ChangeListener;
24 import org.simantics.db.exception.DatabaseException;
25 import org.simantics.db.request.Read;
26 import org.simantics.utils.ReflectionUtils;
27 import org.slf4j.LoggerFactory;
28
29 /**
30  * A listener added to a Session for receiving notifications for completed
31  * write transactions.
32  * 
33  * @see GraphChangeEvent
34  * @see Session
35  */
36 abstract public class GenericChangeListener<Request, Result> implements ChangeListener {
37
38     private final Constructor<Read<Result>> constructor;
39
40     public GenericChangeListener() {
41
42         try {
43             Class<Read<Result>> clazz = ReflectionUtils.getSingleParameterTypeExtending(getClass());
44             this.constructor = clazz.getConstructor(ChangeSet.class);
45             return;
46         } catch (SecurityException | NoSuchMethodException e) {
47             LoggerFactory.getLogger(getClass()).error("Could not get constructor with param {}", ChangeSet.class.getSimpleName(), e);
48             throw new IllegalArgumentException(e);
49         }
50     }
51
52     public final void graphChanged(ChangeEvent e) throws DatabaseException {
53
54         try {
55             if (!preEventRequest())
56                 return;
57
58             Result event = e.getGraph().syncRequest(constructor.newInstance(e.getChanges()), TransientCacheListener.<Result>instance());
59             onEvent(e.getGraph(), e.getMetadataI(), event);
60         } catch (IllegalArgumentException | InstantiationException | IllegalAccessException | InvocationTargetException ex) {
61             LoggerFactory.getLogger(getClass()).error("Could not construct new instance with {}", e.getChanges(), ex);
62             throw new DatabaseException(ex);
63         }
64
65     }
66
67     /**
68      * Invoked before performing the event request with the received change
69      * event and sending the result to {@link #onEvent(ReadGraph, Object)}. Can
70      * be used to veto processing of an event.
71      *
72      * @return <code>true</code> if the event request shall be performed and the
73      *         result sent to {@link #onEvent(ReadGraph, Object)},
74      *         <code>false</code> to disable any further processing of the
75      *         received db {@link ChangeEvent}
76      * @since 1.8
77      */
78     public boolean preEventRequest() {
79         return true;
80     }
81
82     public abstract void onEvent(ReadGraph graph, MetadataI metadata, Result event) throws DatabaseException;
83
84 }