Skip to content

Commit 5609b9e

Browse files
committed
Added dna_getAttributes function to rDNA
Part of #255
1 parent 10898fc commit 5609b9e

File tree

6 files changed

+310
-10
lines changed

6 files changed

+310
-10
lines changed

dna/src/main/java/dna/HeadlessDna.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ public void rBackbone(double p, int T, String statementType, String variable1, b
724724
*/
725725

726726
/**
727-
* Retrieve entities with attributes for a specific variable.
727+
* Retrieve entities with attributes for a specific variable with a given variable ID.
728728
*
729729
* @param variableId ID of the variable to query for entities and their attributes.
730730
* @return Data frame with entities and attributes, as defined in {@link sql.DataExchange#getAttributes(int)}.
@@ -740,6 +740,42 @@ public DataFrame getAttributes(int variableId) {
740740
return df;
741741
}
742742

743+
/**
744+
* Retrieve entities with attributes for a specific variable with a given variable name and statement type ID.
745+
*
746+
* @param statementTypeId The statement type ID in which the variable is defined.
747+
* @param variable The name of the variable.
748+
* @return Data frame with entities and attributes, as defined in {@link sql.DataExchange#getAttributes(int)}.
749+
*/
750+
public DataFrame getAttributes(int statementTypeId, String variable) {
751+
DataFrame df = sql.DataExchange.getAttributes(statementTypeId, variable);
752+
753+
LogEvent l = new LogEvent(Logger.MESSAGE,
754+
"Attributes have been queried.",
755+
"The attributes for Variable \"" + variable + "\" have been successfully retrieved from the database.");
756+
Dna.logger.log(l);
757+
758+
return df;
759+
}
760+
761+
/**
762+
* Retrieve entities with attributes for a specific variable with a given variable name and statement type name.
763+
*
764+
* @param statementType The statement type in which the variable is defined.
765+
* @param variable The name of the variable.
766+
* @return Data frame with entities and attributes, as defined in {@link sql.DataExchange#getAttributes(int)}.
767+
*/
768+
public DataFrame getAttributes(String statementType, String variable) {
769+
DataFrame df = sql.DataExchange.getAttributes(statementType, variable);
770+
771+
LogEvent l = new LogEvent(Logger.MESSAGE,
772+
"Attributes have been queried.",
773+
"The attributes for Variable \"" + variable + "\" have been successfully retrieved from the database.");
774+
Dna.logger.log(l);
775+
776+
return df;
777+
}
778+
743779
/**
744780
* Set entities and attributes for a specific variable.
745781
*

dna/src/main/java/sql/DataExchange.java

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class DataExchange {
2929
* available for the variable being queried.
3030
*/
3131
static public DataFrame getAttributes(int variableId) {
32-
Object[][] data = new Object[0][3];
32+
Object[][] data = null;
3333
ArrayList<String> attributeVariableNames = new ArrayList<String>();
3434
try (Connection conn = Dna.sql.getDataSource().getConnection();
3535
PreparedStatement s1 = conn.prepareStatement("SELECT AttributeVariable FROM ATTRIBUTEVARIABLES WHERE VariableId = ? ORDER BY ATTRIBUTEVARIABLES.ID ASC;");
@@ -59,19 +59,20 @@ static public DataFrame getAttributes(int variableId) {
5959
ResultSet r2;
6060
int entityId;
6161
int rowCounter = 0;
62-
int columnCounter = 0;
62+
int columnCounter;
6363
while(r1.next()) {
6464
entityId = r1.getInt("ID");
6565
data[rowCounter][0] = entityId; // entity ID
6666
data[rowCounter][1] = r1.getString("Value"); // entity value
6767
data[rowCounter][2] = String.format("#%02X%02X%02X", r1.getInt("Red"), r1.getInt("Green"), r1.getInt("Blue")); // entity color as hex RGB value with leading hashtag
6868

6969
// go through attribute values in inner loop
70+
columnCounter = 0;
7071
s4.setInt(1, variableId);
7172
s4.setInt(2, entityId);
7273
r2 = s4.executeQuery();
7374
while (r2.next()) {
74-
data[rowCounter][columnCounter + 3] = r2.getString(attributeVariableNames.get(columnCounter));
75+
data[rowCounter][columnCounter + 3] = r2.getString("AttributeValue");
7576
columnCounter++;
7677
}
7778
rowCounter++;
@@ -100,6 +101,62 @@ static public DataFrame getAttributes(int variableId) {
100101
return df;
101102
}
102103

104+
/**
105+
* A wrapper for {@link #getAttributes(int)} that first retrieves the variable ID based on statement type ID and
106+
* variable name.
107+
*
108+
* @param statementTypeId The statement type ID in which the variable is defined.
109+
* @param variable The name of the variable.
110+
* @return A data frame as returned by {@link #getAttributes(int)}.
111+
*/
112+
static public DataFrame getAttributes(int statementTypeId, String variable) {
113+
int variableId = -1;
114+
try (Connection conn = Dna.sql.getDataSource().getConnection();
115+
PreparedStatement s = conn.prepareStatement("SELECT ID FROM VARIABLES WHERE Variable = ? AND StatementTypeId = ?;")) {
116+
s.setString(1, variable);
117+
s.setInt(2, statementTypeId);
118+
ResultSet r = s.executeQuery();
119+
while (r.next()) {
120+
variableId = r.getInt(1);
121+
}
122+
} catch (SQLException ex) {
123+
LogEvent l = new LogEvent(Logger.ERROR,
124+
"Could not retrieve variable ID for variable \"" + variable + ".",
125+
"Could not retrieve the variable ID for variable \"" + variable + " (statement type ID: " + statementTypeId + ") while trying to retrieve entities and attributes. Check if the statement type ID and variable are valid.",
126+
ex);
127+
Dna.logger.log(l);
128+
}
129+
return getAttributes(variableId);
130+
}
131+
132+
/**
133+
* A wrapper for {@link #getAttributes(int)} that first retrieves the variable ID based on statement type and
134+
* variable names.
135+
*
136+
* @param statementType The statement type in which the variable is defined.
137+
* @param variable The name of the variable.
138+
* @return A data frame as returned by {@link #getAttributes(int)}.
139+
*/
140+
static public DataFrame getAttributes(String statementType, String variable) {
141+
int variableId = -1;
142+
try (Connection conn = Dna.sql.getDataSource().getConnection();
143+
PreparedStatement s = conn.prepareStatement("SELECT ID FROM VARIABLES WHERE Variable = ? AND StatementTypeId = (SELECT ID FROM STATEMENTTYPES WHERE Label = ?);")) {
144+
s.setString(1, variable);
145+
s.setString(2, statementType);
146+
ResultSet r = s.executeQuery();
147+
while (r.next()) {
148+
variableId = r.getInt(1);
149+
}
150+
} catch (SQLException ex) {
151+
LogEvent l = new LogEvent(Logger.ERROR,
152+
"Could not retrieve variable ID for variable \"" + variable + ".",
153+
"Could not retrieve the variable ID for variable \"" + variable + " (statement type: \"" + statementType + "\") while trying to retrieve entities and attributes. Check if the statement type and variable are valid.",
154+
ex);
155+
Dna.logger.log(l);
156+
}
157+
return getAttributes(variableId);
158+
}
159+
103160
/**
104161
* Set entities and attributes for a variable by comparing with a supplied data frame.
105162
*

rDNA/DESCRIPTION

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
Package: rDNA
22
Version: 3.0.9
3-
Date: 2022-12-18
3+
Date: 2023-01-08
44
Title: Discourse Network Analysis in R
55
Authors@R:
6-
person("Philip",
7-
"Leifeld",
8-
email = "[email protected]",
9-
role = c("aut", "cre", "cph"))
6+
c(person(given = "Philip",
7+
family = "Leifeld",
8+
email = "[email protected]",
9+
role = c("aut", "cre", "cph")),
10+
person(given = "Tim",
11+
family = "Henrichsen",
12+
email = "[email protected]",
13+
role = "ctb"))
1014
Maintainer: Philip Leifeld <[email protected]>
1115
Description: Qualitative content analysis and discourse network analysis
1216
using the Java software Discourse Network Analyzer (DNA).
@@ -25,4 +29,4 @@ URL: https://github.com/leifeld/dna
2529
BugReports: https://github.com/leifeld/dna/issues
2630
Encoding: UTF-8
2731
Language: en-US
28-
RoxygenNote: 7.2.1
32+
RoxygenNote: 7.2.3

rDNA/NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ S3method(print,dna_network_twomode)
1111
export(dna_backbone)
1212
export(dna_barplot)
1313
export(dna_closeDatabase)
14+
export(dna_getAttributes)
1415
export(dna_init)
1516
export(dna_jar)
1617
export(dna_network)

rDNA/R/rDNA.R

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ dnaEnvironment <- new.env(hash = TRUE, parent = emptyenv())
1111
'Version: ', desc$Version, '\n',
1212
'Date: ', desc$Date, '\n',
1313
'Author: Philip Leifeld (University of Essex)\n',
14+
'Contributor: Tim Henrichsen (University of Warwick)\n',
1415
'Project home: github.com/leifeld/dna'
1516
)
1617
}
@@ -585,6 +586,145 @@ dna_openConnectionProfile <- function(file, coderPassword = "") {
585586
coderPassword)
586587
}
587588

589+
#' Get the entities and attributes for a variable
590+
#'
591+
#' Retrieve the entities and their attributes for a variable in DNA
592+
#'
593+
#' This function retrieves the entities and their attributes for a given
594+
#' variable from the DNA database as a \code{dna_attributes} object. Such an
595+
#' object is an extension of a data frame and can be treated as such.
596+
#'
597+
#' There are three ways to use this function: by specifying only the variable
598+
#' ID; by specifying the variable name and its statement type ID; and by
599+
#' specifying the variable name and its statement type name.
600+
#'
601+
#' @param statementType The name of the statement type in which the variable is
602+
#' defined for which entities and values should be retrieved. Only required if
603+
#' \code{variableId} is not supplied. Either \code{statementType} or
604+
#' \code{statementTypeId} must be specified in this case.
605+
#' @param variable The name of the variable for which the entities and
606+
#' attributes should be returned. In addition to this argument, either the
607+
#' statement type name or statement type ID must be supplied to identify the
608+
#' variable correctly. If the \code{variableId} a specified, the
609+
#' \code{variable} argument is unnecessary and the statement type need not be
610+
#' supplied.
611+
#' @param statementTypeId The ID of the statement type in which the variable is
612+
#' defined for which entities and values should be retrieved. Only required if
613+
#' \code{variableId} is not supplied. Either \code{statementType} or
614+
#' \code{statementTypeId} must be specified in this case.
615+
#' @param variableId The ID of the variable for which the entities and
616+
#' attributes should be returned. If this argument is supplied, the other
617+
#' three arguments are unnecessary.
618+
#'
619+
#' @examples
620+
#' \dontrun{
621+
#' dna_init()
622+
#' dna_sample()
623+
#' dna_openDatabase("sample.dna", coderId = 1, coderPassword = "sample")
624+
#'
625+
#' dna_getAttributes(variableId = 1)
626+
#' dna_getAttributes(statementTypeId = 1, variable = "organization")
627+
#' dna_getAttributes(statementType = "DNA Statement", variable = "concept")
628+
#' }
629+
#'
630+
#' @author Philip Leifeld
631+
#'
632+
#' @importFrom rJava .jcall
633+
#' @importFrom rJava J
634+
#' @export
635+
dna_getAttributes <- function(statementType = NULL,
636+
variable = NULL,
637+
statementTypeId = NULL,
638+
variableId = NULL) {
639+
640+
# check if the arguments are valid
641+
statementTypeValid <- TRUE
642+
if (is.null(statementType) || !is.character(statementType) || length(statementType) != 1 || is.na(statementType) || statementType == "") {
643+
statementTypeValid <- FALSE
644+
}
645+
646+
statementTypeIdValid <- TRUE
647+
if (is.null(statementTypeId) || !is.numeric(statementTypeId) || length(statementTypeId) != 1 || is.na(statementTypeId) || statementTypeId %% 1 != 0) {
648+
statementTypeIdValid <- FALSE
649+
}
650+
651+
variableValid <- TRUE
652+
if (is.null(variable) || !is.character(variable) || length(variable) != 1 || is.na(variable) || variable == "") {
653+
variableValid <- FALSE
654+
}
655+
656+
variableIdValid <- TRUE
657+
if (is.null(variableId) || !is.numeric(variableId) || length(variableId) != 1 || is.na(variableId) || variableId %% 1 != 0) {
658+
variableIdValid <- FALSE
659+
}
660+
661+
errorString <- "Please supply 1) a variable ID or 2) a statement type name and a variable name or 3) a statement type ID and a variable name."
662+
if ((!variableValid && !variableIdValid) || (!statementTypeIdValid && !statementTypeValid && !variableIdValid)) {
663+
stop(errorString)
664+
}
665+
666+
if (variableIdValid && variableValid) {
667+
variable <- NULL
668+
variableValid <- FALSE
669+
warning("Both a variable ID and a variable name were supplied. Ignoring the 'variable' argument.")
670+
}
671+
672+
if (statementTypeIdValid && statementTypeValid && !variableIdValid && variableValid) {
673+
statementType <- NULL
674+
statementTypeValid <- FALSE
675+
warning("Both a statement type ID and a statement type name were supplied. Ignoring the 'statementType' argument.")
676+
}
677+
678+
if (variableIdValid && (statementTypeIdValid || statementTypeValid)) {
679+
statementTypeId <- NULL
680+
statementTypeIdValid <- FALSE
681+
statementType <- NULL
682+
statementTypeValid <- FALSE
683+
warning("If a variable ID is provided, a statement type is not necessary. Ignoring the 'statementType' and 'statementTypeId' arguments.")
684+
}
685+
686+
# get the data from the DNA database using rJava
687+
if (variableIdValid) {
688+
a <- .jcall(dnaEnvironment[["dna"]]$headlessDna,
689+
"Lexport/DataFrame;",
690+
"getAttributes",
691+
as.integer(variableId))
692+
} else if (variableValid && statementTypeIdValid) {
693+
a <- .jcall(dnaEnvironment[["dna"]]$headlessDna,
694+
"Lexport/DataFrame;",
695+
"getAttributes",
696+
as.integer(statementTypeId),
697+
variable)
698+
} else if (variableValid && statementTypeValid) {
699+
a <- .jcall(dnaEnvironment[["dna"]]$headlessDna,
700+
"Lexport/DataFrame;",
701+
"getAttributes",
702+
statementType,
703+
variable)
704+
} else {
705+
stop(errorString)
706+
}
707+
708+
# extract the relevant information from the Java reference
709+
varNames <- .jcall(a, "[S", "getVariableNames")
710+
nr <- .jcall(a, "I", "nrow")
711+
nc <- .jcall(a, "I", "ncol")
712+
713+
# create an empty data frame with the first (integer) column for IDs
714+
dat <- cbind(data.frame(ID = integer(nr)),
715+
matrix(character(nr), nrow = nr, ncol = nc - 1))
716+
# populate the data frame
717+
for (i in 0:(nr - 1)) {
718+
for (j in 0:(nc - 1)) {
719+
dat[i + 1, j + 1] <- J(a, "getValue", as.integer(i), as.integer(j))
720+
}
721+
}
722+
rownames(dat) <- NULL
723+
colnames(dat) <- varNames
724+
class(dat) <- c("dna_attributes", class(dat))
725+
return(dat)
726+
}
727+
588728
#' Compute and retrieve a network
589729
#'
590730
#' Compute and retrieve a network from DNA.

rDNA/man/dna_getAttributes.Rd

Lines changed: 62 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)