How to control inheritance when dynamically extending Reference Classes - r

In a webcrawler/webscraper-setting, I'd like to dynamically extend my base Reference Class URL in order to be able to write specific methods for respective hosts/domains. Just to be clear, by dynamically I mean something like "automatically generate class definitions as new domains are encountered (e.g. class URL_something.com which would inherit from class URL)".
Works a treat, the only problem is that my class WebPage expects the value of field url to be of class URL. It will accept objects of class URL_something.com as this inherits from class URL, but then actually turns the object into an instance of class URL. So I lose the information that it's actually of class URL_something.com.
Do you have any idea of how I can prevent losing that crucial information?
Code Example
setRefClass(Class="URL", fields=list(x="character"))
setRefClass(Class="WebPage", fields=list(url="URL"))
obj <- new("WebPage", url=new("URL", x="http://www.something.com/home/index.html"))
obj$url
# Method would recognize that there is no class 'URL_something.com'
# yet and thus create it:
setRefClass(Class="URL_something.com", contains="URL")
# Another method would take care of mapping field values to
# an instance of the new class:
> url.obj <- new("URL_something.com", x="http://www.something.com/home/index.html")
> inherits(url.obj, "URL")
[1] TRUE
> obj$url <- url.obj
> class(obj$url)
[1] "URL"
# So I lose the information that it was actually of class "URL_something.com"

Picking up on what Martin said (see comments above): R 2.14.0 fixes what I described above.

Related

How to import class data prior to instantiate the class

Assuming that the class and instantiation of class are held in 2 separate files, how would you import the class data prior to instantiate the class?
Below code works fine if held in one same file, but I suspect that as soon as the code base starts growing you would want to split the data into smaller code chunks.
Should I use [source], does it exist an autoloader or any another guideline?
File: _class_data.R
if (!"package:R6" %in% search()) {
library(R6)
}
# Class 1
Class_1 <- R6Class("Class_1",
public = list(
# Properties:
x = 0,
# Lists:
credentials = list(
user = "user",
password = "pass"
),
# Functions:
myFunction = function() {
return(self$x)
}
)
)
File: run.R
# Should I add a [source] path here to [ _class_data.R] ?
# Instantiate a class by creating an object.
class_1 <- Class_1$new()
If I understand your question, you should be creating a package say MyPackage (containing your classes Class_1) and other person would be consumer, they would need to do library(MyPackage) in their code, before consuming the class.
You can source it if all the consumers are part of the same package.
The most straightforward way is to first run or source the class file. In this case the result will be an environment object that is stored in R:s global environment. This is the class.
As a second step you create an object, by instantiate the same class.
If this instantation is kept within a separate file, you would have to run or source that file also.
Since both objects (class and object) will now exist in the Global environment you can now decide if you want to remove the class and just keep the object.
Following standard guidelines the only name convention difference between the 2 objects would be that the class name start with a capital letter, meanwhile the object holds same name but with all characters in lower case.
If the amount of classes grows it is of course unpractical to administrate the objects one-by-one, and you would probably need some autoload logics.

How to call "public void" method through rJava

