Re: Cannot call RegisterDataSource on a own datasource
Axel Hecht <[email protected]> Mon, 04 Feb 2008 14:52:25 +0100
| Newsgroups | gmane.comp.mozilla.devel.rdf |
|---|---|
| Message-ID | <[email protected]> |
mcben wrote: > On 4 fév, 09:27, Axel Hecht <[email protected]> wrote: >> mcben wrote: >>> Hi folks, >>> Here is quite a long post about a problem with a own datasource >>> implementation based on a xml-datasource. >>> I'm looking for any clues or links that could help me to achieve my >>> first goal : a custom datasource that i could fill from a CSV file. >>> Thanks in advance for reading me :) >>> I'm creating a javascript component that fetches a CSV file with >>> XMLHttpRequest, parses it, then adds lines as RDF resources in a RDF >>> datasource. >>> Its contractid is like "@mozilla.org/rdf/datasource;1?name=mydatasource" >>> so as to get it in the chrome with the "rdf:mydatasource" keyword. >>> I started this work by using an in-memory-datasource as the __proto__ >>> properties of my javascript prototype. >>> I could fetch my file and appends data in the datasource : the result >>> was shown in a rdf tree. >>> The first problem with this design was that i was not able to overwrite >>> some nsIRDFDataSource methods (not a real problem in fact), nor extends >>> the in-memory-datasource component with other interfaces : the QI method >>> of my component was never called, so i got a NS_ERROR_NO_INTERFACE >>> error, when i QI another interface (eg: nsIDOMListener to adds >>> XMLHttpRequest callback in my chrome). >>> Then i took a look a the rdf:localstore C++ implementation >>> (nsLocalStore.cpp) and i'm quite happy with its design : it works like a >>> wrapper around a xml-datasource. It "justs" load data from >>> localstore.rdf in the profile directory or creates it if it does not exist. >>> Then with that, I could even read and store a cached version of my CSV >>> file on disk. >>> So, I've made the same design in my javascript component, all >>> nsIRDFDataSource related methods are forwarded to a "mInner" >>> xml-datasource property. >>> But when i try to call RegisterDataSource to register my datasource in >>> the constructor of my component, it throws a NS_ERROR_FAILURE : >>> Here is the code : >>> this._loadLocalData(); >>> RDF.RegisterDataSource(this, false); >>> this._loadRemoteData(); >>> If i log "this" the console service returns me that is an Object. >>> That's the problem ? >>> In fact I get from the chrome : [xpconnect wrapped (nsISupports, >>> nsIRDFDataSource, nsIRDFRemoteDataSource)] after the registration, even >>> if the registration fails. >>> But, the nsIRDFRemoteDatasource Init method is called at every calls >>> from chrome. >>> Maybe the real problem comes from the xml-datasource initialization. >>> The following code is called by the constructor of my component : >>> this.mInner = Components >>> .classes["@mozilla.org/rdf/datasource;1?name=xml-datasource"] >>> .createInstance(Components.interfaces.nsIRDFDataSource); >>> var remote = this.mInner >>> .QueryInterface(Components.interfaces.nsIRDFRemoteDataSource); >>> remote.Init(filespec); >>> The "Init" call throws an exception with the following code >>> "0x804b000a". Its related with nsISocketTransport and means >>> STATUS_WAITING_FOR. Ok, why not. >>> Then remote.loaded returns false, and calling remote.Refresh(false) >>> throws a NS_ERROR_FAILURE >>> What is wrong with that ? >>> So i catch this Init exception and get my remote datasource with the RDF >>> Service like this : >>> remote = RDF.GetDataSource(filespec) >>> .QueryInterface(Components.interfaces.nsIRDFRemoteDataSource) >>> this.mInner = remote >>> .QueryInterface(Components.interfaces.nsIRDFDataSource); >>> In that case no problem with remote ds, but the RegisterDataSource go on >>> failing. >>> And later, in the chrome, when i call a method or property that is >>> forwarded to the inner, i got back a undefined result. >>> And i cant look any result in my xul tree. >>> I can post the full source code of the component if needed. >> I suspect that it has something to do with your move from an in-memory >> datasource as inner to an rdf/xml as inner. I didn't get why you made >> that move, was that intentional? > > Hi Axel, > Thank you for your answer. > > To begin, you can grab my component source code here, with the "second > design" implementation (with inner): > http://pastebin.mozilla.org/319272 > > And the xul tree that should show my results look quite simple : > <tree id="itemtypes-tree" flex="1" > datasources="rdf:bi-itemtypes" ref="bi:itemtypes-list"> > <treecols> > <treecol id="col-name" primary="true" label="Name" flex="1"/> > </treecols> > <template> > <treechildren> > <treeitem uri="rdf:*"> > <treerow> > <treecell label="rdf:*" /> > </treerow> > </treeitem> > </treechildren> > </template> > </tree> > > > Hum. yes, the move was partially intentional : > > * My first try with an in-memory datasource was with the instance set > as __proto__ property in the prototype of my component. That is to > say, that it was not with the "inner" design. > The main problem with this design was that i could not extends my > component by implementing other public interface : the QI function of > my component was never called, nor any method that i though they > overrode existing methods of the in-mem. The only thing that i could > improve in this design was the init phase of my component (by filling > in-mem with XMLHttpRequest) nothing else. > > Is it normal that with the following code, the QueryInterface method > is never called, that's why i cant implement any other interfaces ? (i > think that the __proto__ QI is called instead). > > function myComponentImplementation() { > } > myComponentImplementation.prototype { > __proto__ : Components.classes["@mozilla.org/rdf/datasource;1? > name=in-memory-datasource"] > .createInstance(Components.interfaces.nsIRDFDataSource), > > QueryInterface : function(iid) { > if (!iid.equals(C_i.nsIDOMEventListener) && > !iid.equals(C_i.nsIRDFDataSource) && > !iid.equals(C_i.nsIRDFRemoteDataSource) && > !iid.equals(C_i.nsISupports)) > throw Components.results.NS_ERROR_NO_INTERFACE; > ConsoleService.logStringMessage("QI called:" + iid); > return this; > } > } > > > * With the "inner" design, i immediatly use a xml-datasource, just > like the nsLocalStore implementation. With that, i could load a cached > version of the rdf file from disk, and then update it with > XMLHttpRequest only if it really needed. > > Since, you are thinking that the problem can come from the xml- > datasource, i took the same component, and just replaced the xml- > datasource inner, with an in-memory-datasource. > Indeed, it seems there is no major failure with initialization, i can > register the datasource, but the content that i downloaded with > XMLHttpRequest and that i put in the ds is not reflected in my chrome > xul tree, nor i can query my datasource for any target that sould > exists. > > More precisely, about any errors, i had to create the container (the > one to wich I append downloaded resources) with this.mInner (the in- > mem ds) and not my component. Is it normal ? > Look: > this._container = RDFContainer.MakeSeq(this.mInner, > RDF.GetResource(this._struct.ref)); > Even though my component should implement nsIRDFDataSource, that's why > i thought i could do that : > this._container = RDFContainer.MakeSeq(this, > RDF.GetResource(this._struct.ref)); > > But it seems that append does not work anyway. > > > * Finally, why I made the move to xml-datasource ? > (I thought) I could parse a local rdf file at init, and flushes the > modified results at destruction. I even could observe the download > progress from chrome (eg: with a progressbar), etc. > > So any clue ? > What do you think is the best implementation ? > > The first design could be perfect if i could override and extends > methods and interfaces of the __proto__ instance. > > Thank you for reading me. I suspect that something in your implementation is broken. There is http://developer.mozilla.org/en/docs/Aggregating_the_In-Memory_Datasource, but that hasn't been maintained in years, same goes for its sibling documents. Sorry, no better idea, maybe if you post parts of your code there's better chances. Axel