Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/metaobjects/property/remoteproperty.cc

Go to the documentation of this file.
00001 /*
00002     This file is part of the Virtual Object System of
00003     the Interreality project (http://interreality.org).
00004 
00005     Copyright (C) 2001, 2002 Peter Amstutz
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00020 
00021     Peter Amstutz <tetron@interreality.org>
00022 */
00023 #include <stdio.h>
00024 #include <iostream>
00025 #include <fstream>
00026 
00027 #include <vos/corelibs/vos/vos.hh>
00028 #include "property.hh"
00029 #include <typechain/typechain.hh>
00030 
00031 #include <assert.h>
00032 
00033 RemoteProperty::RemoteProperty(MetaObject* superobject)
00034     : MetaObject(superobject), Property(superobject), offset(-1), first_read(true)
00035 {
00036     addUpdateHandler<RemoteProperty>("property:length-update", this, &RemoteProperty::lengthUpdateHandler);
00037     addUpdateHandler<RemoteProperty>("property:update", this, &RemoteProperty::writeUpdateHandler);
00038     addUpdateHandler<RemoteProperty>("property:replace-update", this, &RemoteProperty::replaceUpdateHandler);
00039     addUpdateHandler<RemoteProperty>("property:start-listening-reply", this, &RemoteProperty::startListeningReplyHandler);
00040 }
00041 
00042 
00043 /* Remote Property */
00044 
00045 
00046 void RemoteProperty::checkDecoded() {
00047     if(first_read) {
00048         string foo;
00049         readRaw(foo, 0, -1);
00050         first_read = false;
00051     }
00052     Property::checkDecoded();
00053 }
00054 
00055 int RemoteProperty::getRawLength()
00056 {
00057     if(propertyListeners.empty()) {
00058         pREF(Message*, m, new Message(),
00059              rREF(LocalSite&, ls, RemoteVobject::initFields(this, m, "property:get-length", true),
00060                   sendMessage(m);
00061                   rREF(RemoteSite&, site, dynamic_cast<RemoteSite&>(getSite()),
00062                        pREF(Message*, n, ls.waitFor(m->getNonce(), &site), );
00063                       );
00064                  );
00065             );
00066     }
00067 
00068     return Property::getRawLength();
00069 }
00070 
00071 int RemoteProperty::getLength()
00072 {
00073     string foo;
00074     readRaw(foo, 0, -1);
00075     return Property::getLength();
00076 }
00077 
00078 const string RemoteProperty::getRawDataType() {
00079     if(raw_datatype == "?") { // probably have not sent a read message yet. XXX but this could be done better
00080         string foo;
00081         readRaw(foo, 0, -1);
00082     }
00083     return Property::getRawDataType();
00084 }
00085 
00086 
00087 /* this is the primary read() method */
00088 void RemoteProperty::read(string& target, int start, int length)
00089 {
00090     string foo;
00091     readRaw(foo, start, length);    // send property:read message if necesary? XXX duplicate reads ??
00092     Property::read(target, start, length);
00093 }
00094 
00095 void RemoteProperty::readRaw(string& target, int start, int length)
00096 {
00097     if(propertyListeners.empty()) {
00098         LOG("RemoteProperty", 5, "readRaw: sending read message (no listeners).");
00099         pREF(Message*, m, new Message(),
00100              rREF(LocalSite&, ls, RemoteVobject::initFields(this, m, "property:read", true),
00101                   char x[16];
00102                   sprintf(x, "%i", start);
00103                   m->insertField(-1, "start", x);
00104                   sprintf(x, "%i", length);
00105                   m->insertField(-1, "length", x);
00106 
00107                   sendMessage(m);
00108                   rREF(RemoteSite&, site, dynamic_cast<RemoteSite&>(getSite()),
00109                        pREF(Message*, n, ls.waitFor(m->getNonce(), &site), );
00110                       );
00111                  );
00112             );
00113     }
00114 
00115     Property::readRaw(target, start, length);
00116 }
00117 
00118 void RemoteProperty::asyncRead()
00119 {
00120     if(propertyListeners.empty()) {
00121         LOG("RemoteProperty", 5, "readRaw: sending read message (no listeners).");
00122         pREF(Message*, m, new Message(),
00123              rREF(LocalSite&, ls, RemoteVobject::initFields(this, m, "property:read", true),
00124                   m->insertField(-1, "start", "0");
00125                   m->insertField(-1, "length", "-1");
00126 
00127                   sendMessage(m);
00128                  );
00129             );
00130     } else {
00131         vRef<PropertyEvent> event = new PropertyEvent(
00132             PropertyEvent::PropertyReplace,
00133             *this, *this,
00134             data,
00135             getRawDataType(),
00136             false);
00137                                                       
00138         for(PropertyListenerMap::iterator i = propertyListeners.begin(); i != propertyListeners.end(); i++) {
00139             (*i).second->notifyPropertyChange(*event);
00140         }
00141     }
00142 }
00143 
00144 void RemoteProperty::asyncRead(int start, int length)
00145 {
00146     if(propertyListeners.empty()) {
00147         LOG("RemoteProperty", 5, "readRaw: sending read message (no listeners).");
00148         pREF(Message*, m, new Message(),
00149              rREF(LocalSite&, ls, RemoteVobject::initFields(this, m, "property:read", true),
00150                   char x[16];
00151                   snprintf(x, sizeof(x), "%i", start);
00152                   m->insertField(-1, "start", x);
00153                   snprintf(x, sizeof(x), "%i", length);
00154                   m->insertField(-1, "length", x);
00155 
00156                   sendMessage(m);
00157                  );
00158             );
00159     } else {
00160         vRef<PropertyEvent> event = new PropertyEvent(
00161             PropertyEvent::PropertyWrite,
00162             *this, *this,
00163             start, data.size(),
00164             data,
00165             getRawDataType(),
00166             false);                                                   
00167 
00168         for(PropertyListenerMap::iterator i = propertyListeners.begin(); i != propertyListeners.end(); i++) {
00169             (*i).second->notifyPropertyChange(*event);
00170         }
00171     }
00172 }
00173 
00174 
00175 void RemoteProperty::write(int start, const string& newdata)
00176 {
00177     vRef<Message> m = new Message();
00178     vRef<LocalSite> ls = RemoteVobject::initFields(this, &m, "property:write", true);
00179     char x[16];
00180     snprintf(x, sizeof(x), "%i", start);
00181     m->insertField(-1, "start", x);
00182     m->insertField(-1, "data", newdata);
00183     sendMessage(&m);
00184     vRef<RemoteSite> site = dynamic_cast<RemoteSite&>(getSite());
00185     vRef<Message> n = ls->waitFor(m->getNonce(), &site);
00186 }
00187 
00188 void RemoteProperty::replace(const string& newdata, const string& newtype)
00189 {
00190     vRef<Message> m = new Message();
00191     vRef<LocalSite> ls = RemoteVobject::initFields(this, &m, "property:replace", true);
00192     m->insertField(-1, "data", newdata);
00193 
00194     // if no type was supplied, assume the old cached one still is correct
00195     if(newtype == "?")
00196         m->insertField(-1, "datatype", getRawDataType());
00197     else
00198         m->insertField(-1, "datatype", newtype);
00199     
00200     sendMessage(&m);
00201     vRef<RemoteSite> site = dynamic_cast<RemoteSite&>(getSite());
00202     vRef<Message> n = ls->waitFor(m->getNonce(), &site);
00203 }
00204 
00205 
00206 
00207 void RemoteProperty::lengthUpdateHandler(Message* m)
00208 {
00209     if(m->getNumFields() > 0) {
00210         raw_length = atoi(m->getField(0).value.c_str());
00211         decoded = false;
00212     }
00213 }
00214 
00215 void RemoteProperty::writeUpdateHandler(Message* m)
00216 {
00217     try {
00218         int off = atoi(m->getField("start").value.c_str());
00219         string oldvalue = raw_data;
00220         raw_data.replace(off, m->getField("data").value.size(), m->getField("data").value);
00221         raw_datatype = m->getField("datatype").value;
00222         raw_length = raw_data.size();
00223         decoded = false;        
00224 
00225         vRef<PropertyEvent> event = 
00226             new PropertyEvent(PropertyEvent::PropertyWrite,
00227                               *this, *this, 
00228                               off, raw_length,
00229                               raw_data, raw_datatype,
00230                               oldvalue, raw_datatype,
00231                               false);
00232 
00233         for(PropertyListenerMap::iterator i = propertyListeners.begin();
00234             i != propertyListeners.end();
00235             i++) {
00236             (*i).second->notifyPropertyChange(*event);
00237         }
00238     } catch(Message::NoSuchFieldError) {
00239     }
00240 }
00241 
00242 void RemoteProperty::replaceUpdateHandler(Message* m)
00243 {
00244         try {
00245             string oldvalue = raw_data;
00246             string olddatatype = raw_datatype;
00247             raw_data = m->getField("data").value;
00248             raw_datatype = m->getField("datatype").value;
00249             raw_length = raw_data.size();
00250             decoded = false;
00251 
00252         vRef<PropertyEvent> event = 
00253             new PropertyEvent(PropertyEvent::PropertyReplace,
00254                               *this, *this,
00255                               raw_data, raw_datatype,
00256                               oldvalue, olddatatype,
00257                               false);
00258 
00259             for(PropertyListenerMap::iterator i = propertyListeners.begin();
00260                 i != propertyListeners.end();
00261                 i++) {
00262                 (*i).second->notifyPropertyChange(*event);
00263             }
00264         } catch(Message::NoSuchFieldError) {
00265         }
00266 }
00267 
00268 void RemoteProperty::startListeningReplyHandler(Message* m)
00269 {
00270     const Message::Field& f = m->getField("listen");
00271     if(f.value == "property") {
00272         Property::addPropertyListener(&DoNothingPropertyListener::static_);
00273     }
00274 }
00275 
00276 MetaObject* RemoteProperty::new_RemoteProperty(MetaObject* superobject, const string& type)
00277 {
00278     return new RemoteProperty(superobject);
00279 }
00280 
00281 void RemoteProperty::addPropertyListener(PropertyListener* pl, bool refresh)
00282 {
00283     if(propertyListeners.empty()) {
00284 //      clearCache();   // correct? XXX
00285 
00286         if(refresh) {
00287             vRef<Message> m = new Message();
00288             vRef<LocalSite> ls = RemoteVobject::initFields(this, &m, "property:start-listening", true);
00289             m->insertField(-1, "listen", "property");
00290 
00291             sendMessage(&m);
00292 
00293             vRef<Site> site = getSite();
00294             vRef<Message> r = ls->waitFor(m->getNonce(), dynamic_cast<RemoteSite*>(&site));
00295         }
00296         Property::addPropertyListener(pl, refresh);
00297         string d;
00298         readRaw(d, 0, getRawLength());
00299 
00300         vRef<PropertyEvent> event = 
00301             new PropertyEvent(PropertyEvent::PropertyReplace,
00302                               *this, *this,
00303                               d, getRawDataType(),
00304                               false);
00305 
00306         pl->notifyPropertyChange(*event);
00307     } else {
00308         Property::addPropertyListener(pl, refresh);
00309         string d;
00310         readRaw(d, 0, getRawLength());
00311 
00312         if(refresh) {
00313             vRef<PropertyEvent> event = 
00314                 new PropertyEvent(PropertyEvent::PropertyReplace,
00315                                   *this, *this,
00316                                   d, getRawDataType(),
00317                                   false);
00318             pl->notifyPropertyChange(*event);
00319         }
00320     }
00321 }
00322 
00323 void RemoteProperty::removePropertyListener(PropertyListener* pl)
00324 {
00325     Property::removePropertyListener(pl);
00326 
00327     if(propertyListeners.size() == 1 && propertyListeners.count(&DoNothingPropertyListener::static_) == 1)
00328         propertyListeners.erase(&DoNothingPropertyListener::static_);
00329 
00330     if(propertyListeners.empty()) {
00331         vRef<Message> m = new Message();
00332         vRef<LocalSite> ls = RemoteVobject::initFields(this, &m, "property:stop-listening", false);
00333              
00334         m->insertField(-1, "listen", "property");
00335         
00336         sendMessage(&m);
00337     }
00338 }
00339 
00340 void RemoteProperty::clearCache()
00341 {
00342     data="";
00343     raw_data = "";
00344     datatype="?";
00345     raw_datatype = "?";
00346     offset=-1;
00347     raw_length=-1;
00348     data_length = 0;
00349     decoded = false;
00350 }

Generated on Tue Aug 12 03:55:46 2003 for Interreality Project - VOS by doxygen 1.3.2