1 /*******************************************************************************
2 * Copyright (c) 2010 Association for Decentralized Information Management in
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.databoard.accessor;
14 import java.util.Collection;
15 import java.util.LinkedList;
16 import java.util.List;
17 import java.util.concurrent.Executor;
19 import org.simantics.databoard.Accessors;
20 import org.simantics.databoard.accessor.binary.BinaryObject;
21 import org.simantics.databoard.accessor.error.AccessorConstructionException;
22 import org.simantics.databoard.accessor.error.AccessorException;
23 import org.simantics.databoard.accessor.event.Event;
24 import org.simantics.databoard.accessor.event.InvalidatedEvent;
25 import org.simantics.databoard.accessor.impl.ChangeSet;
26 import org.simantics.databoard.accessor.interestset.InterestSet;
27 import org.simantics.databoard.accessor.java.JavaObject;
28 import org.simantics.databoard.accessor.reference.ChildReference;
29 import org.simantics.databoard.binding.Binding;
30 import org.simantics.databoard.binding.error.BindingException;
31 import org.simantics.databoard.type.Datatype;
34 * Accessor is an interface to access, modify and monitor a data container.
35 * The actual storage format and location is implementation specific.
36 * For instance, container could be: a bunch of bytes, a Java object, a file,
37 * a folder with files, a network location, or direct memory of a simulation
40 * The structure is presentable with Databoard type system. The type can be
41 * anything but a recursive structure.<p>
43 * The listening model allows placing of listener objects to accessors.
44 * Each listener is associated with a InterestSet. It describes a sub-tree of
45 * nodes to listen and aspects to monitor. Accessors emit Events on modifications
46 * of structure and value. There is a reference in each event, and it is relative
47 * to the accessor where the listener was placed. For instance, a listener, that is
48 * interested in whole tree, is placed on a root accessor. A modification at a
49 * leaf-node spawns an event with a reference path from the root to the leaf.
50 * If the listener was placed directly on the leaf, there wouldn't be a path
51 * in the evenr object.<p>
53 * Multi-thread-usage is implementation dependent, read the documentation. <p>
55 * Construction and destruction model is also implementation dependent.
56 * A rule of thumb in life management of objects is that, the party that
57 * constructs an object must destroy it. Both construction and destruction of
58 * the container are also outside the scope of the Accessor interface. <p>
60 * However, as general implementation contract, the data container is disposed
61 * as whole, individual nodes are not. While the container is alive, individual
62 * nodes may be disposed using garbage collection mechanisms. Reference queue
63 * mechanism is one implementatio strategy. More common strategy is usage of
64 * weak references from parent to child. <p>
67 * @see JavaObject Accessor to Java Object container
68 * @see BinaryObject Accessor to a container in File or Memory
70 * @see BooleanAccessor
74 * @see IntegerAccessor
77 * @see OptionalAccessor
81 * @see VariantAccessor
82 * @author Toni Kalajainen (toni.kalajainen@iki.fi)
84 public interface Accessor {
87 * Get a snapshot of the object as a single data value. <p>
88 * Accessor makes type adaption to users binding if possible. <p>
92 * @throws AccessorException
94 Object getValue(Binding binding) throws AccessorException;
97 * Read a copy of the accessor's object into the <tt>obj</tt> instance. <p>
98 * Accessor makes type adaption to users binding if possible. <p>
101 * @param obj object to read the value to
102 * @throws AccessorException
104 void getValue(Binding binding, Object obj) throws AccessorException;
107 * Read value in <tt>path</tt> reference into an <tt>obj</tt> instance. <p>
109 * @param path component reference path or <code>null</code> to return _this_
112 * @return true if value existed, false if not
113 * @throws AccessorException
115 boolean getValue(ChildReference path, Binding binding, Object obj) throws AccessorException;
118 * Read value in <tt>path</tt> reference into an <tt>obj</tt> instance. <p>
120 * @param path component reference path or <code>null</code> to return _this_ accessor
123 * @return the object or <tt>null</tt> if value doesn't exist
124 * @throws AccessorException
126 Object getValue(ChildReference path, Binding binding) throws AccessorException;
129 * Set a complete new value to the data container.
130 * Accessor makes type adaption to users binding if possible. <p>
132 * If the new value removes old map entries, array entries, optional value, or
133 * changes union or variant value type, it will disengage any existing
134 * sub-accessors and send {@link InvalidatedEvent}. <p>
136 * Writing the current value again may not emit an event. This is implementation
139 * Write is durable, once a the method returns successfully the value has been
140 * stored in the implmentation. <p>
144 * @throws BindingException binding error
145 * @throws UnsupportedOperationException cannot set a new value
147 void setValue(Binding binding, Object newValue) throws AccessorException;
150 * Set value to <tt>path</tt> reference.
152 * @param path component reference path or <code>null</code> to return _this_
155 * @return true if value existed in the accessor, false if not
156 * @throws AccessorException
158 boolean setValue(ChildReference path, Binding binding, Object obj) throws AccessorException;
161 * Open an accessor to a child. If one already exists, the existing is returned,
162 * otherwise a new is created. Child accessors are often remembered with
165 * InvalidatedEvent is thrown from the accessor if it is unlinked from the
166 * parent hierarchy. <p>
168 * @param path component reference path or <code>null</code> to return _this_ accessor
170 * @throws AccessorConstructionException
172 <T extends Accessor> T getComponent(ChildReference path) throws AccessorConstructionException;
175 * Apply a change set in a single transaction operation.
177 * If rollback log is supplied, it is filled with reverse events.
179 * If the operation fails, rollback log can be applied to cancel changes.
182 * @param rollback log to be filled with rollback events or <code>null</code>
183 * @throws AccessorException failed to apply change set
185 void apply(List<Event> changeSet, LinkedList<Event> rollback) throws AccessorException;
188 * Get structural represtentation of the accessor presented in databoard's
191 * @return type description
196 * Place a listener to an accessor node. The listener will be notified for changes
197 * in the node/node tree, depending on interest set.<p>
199 * When events are emited and in which thread processed is implementation
200 * specific. It is also implementation specific, whether the object can be mutated
201 * in the listener or whether it has to be done afterwards. <p>
203 * In many implementations there is a pluggable event handling strategy
204 * EventEmitter. The default behaviour is to emit events as they are
205 * spawned in the current thread.<p>
207 * There is a reference in each event instance that describes the path from
208 * the accessor where listener was placed to the node to which the event
211 * Listener is attached to the object that holds the value at the time at
213 * For example, If a listener is attached to an array of element at index 3,
214 * and a new value is inserted at position 2, the listener still monitors the same
215 * container, which is now at index 4. The references of incoming the events
216 * are modified to have the new index.<p>
218 * Also, if a new value is assigned to the parent of an object that is listened,
219 * the listener keeps on monitoring the new value at the same reference.
220 * This doesn't apply when a new value is set to a union of different tag,
221 * to a variant with a new type, or value is removed from Optional type.
222 * In these two cases the listener is invalidated.<p>
224 * See {@link ChangeSet} is an implementation that collects events.
226 * Executor argument determines the thread where the onEvents method is
227 * handled. <tt>null</tt> argument denotes current thread.
231 * @param pathPrefix path to the accessor or <code>null</code>. This is used in the events the accessor produces
233 * @see ChangeSet collects events
235 void addListener(Listener listener, InterestSet interestSet, ChildReference pathPrefix, Executor executor) throws AccessorException;
238 * Remove a listener. If the listener is added multiple times, the last
239 * one added is removed.
242 * @throws AccessorException
244 void removeListener(Listener listener) throws AccessorException;
249 * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
251 public static interface Listener {
254 * Notify the listener on a new event
258 void onEvents(Collection<Event> events);