-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
i #223 Add GoF Module and QoL for Text Module
The GoF Module slighly extends the previous GoF Notebook API to facilitate integration to other analysis in Kaiaulu. - De-coupled GoF Parser into Parser/Writer - Sub-setting of GoF Output from Classes/Methods/Variables -> Classes - Mapping from Classes to Filepaths - Reorganization of functions into a dedicated GoF module. Signed-off-by: Carlos Paradis <[email protected]>
- Loading branch information
1 parent
f350952
commit ad6efa7
Showing
11 changed files
with
317 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
# Kaiaulu - https://github.com/sailuh/kaiaulu | ||
# | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
#' Write GoF Patterns | ||
#' | ||
#' Write GoF patterns generated by `pattern4.jar` into a a table. | ||
#' \url{https://www.srcml.org/documentation.html}. | ||
#' Pattern4.jar is available on | ||
#' [Tsantalis' homepage](https://users.encs.concordia.ca/~nikolaos/pattern_detection.html)). | ||
#' | ||
#' @param pattern4_path The path to Tsantalis' pattern4 jar | ||
#' @param class_folder_path The path to a folder one | ||
#' level above subdirectories that contain the class files. | ||
#' @param output_filepath Optional path to store the XML generated by pattern4. If not | ||
#' specified, it will be saved to `/tmp/gof.xml`. | ||
#' | ||
#' @return A data.table containing the parsed gof patterns per class. | ||
#' @references N. Tsantalis, A. Chatzigeorgiou, G. Stephanides, S. T. Halkidis, | ||
#' "Design Pattern Detection Using Similarity Scoring", | ||
#' IEEE Transactions on Software Engineering, | ||
#' vol. 32, no. 11, pp. 896-909, November, 2006. | ||
#' @export | ||
write_gof_patterns <- function(pattern4_path,class_folder_path,output_filepath='/tmp/gof.xml'){ | ||
|
||
pattern4_path <- path.expand(pattern4_path) | ||
class_folder_path <- path.expand(class_folder_path) | ||
|
||
if(!file.exists(pattern4_path)) stop("The specified pattern4_path does not exist!") | ||
if(!dir.exists(class_folder_path)) stop("The specified class_folder_path does not exist!") | ||
|
||
# java -Xms32m -Xmx512m -jar pattern4.jar -target "C:\foo\myclasses" -output "C:\foo\output.xml" | ||
gof_pattern_xml_path <- system2("java", | ||
args = c('-Xms64m','-Xmx100000m','-jar', | ||
pattern4_path, | ||
'-target',paste0('"',class_folder_path,'"'), | ||
'-output',paste0('"',output_filepath,'"')), | ||
stdout = TRUE, | ||
stderr = FALSE) | ||
} | ||
|
||
#' Parse GoF Patterns | ||
#' | ||
#' Parses GoF patterns generated by \code{\link{write_gof_patterns}} into a a table. | ||
#' \url{https://www.srcml.org/documentation.html}. | ||
#' Pattern4.jar is available on | ||
#' [Tsantalis' homepage](https://users.encs.concordia.ca/~nikolaos/pattern_detection.html)). | ||
#' | ||
#' @param output_filepath Optional path to read the XML generated by \code{\link{write_gof_patterns}}. If not | ||
#' specified, it will be assumed saved to the temporary folder path `/tmp/gof.xml`. | ||
#' | ||
#' @return A data.table containing the parsed gof patterns per class. | ||
#' @references N. Tsantalis, A. Chatzigeorgiou, G. Stephanides, S. T. Halkidis, | ||
#' "Design Pattern Detection Using Similarity Scoring", | ||
#' IEEE Transactions on Software Engineering, | ||
#' vol. 32, no. 11, pp. 896-909, November, 2006. | ||
#' @export | ||
parse_gof_patterns <- function(output_filepath='/tmp/gof.xml'){ | ||
gof_pattern_xml <- XML::xmlTreeParse(output_filepath) | ||
|
||
# The <system> root node enumerates a fixed number of <pattern> tags. | ||
gof_root <- XML::xmlRoot(gof_pattern_xml) #class => XML Node | ||
patterns <- XML::xmlChildren(gof_root) #class => XMLNodeList (lapply safe) | ||
|
||
parse_instance <- function(instance){ | ||
|
||
roles <- XML::xmlChildren(instance) | ||
role_names <- sapply(roles,XML::xmlGetAttr,"name") | ||
element <- sapply(roles,XML::xmlGetAttr,"element") | ||
|
||
instance <- data.table(instance_id, | ||
role_name = role_names, | ||
element = element) | ||
|
||
instance_id <<- instance_id + 1 | ||
|
||
return(instance) | ||
} | ||
|
||
parse_pattern <- function(pattern){ | ||
# Each GoF pattern, if occurring on the code, is assigned an instance | ||
n_instances <- XML::xmlSize(pattern) | ||
|
||
# The XML mentions the pattern name even with no instances detected. We do not | ||
# include the pattern name if no instances are detected. | ||
if(n_instances > 0){ | ||
|
||
# Note counter bypasses lapply scope <<- | ||
instance_id <<- 1 | ||
|
||
pattern_name <- XML::xmlGetAttr(pattern,"name") | ||
|
||
instances <- XML::xmlChildren(pattern) | ||
instances_dt <- rbindlist(lapply(instances,parse_instance)) | ||
instances_dt$pattern_name <- pattern_name | ||
return(instances_dt) | ||
}else{ | ||
return(data.table()) | ||
} | ||
} | ||
patterns_dt <- rbindlist(lapply(patterns,parse_pattern)) | ||
|
||
patterns_dt <- patterns_dt[,.(pattern_name,instance_id,role_name,element)] | ||
return(patterns_dt) | ||
} | ||
|
||
|
||
#' Subset GoF Classes | ||
#' | ||
#' The \code{\link{write_gof_patterns}} contains not only | ||
#' the participation of a class in a GoF Pattern, but also | ||
#' the participation of methods and variables when applicable. | ||
#' To distinguish a row entry among class, method or variable, | ||
#' we must subset the role names that are associated to classes. | ||
#' This information can be obtained by inspecting the source code | ||
#' of a similar tool to pattern4 by Tsantalis. | ||
#' | ||
#' More specifically, every pattern that pattern4.jar can identify is | ||
#' defined as a PatternDescriptor in DPD4Eclipse/src/gr/uom/java/pattern | ||
#' /PatternGenerator.java (see: https://github.com/tsantalis/DPD4Eclipse). | ||
#' | ||
#' E.g. The PatternDescriptor Decorator has rowNameList.add("Component"); | ||
#' rowNameList.add("Decorator"); Therefore, in the XML output by pattern4.jar, | ||
#' it is guaranteed when (pattern_name == "Decorator" & role_name == "Component") or | ||
#' (pattern_name == "Decorator" & role_name == "Decorator"). | ||
#' | ||
#' By following this process, a list of role names can be defined to subset the table | ||
#' to only contain classes. | ||
#' | ||
#' Note pattern4 executes in bytecode, hence the classes are identified by their namespace. | ||
#' Refer to \code{\link{query_src_text_namespace}} to obtain a table to map namespace classes | ||
#' to filepaths. | ||
#' @param gof_patterns A table of parsed GoF Patterns | ||
#' obtained from \code{\link{parse_gof_patterns}}. | ||
#' @export | ||
subset_gof_class <- function(gof_patterns){ | ||
lead_patterns <- c('Creator', 'Abstraction', 'Adapter', 'Singleton', 'Prototype', 'Decorator', 'AbstractClass', 'Composite', 'Subject', 'State', 'Visitor', 'Strategy', 'Observer', 'Command', 'Handler', 'Component', 'Context', 'Implementor', 'ConcreteElement', 'Prototype', 'Client', 'Proxy', 'RealSubject', 'Subject', 'FamilyHead', 'Redirecter') | ||
return(gof_patterns[role_name %in% lead_patterns]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.