]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/accessor/Accessor.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / accessor / Accessor.java
1 /*******************************************************************************\r
2  *  Copyright (c) 2010 Association for Decentralized Information Management in\r
3  *  Industry THTH ry.\r
4  *  All rights reserved. This program and the accompanying materials\r
5  *  are made available under the terms of the Eclipse Public License v1.0\r
6  *  which accompanies this distribution, and is available at\r
7  *  http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  *  Contributors:\r
10  *      VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.databoard.accessor;\r
13 \r
14 import java.util.Collection;\r
15 import java.util.LinkedList;\r
16 import java.util.List;\r
17 import java.util.concurrent.Executor;\r
18 \r
19 import org.simantics.databoard.Accessors;\r
20 import org.simantics.databoard.accessor.binary.BinaryObject;\r
21 import org.simantics.databoard.accessor.error.AccessorConstructionException;\r
22 import org.simantics.databoard.accessor.error.AccessorException;\r
23 import org.simantics.databoard.accessor.event.Event;\r
24 import org.simantics.databoard.accessor.event.InvalidatedEvent;\r
25 import org.simantics.databoard.accessor.impl.ChangeSet;\r
26 import org.simantics.databoard.accessor.interestset.InterestSet;\r
27 import org.simantics.databoard.accessor.java.JavaObject;\r
28 import org.simantics.databoard.accessor.reference.ChildReference;\r
29 import org.simantics.databoard.binding.Binding;\r
30 import org.simantics.databoard.binding.error.BindingException;\r
31 import org.simantics.databoard.type.Datatype;\r
32 \r
33 /**\r
34  * Accessor is an interface to access, modify and monitor a data container.\r
35  * The actual storage format and location is implementation specific. \r
36  * For instance, container could be: a bunch of bytes, a Java object, a file, \r
37  * a folder with files, a network location, or direct memory of a simulation \r
38  * experiment. <p> \r
39  * \r
40  * The structure is presentable with Databoard type system. The type can be \r
41  * anything but a recursive structure.<p> \r
42  * \r
43  * The listening model allows placing of listener objects to accessors. \r
44  * Each listener is associated with a InterestSet. It describes a sub-tree of \r
45  * nodes to listen and aspects to monitor. Accessors emit Events on modifications  \r
46  * of structure and value. There is a reference in each event, and it is relative \r
47  * to the accessor where the listener was placed. For instance, a listener, that is \r
48  * interested in whole tree, is placed on a root accessor. A modification at a \r
49  * leaf-node spawns an event with a reference path from the root to the leaf. \r
50  * If the listener was placed directly on the leaf, there wouldn't be a path\r
51  * in the evenr object.<p> \r
52  * \r
53  * Multi-thread-usage is implementation dependent, read the documentation. <p>\r
54  * \r
55  * Construction and destruction model is also implementation dependent.\r
56  * A rule of thumb in life management of objects is that, the party that \r
57  * constructs an object must destroy it. Both construction and destruction of \r
58  * the container are also outside the scope of the Accessor interface. <p> \r
59  * \r
60  * However, as general implementation contract, the data container is disposed\r
61  * as whole, individual nodes are not. While the container is alive, individual \r
62  * nodes may be disposed using garbage collection mechanisms. Reference queue \r
63  * mechanism is one implementatio strategy. More common strategy is usage of \r
64  * weak references from parent to child. <p>\r
65  * \r
66  * @see Accessors \r
67  * @see JavaObject Accessor to Java Object container\r
68  * @see BinaryObject Accessor to a container in File or Memory  \r
69  * @see ArrayAccessor  \r
70  * @see BooleanAccessor \r
71  * @see ByteAccessor \r
72  * @see DoubleAccessor\r
73  * @see FloatAccessor\r
74  * @see IntegerAccessor\r
75  * @see LongAccessor\r
76  * @see MapAccessor\r
77  * @see OptionalAccessor\r
78  * @see RecordAccessor\r
79  * @see StringAccessor\r
80  * @see UnionAccessor\r
81  * @see VariantAccessor\r
82  * @author Toni Kalajainen (toni.kalajainen@iki.fi)\r
83  */\r
84 public interface Accessor {\r
85 \r
86         /**\r
87          * Get a snapshot of the object as a single data value. <p>\r
88          * Accessor makes type adaption to users binding if possible. <p>\r
89          * \r
90          * @param binding\r
91          * @return the value\r
92          * @throws AccessorException\r
93          */\r
94         Object getValue(Binding binding) throws AccessorException;\r
95 \r
96         /**\r
97          * Read a copy of the accessor's object into the <tt>obj</tt> instance. <p>\r
98          * Accessor makes type adaption to users binding if possible. <p>\r
99          * \r
100          * @param binding\r
101          * @param obj object to read the value to\r
102          * @throws AccessorException\r
103          */\r
104         void getValue(Binding binding, Object obj) throws AccessorException;\r
105         \r
106         /**\r
107          * Read value in <tt>path</tt> reference into an <tt>obj</tt> instance. <p>\r
108          * \r
109          * @param path component reference path or <code>null</code> to return _this_ \r
110          * @param binding\r
111          * @param obj\r
112          * @return true if value existed, false if not\r
113          * @throws AccessorException\r
114          */\r
115         boolean getValue(ChildReference path, Binding binding, Object obj) throws AccessorException;\r
116 \r
117         /**\r
118          * Read value in <tt>path</tt> reference into an <tt>obj</tt> instance. <p>\r
119          * \r
120          * @param path component reference path or <code>null</code> to return _this_ accessor\r
121          * @param binding\r
122          * @param obj\r
123          * @return the object or <tt>null</tt> if value doesn't exist\r
124          * @throws AccessorException\r
125          */\r
126         Object getValue(ChildReference path, Binding binding) throws AccessorException;\r
127         \r
128         /**\r
129          * Set a complete new value to the data container. \r
130          * Accessor makes type adaption to users binding if possible. <p>\r
131          *\r
132          * If the new value removes old map entries, array entries, optional value, or \r
133          * changes union or variant value type, it will disengage any existing \r
134          * sub-accessors and send {@link InvalidatedEvent}. <p>\r
135          * \r
136          * Writing the current value again may not emit an event. This is implementation\r
137          * specific. <p>\r
138          * \r
139          * Write is durable, once a the method returns successfully the value has been\r
140          * stored in the implmentation. <p>\r
141          * \r
142          * @param binding\r
143          * @param newValue\r
144          * @throws BindingException binding error\r
145          * @throws UnsupportedOperationException cannot set a new value\r
146          */\r
147         void setValue(Binding binding, Object newValue) throws AccessorException;\r
148 \r
149         /**\r
150          * Set value to <tt>path</tt> reference.\r
151          * \r
152          * @param path component reference path or <code>null</code> to return _this_ \r
153          * @param binding\r
154          * @param obj\r
155          * @return true if value existed in the accessor, false if not\r
156          * @throws AccessorException\r
157          */\r
158         boolean setValue(ChildReference path, Binding binding, Object obj) throws AccessorException;\r
159         \r
160         /**\r
161          * Open an accessor to a child. If one already exists, the existing is returned, \r
162          * otherwise a new is created. Child accessors are often remembered with \r
163          * weak reference.<p> \r
164          * \r
165          * InvalidatedEvent is thrown from the accessor if it is unlinked from the\r
166          * parent hierarchy. <p> \r
167          * \r
168          * @param path component reference path or <code>null</code> to return _this_ accessor\r
169          * @return accessor\r
170          * @throws AccessorConstructionException\r
171          */\r
172         <T extends Accessor> T getComponent(ChildReference path) throws AccessorConstructionException;\r
173         \r
174         /**\r
175          * Apply a change set in a single transaction operation.\r
176          * \r
177          * If rollback log is supplied, it is filled with reverse events. \r
178          *  \r
179          * If the operation fails, rollback log can be applied to cancel changes.\r
180          * \r
181          * @param changeSet\r
182          * @param rollback log to be filled with rollback events or <code>null</code>\r
183          * @throws AccessorException failed to apply change set\r
184          */\r
185         void apply(List<Event> changeSet, LinkedList<Event> rollback) throws AccessorException;\r
186         \r
187         /**\r
188          * Get structural represtentation of the accessor presented in databoard's\r
189          * type system. \r
190          * \r
191          * @return type description\r
192          */\r
193         Datatype type();\r
194         \r
195         /**\r
196          * Place a listener to an accessor node. The listener will be notified for changes\r
197          * in the node/node tree, depending on interest set.<p> \r
198          * \r
199          * When events are emited and in which thread processed is implementation\r
200          * specific. It is also implementation specific, whether the object can be mutated \r
201          * in the listener or whether it has to be done afterwards. <p> \r
202          * \r
203          * In many implementations there is a pluggable event handling strategy \r
204          * EventEmitter. The default behaviour is to emit events as they are\r
205          * spawned in the current thread.<p>\r
206          * \r
207          * There is a reference in each event instance that describes the path from\r
208          * the accessor where listener was placed to the node to which the event \r
209          * applies to. <p>\r
210          * \r
211          * Listener is attached to the object that holds the value at the time at \r
212          * the of the adding. \r
213          * For example, If a listener is attached to an array of element at index 3, \r
214          * and a new value is inserted at position 2, the listener still monitors the same\r
215          * container, which is now at index 4. The references of incoming the events \r
216          * are modified to have the new index.<p>\r
217          * \r
218          * Also, if a new value is assigned to the parent of an object that is listened,\r
219          * the listener keeps on monitoring the new value at the same reference.\r
220          * This doesn't apply when a new value is set to a union of different tag,\r
221          * to a variant with a new type, or value is removed from Optional type. \r
222          * In these two cases the listener is invalidated.<p>   \r
223          * \r
224          * See {@link ChangeSet} is an implementation that collects events.\r
225          * \r
226          * Executor argument determines the thread where the onEvents method is \r
227          * handled. <tt>null</tt> argument denotes current thread. \r
228          * \r
229          * @param listener\r
230          * @param interestSet\r
231          * @param pathPrefix path to the accessor or <code>null</code>. This is used in the events the accessor produces\r
232          * @param executor \r
233          * @see ChangeSet collects events \r
234          */\r
235         void addListener(Listener listener, InterestSet interestSet, ChildReference pathPrefix, Executor executor) throws AccessorException;\r
236         \r
237         /**\r
238          * Remove a listener. If the listener is added multiple times, the last \r
239          * one added is removed. \r
240          * \r
241          * @param listener\r
242          * @throws AccessorException\r
243          */\r
244         void removeListener(Listener listener) throws AccessorException;\r
245         \r
246         /**\r
247          * Accessor listener. \r
248          *\r
249          * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
250          */\r
251         public static interface Listener {\r
252 \r
253                 /**\r
254                  * Notify the listener on a new event \r
255                  * \r
256                  * @param events\r
257                  */\r
258                 void onEvents(Collection<Event> events);\r
259                 \r
260         }\r
261         \r
262 }\r
263 \r