capture
[rrq/gorite.git] / com / intendico / data / Ref.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.Vector;
23 import java.util.Iterator;
24 import java.io.Serializable;
25
26 /**
27  * This class is a carrier of values. The Relation class knows of Ref
28  * objects, so as to allow passing of values between queries.
29  */
30 public class Ref/*<T>*/ implements Serializable {
31
32     /**
33      * Utility method to obtain an actual value of a possible Ref
34      * object.
35      */
36     public static Object deref(Object x) {
37         return x instanceof Ref? ((Ref) x).get() : x;
38     }
39
40     /**
41      * Utility method that creates an array of Object values from an
42      * array of Ref
43      */
44     public static Object [] getValues(Ref [] rs) {
45         Object [] v = new Object [ rs.length ];
46         for ( int i = 0; i < rs.length; i++ ) {
47             v[ i ] = rs[ i ].get();
48         }
49         return v;
50     }
51
52     /**
53      * Utility method to set an array of Ref from an array of Object
54      * values.
55      */
56     //@SuppressWarnings("unchecked")
57     public static void setValues(Ref [] rs,Object [] v) {
58         for ( int i = 0; i < rs.length; i++ ) {
59             rs[ i ].set( Ref.deref( v[ i ] ) );
60         }
61     }
62
63     /**
64      * Utility method that collects the bindings of given {@link Ref}
65      * objects into a {@link java.util.Vector}.
66      */
67     public static Vector getBinding(Vector/*<Ref>*/ refs) {
68         Vector/*<Object>*/ v = new Vector/*<Object>*/();
69         for ( Iterator/*<Ref>*/ i = refs.iterator(); i.hasNext(); )
70             v.add( ((Ref) i.next()).get() );
71         return v;
72     }
73
74     /**
75      * Utility method that binds the given {@link Ref} objects with
76      * corresponding values from a {@link java.util.Vector}.
77      */
78     //@SuppressWarnings("unchecked")
79     public static void bind(Vector/*<Ref>*/ refs,Vector v) {
80         int c = 0;
81         for ( Iterator/*<Ref>*/ i = refs.iterator(); i.hasNext(); )
82             ((Ref) i.next()).set( deref( v.get( c++ ) ) );
83     }
84
85     /**
86      * Utility method to create a vector of ref objects from a string
87      * array of names.
88      */
89     public static Vector/*<Ref>*/ create(String [] names) {
90         Vector/*<Ref>*/ v = new Vector/*<Ref>*/();
91         if ( names == null )
92             return v;
93         for ( int i = 0; i < names.length; i++ ) {
94             v.add( new Ref( names[i] ) );
95         }
96         return v;
97     }
98
99     /**
100      * Utility method that invokes {@link #clear} for the given {@link
101      * Ref} objects with.
102      */
103     public static void clear(Vector/*<Ref>*/ refs) {
104         for ( Iterator/*<Ref>*/ i = refs.iterator(); i.hasNext(); )
105             ((Ref) i.next()).clear();
106     }
107
108     /**
109      * Creates copies of Ref objects.
110      */
111     //@SuppressWarnings("unchecked")
112     public static Vector/*<Ref>*/ copy(Vector/*<Ref>*/ src) {
113         Vector/*<Ref>*/ refs = new Vector/*<Ref>*/();
114         for ( Iterator/*<Ref>*/ i = src.iterator(); i.hasNext(); )
115             refs.add( new Ref( (Ref) i.next() ) );
116         return refs;
117     }
118
119     /**
120      * Returns a textual representation of a vector of {@link Ref}
121      * objects.
122      */
123     public static String toString(Vector/*<Ref>*/ refs) {
124         return toString( (Ref[]) refs.toArray( new Ref [ refs.size() ] ) );
125     }
126
127     /**
128      * Returns a textual representation of an expected array of Ref
129      * objects. Each Ref object is presented by name and value, using
130      * {@link #toString()}, but the value is clipped to at most 40
131      * characters. The whole things is put within a matching pair of
132      * curly braces.
133      */
134     public static String toString(Object [] refs) {
135         StringBuffer s = new StringBuffer();
136         s.append( "{" );
137         for ( int i = 0; i < refs.length; i++ ) {
138             if ( i > 0 )
139                 s.append( "," );
140             if ( refs[ i ] instanceof Ref ) {
141                 Ref r = (Ref) refs[ i ];
142                 s.append( r.getName() );
143                 s.append( "=" );
144                 String v = r.toString();
145                 if ( v.length() > 40 )
146                     v = v.substring( 0, 37 ) + "...";
147                 s.append( v );
148             } else {
149                 s.append( refs[ i ] );
150             }
151         }
152         s.append( "}" );
153         return s.toString();
154     }
155
156     /**
157      * Two Ref vectors are equals if they are of same size, and
158      * dereference to the same values in the same order.
159      */
160     public static boolean equals(Vector/*<Ref>*/ a,Vector/*<Ref>*/ b) {
161         if ( a.size() != b.size() )
162             return false;
163         for ( int i = 0; i < a.size(); i++ ) {
164             Object ra = deref( a.get( i ) );
165             Object rb = deref( b.get( i ) );
166             if ( ra == null || rb == null )
167                 if ( ra != rb )
168                     return false;
169             if ( ! ra.equals( rb ) )
170                 return false;
171         }
172         return true;
173     }
174
175     /**
176      * The name given to the {@link Ref} object at construction.
177      */
178     public String name;
179
180     /**
181      * The value of the {@link Ref} object, or <em>null</em> if not
182      * bound.
183      */
184     private /*T*/ Object value;
185
186     /**
187      * Constructor. Each Ref object is named.
188      */
189     public Ref(String n) {
190         name = n;
191     }
192
193     /**
194      * Constructor with both name and value.
195      */
196     public Ref(String n,/*T*/ Object v) {
197         name = n;
198         value = v;
199     }
200
201     /**
202      * Constructor that copies another Ref object.
203      */
204     public Ref(Ref/*<T>*/ src) {
205         name = src.getName();
206         value = src.get();
207     }
208
209     /**
210      * Finds a same named Ref object in a {@link Vector}.
211      */
212     public Ref find(Vector/*<Ref>*/ refs) {
213         for ( Iterator/*<Ref>*/ i = refs.iterator(); i.hasNext(); ) {
214             Ref ref = (Ref) i.next();
215             if ( name.equals( ref.name ) )
216                 return ref;
217         }
218         return null;
219     }
220
221     /**
222      * Returns the value. This is <em>null</em> unless bound to
223      * something.
224      */
225     public /*T*/ Object get() {
226         return value;
227     }
228
229     /**
230      * Accessor method for the name.
231      */
232     public String getName() {
233         return name == null? "Ref#" + System.identityHashCode( this ) : name;
234     }
235
236     /**
237      * Assigns the value.
238      */
239     public void set(/*T*/ Object v) {
240         value = v;
241     }
242
243     /**
244      * Resets its value to null.
245      */
246     public void clear() {
247         value = null;
248     }
249
250     /**
251      * Returns a String representation of this {@link Ref} object. The
252      * object is transparent, and it presents itself only via its
253      * value. Use {@link #getName} to present the {@link Ref} object.
254      */
255     public String toString() {
256         return "" + value;
257     }
258
259 }