Skip to content

Commit

Permalink
Added dna_getAttributes function to rDNA
Browse files Browse the repository at this point in the history
Part of #255
  • Loading branch information
leifeld committed Jan 5, 2023
1 parent 10898fc commit 5609b9e
Show file tree
Hide file tree
Showing 6 changed files with 310 additions and 10 deletions.
38 changes: 37 additions & 1 deletion dna/src/main/java/dna/HeadlessDna.java
Expand Up @@ -724,7 +724,7 @@ public void rBackbone(double p, int T, String statementType, String variable1, b
*/

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

/**
* Retrieve entities with attributes for a specific variable with a given variable name and statement type ID.
*
* @param statementTypeId The statement type ID in which the variable is defined.
* @param variable The name of the variable.
* @return Data frame with entities and attributes, as defined in {@link sql.DataExchange#getAttributes(int)}.
*/
public DataFrame getAttributes(int statementTypeId, String variable) {
DataFrame df = sql.DataExchange.getAttributes(statementTypeId, variable);

LogEvent l = new LogEvent(Logger.MESSAGE,
"Attributes have been queried.",
"The attributes for Variable \"" + variable + "\" have been successfully retrieved from the database.");
Dna.logger.log(l);

return df;
}

/**
* Retrieve entities with attributes for a specific variable with a given variable name and statement type name.
*
* @param statementType The statement type in which the variable is defined.
* @param variable The name of the variable.
* @return Data frame with entities and attributes, as defined in {@link sql.DataExchange#getAttributes(int)}.
*/
public DataFrame getAttributes(String statementType, String variable) {
DataFrame df = sql.DataExchange.getAttributes(statementType, variable);

LogEvent l = new LogEvent(Logger.MESSAGE,
"Attributes have been queried.",
"The attributes for Variable \"" + variable + "\" have been successfully retrieved from the database.");
Dna.logger.log(l);

return df;
}

/**
* Set entities and attributes for a specific variable.
*
Expand Down
63 changes: 60 additions & 3 deletions dna/src/main/java/sql/DataExchange.java
Expand Up @@ -29,7 +29,7 @@ public class DataExchange {
* available for the variable being queried.
*/
static public DataFrame getAttributes(int variableId) {
Object[][] data = new Object[0][3];
Object[][] data = null;
ArrayList<String> attributeVariableNames = new ArrayList<String>();
try (Connection conn = Dna.sql.getDataSource().getConnection();
PreparedStatement s1 = conn.prepareStatement("SELECT AttributeVariable FROM ATTRIBUTEVARIABLES WHERE VariableId = ? ORDER BY ATTRIBUTEVARIABLES.ID ASC;");
Expand Down Expand Up @@ -59,19 +59,20 @@ static public DataFrame getAttributes(int variableId) {
ResultSet r2;
int entityId;
int rowCounter = 0;
int columnCounter = 0;
int columnCounter;
while(r1.next()) {
entityId = r1.getInt("ID");
data[rowCounter][0] = entityId; // entity ID
data[rowCounter][1] = r1.getString("Value"); // entity value
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

// go through attribute values in inner loop
columnCounter = 0;
s4.setInt(1, variableId);
s4.setInt(2, entityId);
r2 = s4.executeQuery();
while (r2.next()) {
data[rowCounter][columnCounter + 3] = r2.getString(attributeVariableNames.get(columnCounter));
data[rowCounter][columnCounter + 3] = r2.getString("AttributeValue");
columnCounter++;
}
rowCounter++;
Expand Down Expand Up @@ -100,6 +101,62 @@ static public DataFrame getAttributes(int variableId) {
return df;
}

/**
* A wrapper for {@link #getAttributes(int)} that first retrieves the variable ID based on statement type ID and
* variable name.
*
* @param statementTypeId The statement type ID in which the variable is defined.
* @param variable The name of the variable.
* @return A data frame as returned by {@link #getAttributes(int)}.
*/
static public DataFrame getAttributes(int statementTypeId, String variable) {
int variableId = -1;
try (Connection conn = Dna.sql.getDataSource().getConnection();
PreparedStatement s = conn.prepareStatement("SELECT ID FROM VARIABLES WHERE Variable = ? AND StatementTypeId = ?;")) {
s.setString(1, variable);
s.setInt(2, statementTypeId);
ResultSet r = s.executeQuery();
while (r.next()) {
variableId = r.getInt(1);
}
} catch (SQLException ex) {
LogEvent l = new LogEvent(Logger.ERROR,
"Could not retrieve variable ID for variable \"" + variable + ".",
"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.",
ex);
Dna.logger.log(l);
}
return getAttributes(variableId);
}

/**
* A wrapper for {@link #getAttributes(int)} that first retrieves the variable ID based on statement type and
* variable names.
*
* @param statementType The statement type in which the variable is defined.
* @param variable The name of the variable.
* @return A data frame as returned by {@link #getAttributes(int)}.
*/
static public DataFrame getAttributes(String statementType, String variable) {
int variableId = -1;
try (Connection conn = Dna.sql.getDataSource().getConnection();
PreparedStatement s = conn.prepareStatement("SELECT ID FROM VARIABLES WHERE Variable = ? AND StatementTypeId = (SELECT ID FROM STATEMENTTYPES WHERE Label = ?);")) {
s.setString(1, variable);
s.setString(2, statementType);
ResultSet r = s.executeQuery();
while (r.next()) {
variableId = r.getInt(1);
}
} catch (SQLException ex) {
LogEvent l = new LogEvent(Logger.ERROR,
"Could not retrieve variable ID for variable \"" + variable + ".",
"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.",
ex);
Dna.logger.log(l);
}
return getAttributes(variableId);
}

/**
* Set entities and attributes for a variable by comparing with a supplied data frame.
*
Expand Down
16 changes: 10 additions & 6 deletions rDNA/DESCRIPTION
@@ -1,12 +1,16 @@
Package: rDNA
Version: 3.0.9
Date: 2022-12-18
Date: 2023-01-08
Title: Discourse Network Analysis in R
Authors@R:
person("Philip",
"Leifeld",
email = "Philip.Leifeld@essex.ac.uk",
role = c("aut", "cre", "cph"))
c(person(given = "Philip",
family = "Leifeld",
email = "Philip.Leifeld@essex.ac.uk",
role = c("aut", "cre", "cph")),
person(given = "Tim",
family = "Henrichsen",
email = "Tim.Henrichsen@warwick.ac.uk",
role = "ctb"))
Maintainer: Philip Leifeld <Philip.Leifeld@essex.ac.uk>
Description: Qualitative content analysis and discourse network analysis
using the Java software Discourse Network Analyzer (DNA).
Expand All @@ -25,4 +29,4 @@ URL: https://github.com/leifeld/dna
BugReports: https://github.com/leifeld/dna/issues
Encoding: UTF-8
Language: en-US
RoxygenNote: 7.2.1
RoxygenNote: 7.2.3
1 change: 1 addition & 0 deletions rDNA/NAMESPACE
Expand Up @@ -11,6 +11,7 @@ S3method(print,dna_network_twomode)
export(dna_backbone)
export(dna_barplot)
export(dna_closeDatabase)
export(dna_getAttributes)
export(dna_init)
export(dna_jar)
export(dna_network)
Expand Down
140 changes: 140 additions & 0 deletions rDNA/R/rDNA.R
Expand Up @@ -11,6 +11,7 @@ dnaEnvironment <- new.env(hash = TRUE, parent = emptyenv())
'Version: ', desc$Version, '\n',
'Date: ', desc$Date, '\n',
'Author: Philip Leifeld (University of Essex)\n',
'Contributor: Tim Henrichsen (University of Warwick)\n',
'Project home: github.com/leifeld/dna'
)
}
Expand Down Expand Up @@ -585,6 +586,145 @@ dna_openConnectionProfile <- function(file, coderPassword = "") {
coderPassword)
}

#' Get the entities and attributes for a variable
#'
#' Retrieve the entities and their attributes for a variable in DNA
#'
#' This function retrieves the entities and their attributes for a given
#' variable from the DNA database as a \code{dna_attributes} object. Such an
#' object is an extension of a data frame and can be treated as such.
#'
#' There are three ways to use this function: by specifying only the variable
#' ID; by specifying the variable name and its statement type ID; and by
#' specifying the variable name and its statement type name.
#'
#' @param statementType The name of the statement type in which the variable is
#' defined for which entities and values should be retrieved. Only required if
#' \code{variableId} is not supplied. Either \code{statementType} or
#' \code{statementTypeId} must be specified in this case.
#' @param variable The name of the variable for which the entities and
#' attributes should be returned. In addition to this argument, either the
#' statement type name or statement type ID must be supplied to identify the
#' variable correctly. If the \code{variableId} a specified, the
#' \code{variable} argument is unnecessary and the statement type need not be
#' supplied.
#' @param statementTypeId The ID of the statement type in which the variable is
#' defined for which entities and values should be retrieved. Only required if
#' \code{variableId} is not supplied. Either \code{statementType} or
#' \code{statementTypeId} must be specified in this case.
#' @param variableId The ID of the variable for which the entities and
#' attributes should be returned. If this argument is supplied, the other
#' three arguments are unnecessary.
#'
#' @examples
#' \dontrun{
#' dna_init()
#' dna_sample()
#' dna_openDatabase("sample.dna", coderId = 1, coderPassword = "sample")
#'
#' dna_getAttributes(variableId = 1)
#' dna_getAttributes(statementTypeId = 1, variable = "organization")
#' dna_getAttributes(statementType = "DNA Statement", variable = "concept")
#' }
#'
#' @author Philip Leifeld
#'
#' @importFrom rJava .jcall
#' @importFrom rJava J
#' @export
dna_getAttributes <- function(statementType = NULL,
variable = NULL,
statementTypeId = NULL,
variableId = NULL) {

# check if the arguments are valid
statementTypeValid <- TRUE
if (is.null(statementType) || !is.character(statementType) || length(statementType) != 1 || is.na(statementType) || statementType == "") {
statementTypeValid <- FALSE
}

statementTypeIdValid <- TRUE
if (is.null(statementTypeId) || !is.numeric(statementTypeId) || length(statementTypeId) != 1 || is.na(statementTypeId) || statementTypeId %% 1 != 0) {
statementTypeIdValid <- FALSE
}

variableValid <- TRUE
if (is.null(variable) || !is.character(variable) || length(variable) != 1 || is.na(variable) || variable == "") {
variableValid <- FALSE
}

variableIdValid <- TRUE
if (is.null(variableId) || !is.numeric(variableId) || length(variableId) != 1 || is.na(variableId) || variableId %% 1 != 0) {
variableIdValid <- FALSE
}

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."
if ((!variableValid && !variableIdValid) || (!statementTypeIdValid && !statementTypeValid && !variableIdValid)) {
stop(errorString)
}

if (variableIdValid && variableValid) {
variable <- NULL
variableValid <- FALSE
warning("Both a variable ID and a variable name were supplied. Ignoring the 'variable' argument.")
}

if (statementTypeIdValid && statementTypeValid && !variableIdValid && variableValid) {
statementType <- NULL
statementTypeValid <- FALSE
warning("Both a statement type ID and a statement type name were supplied. Ignoring the 'statementType' argument.")
}

if (variableIdValid && (statementTypeIdValid || statementTypeValid)) {
statementTypeId <- NULL
statementTypeIdValid <- FALSE
statementType <- NULL
statementTypeValid <- FALSE
warning("If a variable ID is provided, a statement type is not necessary. Ignoring the 'statementType' and 'statementTypeId' arguments.")
}

# get the data from the DNA database using rJava
if (variableIdValid) {
a <- .jcall(dnaEnvironment[["dna"]]$headlessDna,
"Lexport/DataFrame;",
"getAttributes",
as.integer(variableId))
} else if (variableValid && statementTypeIdValid) {
a <- .jcall(dnaEnvironment[["dna"]]$headlessDna,
"Lexport/DataFrame;",
"getAttributes",
as.integer(statementTypeId),
variable)
} else if (variableValid && statementTypeValid) {
a <- .jcall(dnaEnvironment[["dna"]]$headlessDna,
"Lexport/DataFrame;",
"getAttributes",
statementType,
variable)
} else {
stop(errorString)
}

# extract the relevant information from the Java reference
varNames <- .jcall(a, "[S", "getVariableNames")
nr <- .jcall(a, "I", "nrow")
nc <- .jcall(a, "I", "ncol")

# create an empty data frame with the first (integer) column for IDs
dat <- cbind(data.frame(ID = integer(nr)),
matrix(character(nr), nrow = nr, ncol = nc - 1))
# populate the data frame
for (i in 0:(nr - 1)) {
for (j in 0:(nc - 1)) {
dat[i + 1, j + 1] <- J(a, "getValue", as.integer(i), as.integer(j))
}
}
rownames(dat) <- NULL
colnames(dat) <- varNames
class(dat) <- c("dna_attributes", class(dat))
return(dat)
}

#' Compute and retrieve a network
#'
#' Compute and retrieve a network from DNA.
Expand Down
62 changes: 62 additions & 0 deletions rDNA/man/dna_getAttributes.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5609b9e

Please sign in to comment.