1 /*********************************************************************
2 Copyright 2012, Ralph Ronnquist.
4 This file is part of GORITE.
6 GORITE is free software: you can redistribute it and/or modify it
7 under the terms of the Lesser GNU General Public License as published
8 by the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GORITE is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the Lesser GNU General Public
17 License along with GORITE. If not, see <http://www.gnu.org/licenses/>.
18 **********************************************************************/
20 package com.intendico.data;
22 import java.util.Vector;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.Observer;
28 * The Snapshot class implements a query overlay for capturing changes
29 * to a source {@link Query} in respect of the added and lost valid
30 * binding combinations for the {@link Ref} objects
31 * involved. Temporally a snapshot is taken by the {@link #reset}
32 * method, as well as at construction. Thereafter successive {@link
33 * #next} invocations provide the added valid binding combinations
34 * since the prior snapshot.
36 * <p> Following a reset, the Snapshot also holds the lost bindings,
37 * which can be inspected separately.
39 * <p> A Snapshot may hold a non-null {@link #sync} object, which is
40 * used for synchronizing on during {@link #reset}. Any concurrent
41 * thread that updates queried components should synchronize on the
42 * same object, and in that way avoid multi-threading conflict.
44 public class Snapshot implements Query {
47 * Holds all the bindings found at the most recent snapshot.
49 public HashSet/*<Vector>*/ snapshot;
52 * Holds the bindings that were valid before the most recent
53 * snapshot, but were no longer valid at that snapshot.
55 public HashSet/*<Vector>*/ lost = new HashSet/*<Vector>*/();
58 * Holds the Ref objects in a Vector.
60 public Vector/*<Ref>*/ refs;
63 * The iterator for recalling successive new bindings by the
64 * {@link #next} method.
66 public Iterator/*<Vector>*/ bindings;
69 * The query being monitored.
74 * The object, if any, to synchronize on during {@link
75 * #reset}. This is to support multi-thread access to queried
76 * components; any concurrent thread needs to synchronize on the
79 public Object sync = null;
84 public Snapshot(Query q) {
86 refs = query.getRefs( new Vector/*<Ref>*/() );
89 } catch (Exception e) {
95 * Alternative constructor with a synchronization object.
97 public Snapshot(Object lock,Query q) {
103 * The {@link Query#copy} method implemented by creating a new
104 * Snapshot with a copy of the monitored {@link #query}, and
105 * sharing any {@link #sync} object.
107 public Query copy(Vector/*<Ref>*/ newrefs) throws Exception {
108 return new Snapshot( sync, query.copy( newrefs ) );
112 * The {@link Query#reset} method implemented by capturing a new
113 * snapshot of the given query, and initialising the Iterator for
114 * the collection of bindings that are new since the last
117 * <p> This method updates {@link #snapshot}, {@link #lost} and
120 public void reset() throws Exception {
121 if ( sync == null ) {
124 synchronized( sync ) {
131 * Actual reset method, which may and might not be synchronized.
133 private void doReset() throws Exception {
134 lost = snapshot != null? snapshot : new HashSet/*<Vector>*/();
135 HashSet/*<Vector>*/ is = new HashSet/*<Vector>*/();
136 snapshot = new HashSet/*<Vector>*/();
140 while ( query.next() ) {
142 Vector v = Ref.getBinding( refs );
143 if ( snapshot.contains( v ) )
146 if ( lost != null && lost.contains( v ) ) {
152 bindings = none? null : is.iterator();
156 * Produces the succession of bindings that the qurey was valid
157 * for at the last snapshot, but not at the one prior.
159 * <p> This method uses {@link #bindings}.
161 public boolean next() {
162 if ( bindings == null )
164 if ( bindings.hasNext() ) {
165 Ref.bind( refs, (Vector) bindings.next() );
170 if ( ! bindings.hasNext() )
176 * The {@link Query#getRefs} method implemented by returning the
177 * query's Ref object.
179 public Vector/*<Ref>*/ getRefs(Vector/*<Ref>*/ v) {
180 return query.getRefs( v );
184 * The {@link Query#addObserver} method implemented by adding
185 * the observer to the query.
187 public void addObserver(Observer x) {
188 query.addObserver( x );
192 * The {@link Query#deleteObserver} method implemented by
193 * removing the observer from the query.
195 public void deleteObserver(Observer x) {
196 query.deleteObserver( x );
200 * The {@link Query#addable} method implemented by forwarding to
201 * the contained query.
203 public boolean addable() {
204 return query.addable();
208 * The {@link Query#add} method implemented by forwarding to the
211 public boolean add() {
216 * The {@link Query#removable} method implemented by forwarding to
219 public boolean removable() {
220 return query.removable();
224 * The {@link Query#remove} method implemented by forwarding to
227 public boolean remove() {
228 return query.remove();
232 * Utility method to remove all remaining bindings for the
233 * query. This method applies to the current snapshot, and might
234 * make most sense for a newly created Snapshot object, where it
235 * will remove all matching bindings.
237 public void removeAll() {
244 * Returns a String representation of the Snapshot object.
246 public String toString() {
247 return "Snapshot( " + query.toString() + " )";