In testing a Java API, I need to change a default setting. According to the API's document, it should be done using a method defined within the class using "public void setType". Suppose the class name is 'Node', which is referred using
library(rJava)
.jinit(classpath=jarPath)
Node <- J("Node")
In an Java example from its documents, it's called as
Node nodeX = new Node("X", new Variable[]{x});
nodeX.setType(Type.TEMP);
The default type of nodeX is 'CONTEMP'. How the "setType" method can be called in R through rJava to change its default value to another one? Let's assume 'Type' is an enum variable which has several options, including "CONTEMP","TEMP", etc.
I think you want
library(rJava)
.jinit(classpath=jarPath)
variable <- .jarray(new(J("package.name.Variable", input_arg))
Node <- new(J("package.name.Node"), variable)
Then you can do
type <- J("package.name.Type")$TEMP
Node$setType(type)

Why is "//*" the only xPath query that works when I'm parsing this XML in R using the XML-package?

I'm parsing a Swedish library catalogue using R and the XML-package. Using the library's API, I'm getting XML back from a url containing my query.
I'd like to use xPath queries to parse each record, but everything I do with xPath of the XML-package returns blank lists, everything except "//*". I'm no expert in either xml-parsing nor xPath, but I suspect that it has to do with the xml that my API returns to me.
This is a simple example of one single post in the catalogue:
library(XML)
example.url <- "http://libris.kb.se/sru/swepub?version=1.1&operation=searchRetrieve&query=mat:dok&maximumRecords=1&recordSchema=mods"
doc = xmlParse(example.url)
# Title
works <- xmlRoot(doc)[[4]][["record"]][["recordData"]][["mods"]][["titleInfo"]][["title"]][[1]]
doesntwork <- getNodeSet(doc, "//title")
# The only xPath that returns anything
onlythisworks <- getNodeSet(doc, "//*")
If this has something to do with namespaces (as these answers sugests), all I understan about it is that the API returns data that seems to have namespaces defined in the initial tag, and that I could use that, but this doesn't help me:
# Namespaces are confusing:
title <- getNodeSet(xmlRoot(doc), "//xsi:title", namespaces = c(xsi = "http://www.w3.org/2001/XMLSchema-instance"))
Here's (again) the example return data that I'm trying to parse.
You have to use the right namespace.
Try the following
doesntwork <- getNodeSet(doc, "//mods:title")
#[[1]]
#<title>Horizontal Slot Waveguides for Silicon Photonics Back-End Integration [Elektronisk resurs]</title>
#
#[[2]]
#<title>TRITA-ICT/MAP AVH, 2014:17 \
# </title>
#
#attr(,"class")
#[1] "XMLNodeSet"
BTW: I usually get the namespaces via
nsDefs=xmlNamespaceDefinitions(doc,simplify = TRUE,recursive=TRUE)
But this throws an error in your case. It complains that there are different URIs for the same name space prefix. According to
this site this does not seem to be good coding style.
Update as per OP's comment
I am myself not an xml expert, but here is my take: You can define default namespaces via <tag xmlns=URI>. Non default namespaces are of the form <tag xmlns:a=URI> with a being the respective namespace name.
The problem with your document is that there are two different default namespaces. The first being in <searchRetrieveResponse xmlns="http://www.loc.gov/zing/srw/" ... >. The second is in <mods xmlns="http://www.loc.gov/mods/v3" ... >. Also, you will find the second default namespace URI in the first tag as xmlns:mods="http://www.loc.gov/mods/v3" (where it is non-default). This seems rather messy. Now, the <title> tag is within the <mods> tag. I think that the default namespace defined in <mods> gets overridden by the non default namespace of searchRetrieveResponse (because they have the same URI). So although <mods> and all following tags (like <title>) seems to have default namespaces they actually have the xmlns:mods namespace. But this does not apply to the tag <numberOfRecords> (because it's outside of <mods>). You can access this node via
getNodeSet(doc, "//ns:numberOfRecords",
namespaces = c(ns="http://www.loc.gov/zing/srw/"))
Here you extract the default namespace defined in <searchRetrieveResponse> and give it a name (ns in our case). Then you can explicitly use the default namespace name in your xPath query.

How Qt handle a QList<QList<QByteArray> > in Q_PROPERTY?

In my class, I want a member with type QList<QList<QByteArray> > as a property, should the Q_PROPERTY call be:
Q_PROPERTY(QList myData READ myData)
or
typedef QList<QList<QByteArray> > TYPE_LLB;
Q_PROPERTY(TYPE_LLB myData READ myData)
?
Actually I'm trying QWizard and QWizardPageclasses, data with typeQList<QList<QByteArray> > need to be propagated among pages, Qt manual says registerField and field methods help, but these two methods need widget properties to be defined correctly.
Please help. Thanks!

In R, how do I set an S4 class based on another object's class

I need to create an object of type ShortReadQ from Bioconductor's ShortRead library.
ShortReadQ 'signature(sread = "DNAStringSet", quality =
"QualityScore", id = "BStringSet")'
The quality slot needs to be an object inheriting from QualityScore, of which I can easily determine from another ShortReadQ object that I wish to emulate.
> class(quality(anotherObject))
[1] "SFastqQuality"
attr(,"package")
[1] "ShortRead"
What is the best way to use that information ("SFastqQuality") in the contructor argument?
newObject<-ShortReadQ(sread=...,
quality=SFastqQuality(...),
id=...)
Does this do what you want?
quality = new(class(old.quality.obj)[[1]]))
You might want the get function:
a <- get(class(object))
a(...)
thanks for your responses. they lead me to a solution that works
newObject<-ShortReadQ(sread=...,
quality=new(Class=class(quality(anotherObject)),theFirstParameter=...),
id=...)

Resources