--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.db.common.changeset;\r
+\r
+import java.lang.reflect.Constructor;\r
+import java.lang.reflect.InvocationTargetException;\r
+\r
+import org.simantics.db.ChangeSet;\r
+import org.simantics.db.MetadataI;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
+import org.simantics.db.common.utils.Logger;\r
+import org.simantics.db.event.ChangeEvent;\r
+import org.simantics.db.event.ChangeListener;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.utils.ReflectionUtils;\r
+\r
+/**\r
+ * A listener added to a Session for receiving notifications for completed\r
+ * write transactions.\r
+ * \r
+ * @see GraphChangeEvent\r
+ * @see Session\r
+ */\r
+abstract public class GenericChangeListener<Request, Result> implements ChangeListener {\r
+\r
+ private final Constructor<Read<Result>> constructor;\r
+\r
+ public GenericChangeListener() {\r
+\r
+ try {\r
+ Class<Read<Result>> clazz = ReflectionUtils.getSingleParameterTypeExtending(getClass());\r
+ this.constructor = clazz.getConstructor(ChangeSet.class);\r
+ return;\r
+ } catch (SecurityException e) {\r
+ Logger.defaultLogError(e);\r
+ } catch (NoSuchMethodException e) {\r
+ Logger.defaultLogError(e);\r
+ }\r
+ throw new IllegalArgumentException();\r
+\r
+ }\r
+\r
+ final public void graphChanged(ChangeEvent e) throws DatabaseException {\r
+\r
+ try {\r
+ if (!preEventRequest())\r
+ return;\r
+\r
+ Result event = e.getGraph().syncRequest(constructor.newInstance(e.getChanges()), TransientCacheListener.<Result>instance());\r
+ onEvent(e.getGraph(), e.getMetadataI(), event);\r
+ } catch (IllegalArgumentException e1) {\r
+ Logger.defaultLogError(e1);\r
+ } catch (InstantiationException e1) {\r
+ Logger.defaultLogError(e1);\r
+ } catch (IllegalAccessException e1) {\r
+ Logger.defaultLogError(e1);\r
+ } catch (InvocationTargetException e1) {\r
+ Logger.defaultLogError(e1);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Invoked before performing the event request with the received change\r
+ * event and sending the result to {@link #onEvent(ReadGraph, Object)}. Can\r
+ * be used to veto processing of an event.\r
+ * \r
+ * @return <code>true</code> if the event request shall be performed and the\r
+ * result sent to {@link #onEvent(ReadGraph, Object)},\r
+ * <code>false</code> to disable any further processing of the\r
+ * received db {@link ChangeEvent}\r
+ * @since 1.8\r
+ */\r
+ public boolean preEventRequest() {\r
+ return true;\r
+ }\r
+\r
+ public abstract void onEvent(ReadGraph graph, MetadataI metadata, Result event) throws DatabaseException;\r
+\r
+}\r