4 package org.vamsas.client;
6 import java.lang.reflect.Field;
7 import java.lang.reflect.InvocationTargetException;
8 import java.lang.reflect.Method;
9 import java.util.Iterator;
11 import org.apache.commons.logging.Log;
12 import org.apache.commons.logging.LogFactory;
13 import org.exolab.castor.mapping.FieldDescriptor;
14 import org.exolab.castor.mapping.FieldHandler;
15 import org.exolab.castor.xml.util.XMLClassDescriptorImpl;
16 import org.vamsas.test.simpleclient.VamsasArchive;
19 * Base class for all Vamsas objects extracted from an IClientDocument. An
20 * object maybe registered or unregistered.
25 public abstract class object {
26 static Log log = LogFactory.getLog(object.class);
29 * unique id for all vamsas objects allows unambiguous referencing to any
30 * object in the vamsas document
32 protected boolean __stored_in_document = false;
34 protected long __last_hash = 0; // default is different so doHash always returns true initially.
36 protected boolean registerable = false;
38 protected VorbaId vorbaId = null;
40 protected IVorbaIdFactory __vorba = null;
47 testInstanceForIdField();
51 * set the isRegisterable flag based on the presence of a 'String id' field in
52 * the reflected class instance.
54 private void testInstanceForIdField() {
55 // look for the id field (should be an NCName string)
56 // TODO: decide if 'id' is an appropriate reserved attribute name for the VorbaId
58 java.lang.reflect.Field fd = this.getClass().getDeclaredField("_id");
59 if (String.class.isAssignableFrom(fd.getType())) {
60 this.setRegisterable(true);
62 } catch (SecurityException e) {
64 } catch (NoSuchFieldException e) {
65 this.setRegisterable(false);
70 * update the object instance's String id field, based on the contents of the
71 * VorbaId. Only call this if you mean to do it!
73 protected void setInstanceIdField() {
77 Method fd = this.getClass().getMethod("setId", new Class[] { String.class });
78 fd.invoke((Object) this, new Object[] {new String(this.getVorbaId().id)});
79 log.debug(this.getClass().getName()+" called setInstanceIdField!");
80 } catch (InvocationTargetException e) {
81 log.error("SourceGeneration of "
82 + this.getClass().toString()
83 + "\n has resulted in an inaccessible 'setId' method!\nCannot set ID from the vorbaId object.", e);
85 catch (IllegalAccessException e) {
86 log.error("SourceGeneration of "
87 + this.getClass().toString()
88 + "\n has resulted in an inaccessible 'setId' method!\nCannot set ID from the vorbaId object.", e);
89 } catch (SecurityException e) {
90 log.error("Security access violation for "+this.getClass().toString(),e);
91 } catch (NoSuchMethodException e) {
92 log.warn(this.getClass().toString()+" was erroneously marked as a Vorba object class (Implementation error?)");
93 this.setRegisterable(false);
96 System.err.println("Client error. Trying to setInstanceIdField on a "
97 + this.getClass().toString() + " (which cannot be given a vorbaId)");
102 * calculate a hash for the object with all housekeeping fields at standard
103 * values. (isRegisterable is an immutable attribute property)
104 * @return true if new hash different to last hash
106 synchronized protected boolean doHash() {
107 long __old_hash = __last_hash;
109 VorbaId thisid = vorbaId;
110 IVorbaIdFactory factory = __vorba;
111 boolean stored = __stored_in_document;
114 __last_hash = this.hashCode();
117 __stored_in_document = stored;
118 return (__old_hash==0) || (__old_hash == __last_hash);
122 * TODO: combine two versions of the same collection object to resolve
123 * asynchronous updates to the same vamsas object Merges two vamsas objects,
124 * one of which is a later version of the earlier (ie they have the same
125 * vorbaId but one is a later version recently read from the vamsasDocument
130 protected boolean merge(object laterCopy) {
131 log.warn(this.getClass().getName()+".merge() not implemented.");
137 * @return true if object is registered
139 public boolean isRegistered() {
140 return (registerable) ? (vorbaId != null) : false;
144 * Method to get fixed reference for the object in the vamsas document.
146 * @returns null if object is neither registered or not associated with a
147 * properly instantiated VorbaIdFactory.
149 public VorbaId getVorbaId() {
150 if (registerable && vorbaId == null) {
151 // Try to use the associated factory.
153 if ((vorbaId = __vorba.makeVorbaId()) == null)
154 return null; // Factory not valid.
156 this.setInstanceIdField();
164 * used by the IClient implementation to generate unique Id based on client
165 * applications current namespace.
167 protected void setVorbaId(VorbaId newid) {
172 * @return true if object is present in Vamsas Document.
174 public boolean is__stored_in_document() {
175 return __stored_in_document;
179 * for use by Vorba agent to reflect state of vamsas object to client
182 * @param __stored_in_document
183 * The __stored_in_document to set.
185 protected void set__stored_in_document(boolean __stored_in_document) {
186 this.__stored_in_document = __stored_in_document;
190 * __last_hash is the hash value computed when the object was last checked
191 * against a IClientDocument generated by the object's parent IClient
194 * @return Returns the __last_hash.
196 public long get__last_hash() {
201 * @return Returns the registerable.
203 public boolean isRegisterable() {
208 * Called during unmarshalling - if object has an id string, it is
211 * @param registerable
212 * The registerable to set.
214 protected void setRegisterable(boolean registerable) {
215 this.registerable = registerable;
218 * ensure's internal id field corresponds to vorbaId and
219 * cascade through all fields referring to an instance of object
220 * calling the same method on them.
221 * TODO: LATER: properly apply castors own field mechanisms to get at accessors
222 * TODO: FIX CYCLIC __ensure+instance_ids
224 protected void __ensure_instance_ids() {
226 throw new Error("Improperly intialised org.vamsas.client.object - no VorbaFactory given.");
227 log.debug("doing "+this.getClass()+".__ensure_instance_ids()");
228 if (!__stored_in_document && registerable)
229 setInstanceIdField();
231 return; // nothing has changed in this object - probably visited it before.
232 Class descriptor = null;
233 XMLClassDescriptorImpl descimpl = null;
235 // castor descriptor resolver magic
236 descriptor = this.getClass().getClassLoader().loadClass(this.getClass().getName()+"Descriptor");
237 descimpl = (XMLClassDescriptorImpl) descriptor.getConstructor(null).newInstance(null);
238 } catch (Exception e) {
239 log.fatal("Source Generation Error!: Couldn't resolve descriptor for "
240 +this.getClass().getName()
241 +" was 'generate descriptors' set for castorbuilder.properties?");
244 FieldDescriptor fields[] = descimpl.getFields();
245 for (int i=0,j=fields.length; i<j; i++) {
246 Class type= fields[i].getFieldType();
247 if (type.isArray()) {
248 if (object[].class.isAssignableFrom(type)) {
250 Object val = fields[i].getHandler().getValue(this);
252 object vals[] = (object[]) val;
253 for (int k=0, l=vals.length; k<l; k++) {
254 if (vals[k].__vorba==null)
255 vals[k].__vorba = __vorba; // propagate IVorbaIdFactory
256 vals[k].__ensure_instance_ids();
260 catch (Exception e) {
261 log.error("Client error - could not access array "+type.getName()+" in "+this.getClass().getName(), e);
265 if (object.class.isAssignableFrom(type)) {
267 FieldHandler fh = fields[i].getHandler();
270 Object fval = fh.getValue(this);
272 if (fval.getClass().isArray()) {
273 //if (object[].class.isAssignableFrom(type)) {
275 object vals[] = (object[]) fval;
276 for (int k=0, l=vals.length; k<l; k++) {
277 if (vals[k].__vorba==null)
278 vals[k].__vorba = __vorba; // propagate IVorbaIdFactory
279 vals[k].__ensure_instance_ids();
282 catch (Exception e) {
283 log.error("Client error - could not access (fhval)array "+type.getName()+" in "+this.getClass().getName(), e);
288 log.debug("Got value for "+fields[i].getFieldName());
292 // fuck around, fuck around, jump up jump up and get down! */
293 Object o = fields[i].getClassDescriptor();
295 // XMLClassDescriptorImpl fclasdes = (XMLClassDescriptorImpl) o;
296 String methname = "get"+fields[i].getFieldName();
297 Method fgetmeth = this.getClass().getMethod(methname,null);
298 if (fgetmeth!=null) {
299 Object fval = fgetmeth.invoke(this,null);
303 log.warn("Couldn't find "+this.getClass().getName()+"."+methname);
308 if (rf.__vorba==null)
309 rf.__vorba = __vorba; // propagate IVorbaIdFactory
310 rf.__ensure_instance_ids();
313 catch (Exception e) {
314 log.error("Client error - could not access "+type.getName()+" in "+this.getClass().getName(), e);