capture
[rrq/gorite.git] / com / intendico / data / Condition.java
1 /*********************************************************************
2 Copyright 2012, Ralph Ronnquist.
3
4 This file is part of GORITE.
5
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.
10
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.
15
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 **********************************************************************/
19
20 package com.intendico.data;
21
22 import java.util.Observer;
23 import java.util.Vector;
24 import java.util.Iterator;
25
26 /**
27  * A utility class for including a boolean method in query
28  * processing. The typical use is as an inline extension that
29  * implements the {@link #condition} method.
30  */
31 abstract public class Condition implements Query {
32
33     /**
34      * An always true Condition query.
35      */
36     public static Condition TRUE = new Condition() {
37             public boolean condition() {
38                 return true;
39             }
40         };
41
42     /**
43      * Control flag to mark whether the condition has been tested or
44      * not.
45      */
46     public boolean tested = false;
47
48     /**
49      * Cache of initially unbound variables. These are captured on
50      * construction, just in case there is an extension that takes
51      * variables. In that case, the next() method on failing must
52      * restore the incoming unbound variables to be unbound.
53      */
54     public Vector variables;
55
56     /**
57      * The {@link Query#reset} method implemented by noting the
58      * condition as not tested.
59      */
60     public void reset() throws Exception {
61         tested = false;
62     }
63
64     /**
65      * The {@link Query#copy} method implemented by using this same
66      * object.
67      */
68     public Query copy(Vector/*<Ref>*/ newrefs) throws Exception {
69         return this;
70     }
71
72     /**
73      * The {@link Query#next} method implemented by returning as per
74      * the {@link #condition} method on its first invocation, then
75      * returning false without invoking the {@link #condition} method,
76      * until {@link #reset()}. This method also captures any unbound
77      * variables (an extension class may have variables), and clears
78      * these before returning false.
79      */
80     public boolean next() throws Exception {
81         if ( ! tested ) {
82             variables = getRefs( new Vector() );
83             if ( variables.size() > 0 ) {
84                 for ( Iterator i = variables.iterator(); i.hasNext(); ) {
85                     if ( ((Ref) i.next()).get() != null ) {
86                         i.remove();
87                     }
88                 }
89                 if ( variables.size() == 0 )
90                     variables = null;
91             } else {
92                 variables = null;
93             }
94             tested = true;
95             if ( condition() )
96                 return true;
97         }
98         if ( variables != null ) {
99             for ( Iterator i = variables.iterator(); i.hasNext(); ) {
100                 ((Ref) i.next()).clear();
101             }
102         }
103         return false;
104     }
105
106     /**
107      * The {@link Query#getRefs} method implemented by adding
108      * nothing. An actual condition that uses {@link Ref} objects
109      * should override this method.
110      */
111     public Vector/*<Ref>*/ getRefs(Vector/*<Ref>*/ v) {
112         return v;
113     }
114
115     /**
116      * The {@link Query#addObserver} method implemented by doing
117      * nothing. An actual condition that is triggering should override
118      * this method as well as {@link #deleteObserver}.
119      */
120     public void addObserver(Observer x) {
121     }
122
123     /**
124      * The {@link Query#deleteObserver} method implemented by doing
125      * nothing. An actual condition that is triggering should override
126      * this method as well as {@link #addObserver}.
127      */
128     public void deleteObserver(Observer x) {
129     }
130
131     /**
132      * The {@link Query#addable} method is implemented by a reset
133      * followed by next.
134      */
135     public boolean addable() {
136         try {
137             reset();
138             return next();
139         } catch (Exception e) {
140             e.printStackTrace();
141             return false;
142         }
143     }
144
145     /**
146      * The {@link Query#add} method implemented by returning false. An
147      * actual condition that gets updated should override this method.
148      */
149     public boolean add() {
150         return false;
151     }
152
153     /**
154      * Implements {@link Query#removable} by calling {@link #addable}
155      */
156     public boolean removable()
157     {
158         return addable();
159     }
160
161     /**
162      * Implements {@link Query#remove} by returning false;
163      */
164     public boolean remove() {
165         return false;
166     }
167
168     /**
169      * The actual condition returning <em>true</em> or
170      * <em>false</em>. If it is appropriate to re-test the condition
171      * several times before resetting, the actual condition may also
172      * set the {@link #tested} flag.
173      */
174     abstract public boolean condition() throws Exception;
175
176     /**
177      * Returns a {@link java.lang.String} representation of the
178      * condition object.
179      */
180     public String toString() {
181         return "Condition#" + System.identityHashCode( this );
182     }
183 }