52 Commits

Author SHA1 Message Date
Alex Tusa
484180f717 Merge pull request #18 from atusa17/PAN-10
PAN-10 code & test corrections. 100% coverage & passed.
2019-03-05 11:59:47 -07:00
Alex Tusa
22cd0a74d3 Merge branch 'master' into PAN-10 2019-03-05 11:48:57 -07:00
103d09bb0e PAN-10 added a null check to the recurse method 2019-03-05 11:48:18 -07:00
BrittanyBi
2f5aef8092 PAN-10 ParserService.recurse() code refactored to be more readable. 2019-03-04 23:00:26 -07:00
BrittanyBi
357e9b23cc PAN-10 Refactored direct access of fields to getter and setter methods. 2019-03-04 22:24:27 -07:00
BrittanyBi
6f5bbab5ac PAN-10 Corrected many styling errors which required little refactoring. 2019-03-04 21:23:45 -07:00
Alex Tusa
27e56039f4 Create README.md 2019-03-04 18:15:22 -07:00
Alex Tusa
0167ac1a11 Create README.md 2019-03-04 18:13:36 -07:00
Alex Tusa
0b6e18b795 Update README.md 2019-03-04 18:12:33 -07:00
Alex Tusa
f2498f4bda Update README.md 2019-03-04 18:01:52 -07:00
Alex Tusa
953f8d807c Update README.md 2019-03-04 18:01:24 -07:00
Alex Tusa
b154648fdf Update README.md 2019-03-04 17:59:00 -07:00
Alex Tusa
fae060e039 Update README.md 2019-03-04 17:57:37 -07:00
Alex Tusa
dbce550625 Merge branch 'master' into PAN-10 2019-03-03 19:05:31 -07:00
Alex Tusa
6a8f239995 Update .travis.yml 2019-03-03 19:04:55 -07:00
BrittanyBi
e4594dc900 PAN-10 deleted commented-out code 2019-03-03 19:01:01 -07:00
BrittanyBi
cbaea65b56 PAN-10 travis.yml update 2019-03-03 18:58:34 -07:00
BrittanyBi
e47f2556f6 PAN-10 code & tests. 100% coverage.
Node class extracted from ParserService class.
ParserConfig deleted because it wasn't being used.
2019-03-03 18:51:11 -07:00
BrittanyBi
4b76f2eb69 PAN-10 code & test corrections. Node class extracted from ParserService class. 2019-03-03 17:32:52 -07:00
4130e7bef3 Added the README 2019-03-03 16:15:35 -07:00
96c90a3c49 change git root 2019-03-03 16:13:24 -07:00
Brittany
a1d5a82570 Merge pull request #15 from atusa17/PAN-48
PAN-48
2019-02-27 19:02:38 -07:00
30988fa94a PAN-48 Updated the sonar configuration 2019-02-24 22:40:33 -07:00
0734f6ff10 PAN-48 Added dependency on utilities to the persistence project 2019-02-24 20:31:24 -07:00
030e66f516 PAN-48 Added update test to Definition integration test 2019-02-24 20:25:20 -07:00
9ad185b033 PAN-48 Wrote IntegrationTests for Accounts 2019-02-24 20:22:22 -07:00
68fb41c067 PAN-48 Wrote IntegrationTests for Accounts 2019-02-24 20:13:01 -07:00
327724faf1 PAN-48 Wrote unit tests for the AccountController 2019-02-24 19:59:49 -07:00
9020b0fdbb PAN-48 Wrote unit tests for the updateDefinition method 2019-02-24 19:48:18 -07:00
a3ab3f10bf PAN-48 Created the updateDefinition method 2019-02-24 19:17:51 -07:00
b77a750c30 PAN-48 Created the AccountController and created the copyNonNullProperties method 2019-02-24 19:14:17 -07:00
8c9f2bbd9c PAN-48 Updated the AccountsDto and the AccountsRepository 2019-02-24 17:30:39 -07:00
dantanxiaotian
92aebf0283 Merge pull request #14 from atusa17/PAN-7
Pan 7
2019-02-24 16:37:42 -07:00
bb28de709a PAN-7 Updated the loaddb.sh file 2019-02-24 16:26:17 -07:00
9e4131f693 PAN-7 Updated the .travis.yml file 2019-02-24 16:18:36 -07:00
d0f8e0bafa PAN-7 Reverted the loadDb task 2019-02-24 16:03:55 -07:00
dbba747283 PAN-7 Added the loaddb task as a dependency to the integration tests 2019-02-24 15:47:51 -07:00
09cbc8c64a PAN-7 Wrote unit tests for the DefinitionController 2019-02-24 15:30:05 -07:00
f2c05fb68f PAN-7 Wrote CRUD integration test 2019-02-23 23:13:45 -07:00
207db50b15 PAN-7 fixed the loaddb.bat file for Windows 2019-02-23 20:51:41 -07:00
21ef4f27c8 PAN-7 Added project names to Sonar in the sub projects 2019-02-21 11:24:34 -07:00
1d44395e7b PAN-7 Cleaned up the gradle files 2019-02-21 11:03:33 -07:00
d8e81b1abb Revert "PAN-7 Updated the build.gradle files"
This reverts commit da673068
2019-02-19 11:00:17 -07:00
da673068bb PAN-7 Updated the build.gradle files 2019-02-17 23:17:15 -07:00
abefb397e3 PAN-7 Finished the DefinitionController 2019-02-17 22:22:05 -07:00
dffe0187df PAN-7 Added response codes to DefinitionRepository methods 2019-02-17 18:23:09 -07:00
a4dde1b216 PAN-7 Set up the findAll method in the DefinitionDTO 2019-02-17 17:42:25 -07:00
cc302f17c3 PAN-7 Initial setup of the persistence with Spring Data JPA, Hibernate, Tomcat Server, and Spring Boot 2019-02-17 16:52:31 -07:00
015c80215c Merge remote-tracking branch 'origin/master' 2019-02-14 12:30:22 -07:00
2200a6a2d3 PAN-7 Initial setup of the persistence with Spring Data JPA 2019-02-14 12:24:34 -07:00
dantanxiaotian
b142de57d5 Merge pull request #10 from atusa17/PAN-6-windows-compatibility
PAN-6 added a Windows batch file to load the DB on Windows systems.
2019-02-12 11:42:42 -07:00
04e662ecd6 PAN-6 added a Windows batch file to load the DB on Windows systems. 2019-02-12 10:59:39 -07:00
95 changed files with 2199 additions and 291 deletions
+2 -3
View File
@@ -13,13 +13,12 @@ addons:
- mysql-client
before_install:
- chmod +x pandamonium-theorem-prover/gradlew
- cd pandamonium-theorem-prover
- chmod +x gradlew
before_script:
- mysql_upgrade --force -uroot
- mysql -u root -e 'CREATE DATABASE IF NOT EXISTS pandamonium;'
- mysql -u root -e "CREATE USER 'panda'@'localhost';"
- mysql -u root -e "CREATE USER 'panda'@'localhost' IDENTIFIED BY 'secret';"
- mysql -u root -e "GRANT ALL PRIVILEGES ON *.* to 'panda'@'localhost';"
- mysql -u root pandamonium < persistence/scripts/mysql/local_development.sql
+53 -1
View File
@@ -1,2 +1,54 @@
# Pandamonium Theorem Prover
This is the main repository for the Technical Software Project
This project contains several different modules for different parts of the system.
* [persistence](persistence/README.md)
* [web-server](src/README.md)
## Getting Started
1. Clone the project. `git clone git@github.com:atusa17/tsp.git`
2. Open the `pandamonium-theorem-prover` folder with IntelliJ. Use auto-import for a Gradle project.
3. Individual Components have their own README. Continue there.
## Running the Tests
This project is unit tested with JUnit and Mockito. You can run the unit tests with IntelliJ or Gradle. To run them with IntelliJ, browse to any `*Test.java` file and use IntelliJ's built-in test runner to run or debug the test. To run all the unit tests with Gradle:
* On a Linux or Macintosh machine:
```$ ./gradlew test```
* On a Windows machine:
```$ gradlew.bat test```
You can also test modules individually:
* On a Linux or Macintosh machine:
```$ ./gradlew persistence:test```
* On a Windows machine:
```$ gradlew.bat persistence:test```
## Integration Tests
To run the integration tests with IntelliJ, browse to any `*Test.java` file residing in any module name `integrationTest` and use IntelliJ's built-in test runner to run or debug the test. To run all the integration tests with Gradle:
* On a Linux or Macintosh machine:
```$ ./gradlew integrationTest```
* On a Windows machine
```$ gradlew.bat integrationTest```
## Built with
* [Spring Boot](https://projects.spring.io/spring-boot/) - Web framework
* [Spring Web Flow](https://projects.spring.io/spring-webflow/) - MVC framework
* [Gradle](https://gradle.org/) - Dependency management
* [JUnit](http://junit.org/junit4/) - Unit tests
* [Mockito](http://site.mockito.org/) - Mock objects library
* [Lombok](https://projectlombok.org/) - Boilerplate Code Generator
-1
View File
@@ -1 +0,0 @@
theme: jekyll-theme-midnight
@@ -37,6 +37,14 @@ sonarqube {
}
allprojects {
sonarqube {
properties {
property "sonar.host.url", "https://sonarcloud.io"
property "sonar.projectKey", "atusa17_ptp"
property "sonar.organization", "atusa17-github"
property "sonar.login", "9dcc611cd79f175459248b053b25450e36e38463"
}
}
apply plugin: 'java'
apply plugin: 'jacoco'
apply plugin: 'org.unbroken-dome.test-sets'
@@ -45,6 +53,7 @@ allprojects {
}
subprojects {
apply plugin: 'java'
repositories {
mavenCentral()
}
@@ -55,12 +64,13 @@ subprojects {
compile 'org.slf4j:slf4j-api:1.7.21'
compile "joda-time:joda-time:2.2"
compile('org.springframework:spring-context:5.0.9.RELEASE')
compileOnly 'org.projectlombok:lombok:1.18.4'
testCompile group: 'junit', name: 'junit', version: '4.11'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile('org.mockito:mockito-core:1.10.19') {exclude(group: 'org.hamcrest')}
compileOnly 'org.projectlombok:lombok:1.18.4'
}
test {
@@ -94,11 +104,10 @@ dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
compile 'org.apache.commons:commons-lang3:3.5'
// The production code uses the SLF4J logging API at compile time
compile 'org.slf4j:slf4j-api:1.7.21'
compile 'org.slf4j:slf4j-api:1.7.22'
compile "joda-time:joda-time:2.2"
compile("org.springframework.boot:spring-boot-starter-web")
testCompile group: 'junit', name: 'junit', version: '4.11'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.5.RELEASE'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile "org.springframework:spring-test:5.0.9.RELEASE"
testCompile('org.mockito:mockito-core:1.10.19') {exclude(group: 'org.hamcrest')}
@@ -108,6 +117,12 @@ dependencies {
apt 'org.projectlombok:lombok:1.18.4'
}
project(':persistence') {
dependencies {
compile project(':utilities')
}
}
test {
if (System.properties['test.profile'] != 'integrationTest') {
exclude '**/*integrationTest*'
@@ -129,6 +144,6 @@ compileTestKotlin {
}
wrapper {
gradleVersion = '4.10.2'
gradleVersion = '5.2.1'
distributionType = Wrapper.DistributionType.ALL
}
@@ -0,0 +1,6 @@
#Sun Feb 03 13:43:34 MST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip
View File
+172
View File
@@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save ( ) {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="sonarModuleSettings">
<option name="localAnalysisScripName" value="&lt;PROJECT&gt;" />
<option name="serverName" value="&lt;PROJECT&gt;" />
</component>
</module>
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="sonarModuleSettings">
<option name="localAnalysisScripName" value="&lt;PROJECT&gt;" />
<option name="serverName" value="&lt;PROJECT&gt;" />
</component>
</module>
-1
View File
@@ -1 +0,0 @@
# tsp-main
@@ -1,33 +0,0 @@
plugins {
id 'java'
}
description = 'Provides database access and connectivity'
group 'edu.msudenver.tsp'
version '1.0'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile fileTree(dir: 'lib', include: '**/*.jar')
compile 'com.mchange:c3p0:0.9.5.2'
compile 'mysql:mysql-connector-java:5.1.35'
compile 'org.hibernate:hibernate-validator:5.3.4.Final'
compile 'javax.validation:validation-api:1.1.0.Final'
compile('com.googlecode.log4jdbc:log4jdbc:1.2') {
exclude(group: 'org.slf4j')
}
testCompile 'javax.el:javax.el-api:3.0.0'
}
task loadDb(type: Exec, group: 'Verification', description: 'Reloads the local database.') {
workingDir "./scripts/mysql"
commandLine './loaddb.sh'
}
@@ -1,10 +0,0 @@
package edu.msudenver.tsp.persistence;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class PersistenceConfig {
}
@@ -1,28 +0,0 @@
package edu.msudenver.tsp.persistence.dao;
class BaseDao {
// <T> T findById(final int id) {
// //TODO insert DB calls for finding objects by their ID's
// }
// <T> List<T> queryForList(final String query) {
// //TODO insert DB calls for querying for lists based on the specified query
// }
// <T> T save(final T t) {
// //TODO insert DB calls here for insert and update
// }
<T> void delete(final T t) {
//TODO insert DB calls here to delete
}
// private <T> T insert(final T object) {
// // TODO insert DB calls to insert records
// }
//
// private <T> T update(final T object) {
// //TODO insert DB calls to update records
// }
}
@@ -1,4 +0,0 @@
package edu.msudenver.tsp.persistence.dao;
public class DefinitionDao extends BaseDao {
}
@@ -1,4 +0,0 @@
package edu.msudenver.tsp.persistence.dao;
public class NotationDao extends BaseDao {
}
@@ -1,4 +0,0 @@
package edu.msudenver.tsp.persistence.dao;
public class ProofDao extends BaseDao {
}
@@ -1,4 +0,0 @@
package edu.msudenver.tsp.persistence.dao;
public class TheoremDao extends BaseDao {
}
@@ -1,9 +0,0 @@
package edu.msudenver.tsp.persistence.dto;
import lombok.Data;
@Data
class BaseDto {
private String id;
private int version;
}
@@ -1,4 +0,0 @@
package edu.msudenver.tsp.persistence.dto;
public class DefinitionDto extends BaseDto {
}
@@ -1,11 +0,0 @@
package edu.msudenver.tsp.persistence.manager;
import edu.msudenver.tsp.persistence.dao.DefinitionDao;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@AllArgsConstructor
public class DefinitionManager {
final private DefinitionDao definitionDao;
}
@@ -1,10 +0,0 @@
package edu.msudenver.tsp.persistence.manager;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class ManagerConfig {
}
@@ -1,11 +0,0 @@
package edu.msudenver.tsp.persistence.manager;
import edu.msudenver.tsp.persistence.dao.NotationDao;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@AllArgsConstructor
public class NotationManager {
final private NotationDao notationDao;
}
@@ -1,11 +0,0 @@
package edu.msudenver.tsp.persistence.manager;
import edu.msudenver.tsp.persistence.dao.ProofDao;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@AllArgsConstructor
public class ProofManager {
final private ProofDao proofDao;
}
@@ -1,11 +0,0 @@
package edu.msudenver.tsp.persistence.manager;
import edu.msudenver.tsp.persistence.dao.TheoremDao;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@AllArgsConstructor
public class TheoremManager {
final private TheoremDao theoremDao;
}
@@ -1,11 +0,0 @@
package edu.msudenver.tsp.services.parser;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
//@PropertySource("classpath:development.properties")
public class ParserConfig {
}
@@ -1,26 +0,0 @@
package edu.msudenver.tsp.services.parser;
import edu.msudenver.tsp.persistence.manager.DefinitionManager;
import edu.msudenver.tsp.persistence.manager.NotationManager;
import edu.msudenver.tsp.persistence.manager.ProofManager;
import edu.msudenver.tsp.persistence.manager.TheoremManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
class ParserService {
private final DefinitionManager definitionManager;
private final TheoremManager theoremManager;
private final NotationManager notationManager;
private final ProofManager proofManager;
@Autowired
public ParserService(final DefinitionManager definitionManager, final TheoremManager theoremManager,
final NotationManager notationManager, final ProofManager proofManager) {
this.definitionManager = definitionManager;
this.theoremManager = theoremManager;
this.notationManager = notationManager;
this.proofManager = proofManager;
}
}
@@ -1,17 +0,0 @@
package edu.msudenver.tsp.services.parser;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
@RunWith(MockitoJUnitRunner.class)
public class ParserServiceTest {
@Test
public void test() {
assertEquals(3,3);
}
}
@@ -1,13 +0,0 @@
package edu.msudenver.tsp.website;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/")
public String index() {
return "Welcome to Project Pandamonium!";
}
}
@@ -1,12 +0,0 @@
package edu.msudenver.tsp.website;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
//@PropertySource("classpath:development.properties")
public class WebsiteConfig {
}
@@ -1,13 +0,0 @@
package edu.msudenver.tsp.website;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class HelloControllerTest {
@Test
public void test() {
assertEquals(3, 3);
}
}
@@ -1,15 +0,0 @@
package edu.msudenver.tsp.website.integrationTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
public class HelloControllerIntegrationTest {
@Test
public void test() {
assertEquals(3,3);
}
}
+61
View File
@@ -0,0 +1,61 @@
## PTP Persistence API
The PTP Persistence API is the web API for accessing the theorems database.
<http://localhost:8090/>
## Running from IntelliJ
* Create a new run configuration in IntelliJ.
```
Name: "PTP Persistence API Tomcat"
Application Server: Tomcat (8.5.12)
HTTP Port: 8090
JMX Port: 1090
Deployment tabe: Deploy persistence-api.war (exploded)
```
## Running the Tests
This project is unit tested with JUnit and Mockito. You can run the unit tests with IntelliJ or Gradle. To run them with IntelliJ, browse to any `*Test.java` file and use IntelliJ's built-in test runner to run or debug the test. To run all the unit tests with Gradle:
* On a Linux or Macintosh machine:
```$ ./gradlew test```
* On a Windows machine:
```$ gradlew.bat test```
You can also test modules individually:
* On a Linux or Macintosh machine:
```$ ./gradlew persistence:test```
* On a Windows machine:
```$ gradlew.bat persistence:test```
## Integration Tests
To run the integration tests with IntelliJ, browse to any `*Test.java` file residing in any module name `integrationTest` and use IntelliJ's built-in test runner to run or debug the test. To run all the integration tests with Gradle:
* On a Linux or Macintosh machine:
```$ ./gradlew integrationTest```
* On a Windows machine
```$ gradlew.bat integrationTest```
## Built with
* [Spring Boot](https://projects.spring.io/spring-boot/) - Web framework
* [Spring Web Flow](https://projects.spring.io/spring-webflow/) - MVC framework
* [Spring Data](https://spring.io/projects/spring-data/) - Persistence framework
* [Gradle](https://gradle.org/) - Dependency management
* [JUnit](http://junit.org/junit4/) - Unit tests
* [Mockito](http://site.mockito.org/) - Mock objects library
* [Lombok](https://projectlombok.org/) - Boilerplate Code Generator
* [Hibernate ORM](http://hibernate.org/orm/) - Object/Relational Mapping
+52
View File
@@ -0,0 +1,52 @@
import org.gradle.internal.os.OperatingSystem
plugins {
id 'java'
}
description = 'Provides database access and connectivity'
group 'edu.msudenver.tsp'
version '1.0'
sourceCompatibility = 1.8
sonarqube {
properties {
property "sonar.projectName", 'Pandamonium Persistence Tier'
}
}
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '2.0.5.RELEASE'
compile group: 'org.apache.tomcat', name: 'tomcat-jdbc', version: '9.0.16'
compile group: 'org.springframework.boot', name: 'spring-boot-devtools', version: '2.0.5.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.5.RELEASE'
compile group: 'org.springframework', name: 'spring-aspects', version: '5.1.5.RELEASE'
compile group: 'org.hibernate', name: 'hibernate-core', version: '5.4.1.Final'
compile group: 'com.vladmihalcea', name: 'hibernate-types-52', version: '2.4.1'
compile fileTree(dir: 'lib', include: '**/*.jar')
compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.15'
compile('com.googlecode.log4jdbc:log4jdbc:1.2') {
exclude(group: 'org.slf4j')
}
testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.1.2.RELEASE'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile 'javax.el:javax.el-api:3.0.0'
}
task loadDb(type: Exec, group: 'Verification', description: 'Reloads the local database.') {
if (OperatingSystem.current().isLinux() || OperatingSystem.current().isMacOsX()) {
workingDir "./scripts/mysql"
commandLine './loaddb.sh'
} else {
workingDir "./scripts/mysql"
commandLine=['cmd','/c','loaddb.bat']
}
}
+5
View File
@@ -0,0 +1,5 @@
set mysql_pwd = secret
FOR /R %%s IN (*.sql) do (
echo **** %%s ****
mysql -u panda -psecret < %%s
)
@@ -1,8 +1,7 @@
#!/usr/bin/env bash
export MYSQL_PWD=secret
for sqlScript in $( find . -name "*.sql" -print | sort);
do
echo "**** $sqlScript ****"
mysql --batch --quick --raw --line-numbers --force --user=panda < $sqlScript
mysql -u panda -psecret < $sqlScript
done
@@ -0,0 +1,57 @@
package edu.msudenver.tsp.persistence;
import edu.msudenver.tsp.persistence.dto.AccountDto;
import edu.msudenver.tsp.persistence.repository.AccountsRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Optional;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PersistenceTestConfig.class)
public class AccountsIntegrationTest {
@Autowired private AccountsRepository accountsRepository;
@Test
public void testCRUDFunctionality() {
final AccountDto accountDto = createAccount();
final AccountDto savedAccount = accountsRepository.save(accountDto);
assertNotNull(savedAccount);
assertEquals(Integer.valueOf(0), savedAccount.getVersion());
final int id = savedAccount.getId();
assertEquals("Test username", savedAccount.getUsername());
assertEquals("test password", savedAccount.getPassword());
assertTrue(savedAccount.isAdministratorStatus());
savedAccount.setPassword("Test Update");
final AccountDto updatedAccount = accountsRepository.save(savedAccount);
assertEquals("Test username", savedAccount.getUsername());
assertEquals("Test Update", savedAccount.getPassword());
assertTrue(savedAccount.isAdministratorStatus());
assertEquals(updatedAccount.getId(), id);
accountsRepository.delete(accountDto);
final Optional<AccountDto> deletedAccount = accountsRepository.findById(id);
assertFalse(deletedAccount.isPresent());
}
private AccountDto createAccount() {
final AccountDto accountDto = new AccountDto();
accountDto.setUsername("Test username");
accountDto.setPassword("test password");
accountDto.setAdministratorStatus(true);
return accountDto;
}
}
@@ -0,0 +1,91 @@
package edu.msudenver.tsp.persistence;
import edu.msudenver.tsp.persistence.dto.Definition;
import edu.msudenver.tsp.persistence.dto.DefinitionDto;
import edu.msudenver.tsp.persistence.dto.Notation;
import edu.msudenver.tsp.persistence.repository.DefinitionRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PersistenceTestConfig.class)
public class DefinitionsIntegrationTest {
@Autowired private DefinitionRepository definitionRepository;
@Test
public void testCRUDFunctionality() {
final DefinitionDto definitionDto = createDefinition();
final DefinitionDto savedDefinition = definitionRepository.save(definitionDto);
assertNotNull(savedDefinition);
assertEquals(Integer.valueOf(0), savedDefinition.getVersion());
final int id = savedDefinition.getId();
assertEquals("Test Name", savedDefinition.getName());
assertNotNull(savedDefinition.getDefinition());
assertNotNull(savedDefinition.getNotation());
final List<String> definitionsList = savedDefinition.getDefinition().getDefinitions();
final List<String> notationList = savedDefinition.getNotation().getNotations();
assertEquals(2, definitionsList.size());
assertEquals(1, notationList.size());
assertEquals("Test definition 1", definitionsList.get(0));
assertEquals("Test definition 2", definitionsList.get(1));
assertEquals("\\testLaTeX", notationList.get(0));
savedDefinition.setName("Test Update");
final DefinitionDto updatedDefinition = definitionRepository.save(savedDefinition);
assertEquals("Test Update", updatedDefinition.getName());
assertNotNull(updatedDefinition.getDefinition());
assertNotNull(updatedDefinition.getNotation());
final List<String> updatedDefinitionsList = updatedDefinition.getDefinition().getDefinitions();
final List<String> updatedNotationsList = updatedDefinition.getNotation().getNotations();
assertEquals(2, updatedDefinitionsList.size());
assertEquals(1, updatedNotationsList.size());
assertEquals("Test definition 1", updatedDefinitionsList.get(0));
assertEquals("Test definition 2", updatedDefinitionsList.get(1));
assertEquals("\\testLaTeX", updatedNotationsList.get(0));
assertEquals(id, updatedDefinition.getId());
definitionRepository.delete(updatedDefinition);
final Optional<DefinitionDto> deletedDefinition = definitionRepository.findById(id);
assertFalse(deletedDefinition.isPresent());
}
private DefinitionDto createDefinition() {
final List<String> definitionList = new ArrayList<>();
definitionList.add("Test definition 1");
definitionList.add("Test definition 2");
final Definition definition = new Definition();
definition.setDefinitions(definitionList);
final List<String> notationList = new ArrayList<>();
notationList.add("\\testLaTeX");
final Notation notation = new Notation();
notation.setNotations(notationList);
final DefinitionDto definitionDto = new DefinitionDto();
definitionDto.setName("Test Name");
definitionDto.setDefinition(definition);
definitionDto.setNotation(notation);
return definitionDto;
}
}
@@ -0,0 +1,93 @@
package edu.msudenver.tsp.persistence;
import org.hibernate.SessionFactory;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBuilder;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@EnableJpaRepositories
@EnableJpaAuditing
@EntityScan(basePackages = "edu.msudenver.tsp.persistence")
public class PersistenceTestConfig {
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter());
entityManagerFactoryBean.setDataSource(getDataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setPackagesToScan("edu.msudenver.tsp.persistence");
entityManagerFactoryBean.setJpaProperties(additionalProperties());
return entityManagerFactoryBean;
}
@Bean
public JpaTransactionManager jpaTransactionManager() {
final JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return jpaTransactionManager;
}
private HibernateJpaVendorAdapter vendorAdapter() {
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
return vendorAdapter;
}
@Bean(name = "dataSource")
public DataSource getDataSource(){
return DataSourceBuilder
.create()
.username("panda")
.password("secret")
.url("jdbc:mysql://127.0.0.1:3306/pandamonium?autoReconnect=true&useSSL=false")
.driverClassName("com.mysql.cj.jdbc.Driver")
.build();
}
@Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(final DataSource dataSource) {
final LocalSessionFactoryBuilder sessionFactoryBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionFactoryBuilder.scanPackages("edu.msudenver.tsp.persistence.dto");
return sessionFactoryBuilder.buildSessionFactory();
}
@Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(final SessionFactory sessionFactory) {
return new HibernateTransactionManager(sessionFactory);
}
@Bean
public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {
final DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource);
return initializer;
}
private Properties additionalProperties() {
final Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
properties.setProperty("spring.jpa.show-sql", "true");
properties.setProperty("spring.datasource.tomcat.max-active", "1");
properties.setProperty("hibernate.id.new_generator_mappings","false");
return properties;
}
}
@@ -0,0 +1,109 @@
package edu.msudenver.tsp.persistence;
import org.hibernate.SessionFactory;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBuilder;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import javax.sql.DataSource;
import java.util.Properties;
@SpringBootApplication
@EnableJpaRepositories
@EnableJpaAuditing
@EntityScan
public class PersistenceApi {
@Value("${spring.datasource.username}") private String username;
@Value("${spring.datasource.password}") private String password;
@Value("${spring.jpa.hibernate.ddl-auto}") private String hibernateTablePolicy;
@Value("${spring.datasource.url}") private String databaseUrl;
@Value("${spring.jpa.properties.hibernate.dialect}") private String hibernateDialect;
@Value("${spring.jpa.show-sql}") private String showSql;
@Value("${spring.datasource.driver-class-name}") private String driverClassName;
@Value("${spring.datasource.tomcat.max-active}") private String tomcatPoolMaxActive;
public static void main(final String[] args) {
SpringApplication.run(PersistenceApi.class, args);
}
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setJpaVendorAdapter(vendorAdapter());
em.setDataSource(getDataSource());
em.setPersistenceProviderClass(HibernatePersistenceProvider.class);
em.setPackagesToScan("edu.msudenver.tsp.persistence");
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public JpaTransactionManager jpaTransactionManager() {
final JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return jpaTransactionManager;
}
private HibernateJpaVendorAdapter vendorAdapter() {
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
return vendorAdapter;
}
@Bean(name = "dataSource")
public DataSource getDataSource(){
return DataSourceBuilder
.create()
.username(username)
.password(password)
.url(databaseUrl)
.driverClassName(driverClassName)
.build();
}
@Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(final DataSource dataSource) {
final LocalSessionFactoryBuilder sessionFactoryBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionFactoryBuilder.scanPackages("edu.msudenver.tsp.persistence.dto");
return sessionFactoryBuilder.buildSessionFactory();
}
@Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(final SessionFactory sessionFactory) {
return new HibernateTransactionManager(sessionFactory);
}
@Bean
public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {
final DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource);
return initializer;
}
Properties additionalProperties() {
final Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("hibernate.dialect", hibernateDialect);
properties.setProperty("spring.jpa.show-sql", showSql);
properties.setProperty("spring.datasource.tomcat.max-active", tomcatPoolMaxActive);
properties.setProperty("hibernate.id.new_generator_mappings","false");
return properties;
}
}
@@ -0,0 +1,181 @@
package edu.msudenver.tsp.persistence.controller;
import edu.msudenver.tsp.persistence.dto.AccountDto;
import edu.msudenver.tsp.persistence.repository.AccountsRepository;
import edu.msudenver.tsp.utilities.PersistenceUtilities;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StopWatch;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.groups.Default;
import java.util.List;
import java.util.Optional;
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/accounts")
public class AccountController {
private final AccountsRepository accountsRepository;
@GetMapping("/")
public @ResponseBody
ResponseEntity<Iterable<AccountDto>> getListOfAccounts() {
LOG.info("Received request to list all accounts");
LOG.debug("Querying for list of accounts");
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final List<AccountDto> listOfAccounts = (List<AccountDto>) accountsRepository.findAll();
stopWatch.stop();
LOG.debug("Successfully completed query. Query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
LOG.info("Returning list of all accounts with size of " + listOfAccounts.size());
return new ResponseEntity<>(listOfAccounts, HttpStatus.OK);
}
@GetMapping("/{id}")
public @ResponseBody
ResponseEntity<AccountDto> getAccountById(@PathVariable("id") final Integer id) {
LOG.info("Received request to query for account with id " + id);
if (id == null) {
LOG.error("ERROR: ID was null");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Querying for account with id " + id);
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final Optional<AccountDto> account = accountsRepository.findById(id);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
return account.map(accountDto -> {
LOG.info("Returning account with id " + id);
return new ResponseEntity<>(accountDto, HttpStatus.OK);
}).orElseGet(
() -> {
LOG.warn("No account was found with id " + id);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
);
}
@PostMapping("/")
@Validated({AccountDto.Insert.class, Default.class})
public @ResponseBody ResponseEntity<AccountDto> insertAccount(
@Valid @RequestBody final AccountDto accountDto, final BindingResult bindingResult) {
LOG.info("Received request to insert a new account");
if (bindingResult.hasErrors()) {
LOG.error("Binding result is unprocessable");
return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
}
if (accountDto == null) {
LOG.error("Passed account is unprocessable");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Saving new account");
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final AccountDto savedAccount = accountsRepository.save(accountDto);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
LOG.info("Returning the newly created account");
return new ResponseEntity<>(savedAccount, HttpStatus.CREATED);
}
@PatchMapping("/{id}")
public @ResponseBody ResponseEntity<AccountDto> updateAccount(
@PathVariable("id") final Integer id,
@RequestBody final AccountDto accountDto, final BindingResult bindingResult) {
LOG.info("Received request to update an account");
if (bindingResult.hasErrors()) {
LOG.error("Binding result is unprocessable");
return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
}
if (accountDto == null) {
LOG.error("Passed entity is null");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
if (id == null) {
LOG.error("Account ID must be specified");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Checking for existence of account with id " + id);
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final Optional<AccountDto> existingAccount = accountsRepository.findById(id);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
if (!existingAccount.isPresent()) {
LOG.error("No account associated with id " + id);
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
PersistenceUtilities.copyNonNullProperties(accountDto, existingAccount.get());
existingAccount.get().setVersion(existingAccount.get().getVersion()+ 1);
LOG.info("Updating account with id " + id);
LOG.debug("Querying for account with ID " + id);
stopWatch.start();
final AccountDto updatedAccount = accountsRepository.save(existingAccount.get());
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
return new ResponseEntity<>(updatedAccount, HttpStatus.OK);
}
@DeleteMapping("/{id}")
public @ResponseBody ResponseEntity<Void> deleteAccountById(@PathVariable("id") final Integer id) {
LOG.info("Received request to delete account with id " + id);
if (id == null) {
LOG.error("Specified Id is null");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Deleting account with id " + id);
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
accountsRepository.deleteById(id);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
@@ -0,0 +1,181 @@
package edu.msudenver.tsp.persistence.controller;
import edu.msudenver.tsp.persistence.dto.DefinitionDto;
import edu.msudenver.tsp.persistence.repository.DefinitionRepository;
import edu.msudenver.tsp.utilities.PersistenceUtilities;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StopWatch;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.groups.Default;
import java.util.List;
import java.util.Optional;
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping(path = "/definitions/")
public class DefinitionController {
private final DefinitionRepository definitionRepository;
@GetMapping("/")
public @ResponseBody
ResponseEntity<Iterable<DefinitionDto>> getAllDefinitions() {
LOG.info("Received request to list all definitions");
LOG.debug("Querying for list of all definitions");
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final List<DefinitionDto> listOfDefinitions = definitionRepository.findAll();
stopWatch.stop();
LOG.debug("Successfully completed query. Query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
LOG.info("Returning list of all definition with size " + listOfDefinitions.size());
return new ResponseEntity<>(listOfDefinitions, HttpStatus.OK);
}
@GetMapping("/{id}")
public @ResponseBody
ResponseEntity<DefinitionDto> getDefinitionById(@PathVariable("id") final Integer id) {
LOG.info("Received request to query for definition with id " + id);
if (id == null) {
LOG.error("ERROR: ID was null");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Querying for definition with id " + id);
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final Optional<DefinitionDto> definition = definitionRepository.findById(id);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
return definition.map(definitionDto -> {
LOG.info("Returning definition with id " + id);
return new ResponseEntity<>(definitionDto, HttpStatus.OK);
}).orElseGet(
() -> {
LOG.warn("No definition was found with id " + id);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
});
}
@PostMapping("/")
@Validated({DefinitionDto.Insert.class, Default.class})
public @ResponseBody ResponseEntity<DefinitionDto> insertDefinition(
@Valid @RequestBody final DefinitionDto definitionDto,
final BindingResult bindingResult) {
LOG.info("Received request to insert a new definition");
if (bindingResult.hasErrors()) {
LOG.error("Binding result is unprocessable");
return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
}
if (definitionDto == null) {
LOG.error("Passed entity is unprocessable");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Saving new definition");
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final DefinitionDto savedDefinition = definitionRepository.save(definitionDto);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
LOG.info("Returning the newly created definition with id " + savedDefinition.getId());
return new ResponseEntity<>(savedDefinition, HttpStatus.CREATED);
}
@PatchMapping("/{id}")
public @ResponseBody ResponseEntity<DefinitionDto> updateDefinition(
@PathVariable("id") final Integer id,
@RequestBody final DefinitionDto definitionDto, final BindingResult bindingResult) {
LOG.info("Received request to update an account");
if (bindingResult.hasErrors()) {
LOG.error("Binding result is unprocessable");
return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
}
if (definitionDto == null) {
LOG.error("Passed entity is null");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
if (id == null) {
LOG.error("Definition ID must be specified");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Checking for existence of definition with id " + id);
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final Optional<DefinitionDto> existingDefinition = definitionRepository.findById(id);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
if (!existingDefinition.isPresent()) {
LOG.error("No definition associated with id " + id);
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
PersistenceUtilities.copyNonNullProperties(definitionDto, existingDefinition.get());
existingDefinition.get().setVersion(existingDefinition.get().getVersion()+ 1);
LOG.info("Updating definition with id " + id);
LOG.debug("Querying for definition with ID " + id);
stopWatch.start();
final DefinitionDto updatedDefinition = definitionRepository.save(existingDefinition.get());
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
return new ResponseEntity<>(updatedDefinition, HttpStatus.OK);
}
@DeleteMapping("/{id}")
public @ResponseBody ResponseEntity<Void> deleteDefinitionById(@PathVariable("id") final Integer id) {
LOG.info("Received request to delete definition with id " + id);
if (id == null) {
LOG.error("Specified id is null");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Deleting definition with id " + id);
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
definitionRepository.deleteById(id);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
@@ -0,0 +1,11 @@
package edu.msudenver.tsp.persistence.controller;
import edu.msudenver.tsp.persistence.repository.NotationRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@AllArgsConstructor
public class NotationController {
final private NotationRepository notationRepository;
}
@@ -0,0 +1,11 @@
package edu.msudenver.tsp.persistence.controller;
import edu.msudenver.tsp.persistence.repository.ProofRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@AllArgsConstructor
public class ProofController {
final private ProofRepository proofRepository;
}
@@ -0,0 +1,11 @@
package edu.msudenver.tsp.persistence.controller;
import edu.msudenver.tsp.persistence.repository.TheoremRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@AllArgsConstructor
public class TheoremController {
final private TheoremRepository theoremRepository;
}
@@ -0,0 +1,31 @@
package edu.msudenver.tsp.persistence.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.Date;
@Entity(name = "accounts")
@EntityListeners(AuditingEntityListener.class)
@Data
@EqualsAndHashCode(callSuper = true)
public class AccountDto extends BaseDto implements Serializable {
@NotBlank(groups = Insert.class, message = "A username must be specified") @Size(max = 50) private String username;
@NotBlank(groups = Insert.class, message = "A password must be specified") @Size(max = 256) private String password;
@NotNull @JsonProperty("administrator_status") private boolean administratorStatus;
@Temporal(TemporalType.DATE) @JsonProperty("last_login") private Date lastLogin;
public static final long serialVersionUID = 7095627971593953734L;
public interface Insert {}
}
@@ -0,0 +1,40 @@
package edu.msudenver.tsp.persistence.dto;
import com.vladmihalcea.hibernate.type.array.IntArrayType;
import com.vladmihalcea.hibernate.type.array.StringArrayType;
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import com.vladmihalcea.hibernate.type.json.JsonNodeBinaryType;
import com.vladmihalcea.hibernate.type.json.JsonNodeStringType;
import com.vladmihalcea.hibernate.type.json.JsonStringType;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;
import javax.persistence.*;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@MappedSuperclass
@TypeDefs({
@TypeDef(name = "string-array", typeClass = StringArrayType.class),
@TypeDef(name = "int-array", typeClass = IntArrayType.class),
@TypeDef(name = "json", typeClass = JsonStringType.class),
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class),
@TypeDef(name = "jsonb-node", typeClass = JsonNodeBinaryType.class),
@TypeDef(name = "json-node", typeClass = JsonNodeStringType.class),
})
public class BaseDto implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Version
private Integer version;
public static final long serialVersionUID = -1686252381978213945L;
}
@@ -0,0 +1,17 @@
package edu.msudenver.tsp.persistence.dto;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
import java.util.List;
@Getter
@Setter
@ToString
public class Definition implements Serializable {
private List<String> definitions;
public static final long serialVersionUID = -2208496232532214840L;
}
@@ -0,0 +1,34 @@
package edu.msudenver.tsp.persistence.dto;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.Serializable;
@Entity(name = "definitions")
@Table(name = "definitions")
@EntityListeners(AuditingEntityListener.class)
@Data
@EqualsAndHashCode(callSuper = true)
public class DefinitionDto extends BaseDto implements Serializable {
@NotBlank(groups = Insert.class, message = "A name must be specified")
@Size(min = 1, max = 200, message = "Must be between 1 and 200 characters")
private String name;
@NotBlank(groups = Insert.class, message = "At least one (1) definition must be specified")
@Type(type = "json") @Column(columnDefinition = "jsonb") private Definition definition;
@Type(type = "json") @Column(columnDefinition = "jsonb") private Notation notation;
public static final long serialVersionUID = -5314619286352932857L;
public interface Insert {}
}
@@ -0,0 +1,16 @@
package edu.msudenver.tsp.persistence.dto;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
import java.util.List;
@Getter
@Setter
@ToString
public class Notation implements Serializable {
private List<String> notations;
public static final long serialVersionUID = 2301438318932336121L;
}
@@ -0,0 +1,9 @@
package edu.msudenver.tsp.persistence.repository;
import edu.msudenver.tsp.persistence.dto.AccountDto;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AccountsRepository extends CrudRepository<AccountDto, Integer> {
}
@@ -0,0 +1,11 @@
package edu.msudenver.tsp.persistence.repository;
import edu.msudenver.tsp.persistence.dto.DefinitionDto;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface DefinitionRepository extends JpaRepository<DefinitionDto, Integer> {
}
@@ -0,0 +1,7 @@
package edu.msudenver.tsp.persistence.repository;
import edu.msudenver.tsp.persistence.dto.BaseDto;
import org.springframework.data.repository.CrudRepository;
public interface NotationRepository extends CrudRepository<BaseDto, Long> {
}
@@ -0,0 +1,7 @@
package edu.msudenver.tsp.persistence.repository;
import edu.msudenver.tsp.persistence.dto.BaseDto;
import org.springframework.data.repository.CrudRepository;
public interface ProofRepository extends CrudRepository<BaseDto, Long> {
}
@@ -0,0 +1,7 @@
package edu.msudenver.tsp.persistence.repository;
import edu.msudenver.tsp.persistence.dto.BaseDto;
import org.springframework.data.repository.CrudRepository;
public interface TheoremRepository extends CrudRepository<BaseDto, Long> {
}
@@ -0,0 +1,13 @@
spring.jpa.hibernate.ddl-auto = none
spring.jpa.database=mysql
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/pandamonium?autoReconnect=true&useSSL=false
spring.datasource.username=panda
spring.datasource.password=secret
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect
spring.jpa.show-sql = true
spring.datasource.tomcat.test-while-idle=true
spring.datasource.tomcat.validation-query=SELECT 1
logging.level.org.springframework.web=DEBUG
spring.datasource.tomcat.max-active=5
server.port=8090
@@ -0,0 +1,224 @@
package edu.msudenver.tsp.persistence.controller;
import edu.msudenver.tsp.persistence.dto.AccountDto;
import edu.msudenver.tsp.persistence.repository.AccountsRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
@WebMvcTest(controllers = AccountController.class)
public class AccountControllerTest {
@Mock
private AccountsRepository accountsRepository;
@InjectMocks
private AccountController accountController;
@Mock private BindingResult bindingResult;
@Test
public void testGetAllAccounts() {
final AccountDto accountDto = createAccount();
final List<AccountDto> accountDtoList = new ArrayList<>();
accountDtoList.add(accountDto);
accountDtoList.add(accountDto);
when(accountsRepository.findAll()).thenReturn(accountDtoList);
final ResponseEntity<Iterable<AccountDto>> responseEntity = accountController.getListOfAccounts();
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertTrue(responseEntity.hasBody());
assertNotNull(responseEntity.getBody());
responseEntity.getBody().forEach(account -> assertEquals(account, accountDto));
}
@Test
public void testGetAccountById() {
final AccountDto accountDto = createAccount();
when(accountsRepository.findById(anyInt())).thenReturn(Optional.ofNullable(accountDto));
final ResponseEntity<AccountDto> responseEntity = accountController.getAccountById(1);
assertNotNull(responseEntity);
assertTrue(responseEntity.hasBody());
assertNotNull(responseEntity.getBody());
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertEquals(accountDto, responseEntity.getBody());
verify(accountsRepository).findById(anyInt());
}
@Test
public void testGetAccountById_nullId() {
final ResponseEntity responseEntity = accountController.getAccountById(null);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verifyZeroInteractions(accountsRepository);
}
@Test
public void testGetAccountById_noAccountFound() {
when(accountsRepository.findById(anyInt())).thenReturn(Optional.empty());
final ResponseEntity responseEntity = accountController.getAccountById(1);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());
verify(accountsRepository).findById(anyInt());
}
@Test
public void testInsertAccount() {
final AccountDto accountDto = createAccount();
when(accountsRepository.save(any(AccountDto.class))).thenReturn(accountDto);
final ResponseEntity<AccountDto> responseEntity = accountController.insertAccount(accountDto, bindingResult);
assertNotNull(responseEntity);
assertTrue(responseEntity.hasBody());
assertNotNull(responseEntity.getBody());
assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
assertEquals(accountDto, responseEntity.getBody());
verify(accountsRepository).save(any(AccountDto.class));
}
@Test
public void testInsertAccount_accountsDtoIsNull() {
final ResponseEntity responseEntity = accountController.insertAccount(null, bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verifyZeroInteractions(accountsRepository);
}
@Test
public void testInsertAccount_bindingResultHasErrors() {
final AccountDto definitionDto = createAccount();
when(bindingResult.hasErrors()).thenReturn(true);
final ResponseEntity responseEntity = accountController.insertAccount(definitionDto, bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.UNPROCESSABLE_ENTITY, responseEntity.getStatusCode());
verifyZeroInteractions(accountsRepository);
}
@Test
public void testUpdateAccount() {
final AccountDto existingAccount = createAccount();
existingAccount.setId(1);
existingAccount.setVersion(1);
final AccountDto accountUpdate = new AccountDto();
accountUpdate.setUsername("Test Update");
final AccountDto updatedAccount = existingAccount;
updatedAccount.setUsername("Test Update");
when(accountsRepository.findById(anyInt())).thenReturn(Optional.of(existingAccount));
when(accountsRepository.save(any(AccountDto.class))).thenReturn(updatedAccount);
final ResponseEntity<AccountDto> responseEntity = accountController.updateAccount(1, accountUpdate, bindingResult);
assertNotNull(responseEntity);
assertTrue(responseEntity.hasBody());
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertEquals(updatedAccount, responseEntity.getBody());
verify(accountsRepository).findById(anyInt());
verify(accountsRepository).save(any(AccountDto.class));
}
@Test
public void testUpdateAccount_bindingResultHasErrors() {
when(bindingResult.hasErrors()).thenReturn(true);
final ResponseEntity<AccountDto> responseEntity = accountController.updateAccount(1, createAccount(), bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.UNPROCESSABLE_ENTITY, responseEntity.getStatusCode());
verifyZeroInteractions(accountsRepository);
}
@Test
public void testUpdateAccount_accountsDtoIsNull() {
final ResponseEntity<AccountDto> responseEntity = accountController.updateAccount(1, null, bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verifyZeroInteractions(accountsRepository);
}
@Test
public void testUpdateAccount_idIsNull() {
final ResponseEntity<AccountDto> responseEntity = accountController.updateAccount(null, createAccount(), bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verifyZeroInteractions(accountsRepository);
}
@Test
public void testUpdateAccount_accountDoesNotExist() {
when(accountsRepository.findById(anyInt())).thenReturn(Optional.empty());
final ResponseEntity<AccountDto> responseEntity = accountController.updateAccount(1, createAccount(), bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verify(accountsRepository, times(0)).save(any(AccountDto.class));
}
@Test
public void testDeleteAccountById() {
doNothing().when(accountsRepository).deleteById(anyInt());
final ResponseEntity responseEntity = accountController.deleteAccountById(1);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.NO_CONTENT, responseEntity.getStatusCode());
verify(accountsRepository).deleteById(anyInt());
}
@Test
public void testDeleteAccountById_idIsNull() {
final ResponseEntity responseEntity = accountController.deleteAccountById(null);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verifyZeroInteractions(accountsRepository);
}
private AccountDto createAccount() {
final AccountDto accountDto = new AccountDto();
accountDto.setUsername("Test username");
accountDto.setPassword("test password");
accountDto.setAdministratorStatus(true);
return accountDto;
}
}
@@ -0,0 +1,235 @@
package edu.msudenver.tsp.persistence.controller;
import edu.msudenver.tsp.persistence.dto.Definition;
import edu.msudenver.tsp.persistence.dto.DefinitionDto;
import edu.msudenver.tsp.persistence.dto.Notation;
import edu.msudenver.tsp.persistence.repository.DefinitionRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.*;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
@WebMvcTest(controllers = DefinitionController.class)
public class DefinitionControllerTest {
@Mock private DefinitionRepository definitionRepository;
@InjectMocks private DefinitionController definitionController;
@Mock private BindingResult bindingResult;
@Test
public void testGetAllDefinitions() {
final DefinitionDto definitionDto = createDefinition();
final List<DefinitionDto> definitionDtoList = new ArrayList<>();
definitionDtoList.add(definitionDto);
definitionDtoList.add(definitionDto);
when(definitionRepository.findAll()).thenReturn(definitionDtoList);
final ResponseEntity<Iterable<DefinitionDto>> responseEntity = definitionController.getAllDefinitions();
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertTrue(responseEntity.hasBody());
assertNotNull(responseEntity.getBody());
responseEntity.getBody().forEach(definition -> assertEquals(definition, definitionDto));
}
@Test
public void testGetDefinitionsById() {
final DefinitionDto definitionDto = createDefinition();
when(definitionRepository.findById(anyInt())).thenReturn(Optional.ofNullable(definitionDto));
final ResponseEntity<DefinitionDto> responseEntity = definitionController.getDefinitionById(1);
assertNotNull(responseEntity);
assertTrue(responseEntity.hasBody());
assertNotNull(responseEntity.getBody());
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertEquals(definitionDto, responseEntity.getBody());
verify(definitionRepository).findById(anyInt());
}
@Test
public void testGetDefinitionById_nullId() {
final ResponseEntity responseEntity = definitionController.getDefinitionById(null);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verifyZeroInteractions(definitionRepository);
}
@Test
public void testGetDefinitionById_noDefinitionFound() {
when(definitionRepository.findById(anyInt())).thenReturn(Optional.empty());
final ResponseEntity responseEntity = definitionController.getDefinitionById(1);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());
verify(definitionRepository).findById(anyInt());
}
@Test
public void testInsertDefinition() {
final DefinitionDto definitionDto = createDefinition();
when(definitionRepository.save(any(DefinitionDto.class))).thenReturn(definitionDto);
final ResponseEntity<DefinitionDto> responseEntity = definitionController.insertDefinition(definitionDto, bindingResult);
assertNotNull(responseEntity);
assertTrue(responseEntity.hasBody());
assertNotNull(responseEntity.getBody());
assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
assertEquals(definitionDto, responseEntity.getBody());
verify(definitionRepository).save(any(DefinitionDto.class));
}
@Test
public void testInsertDefinition_definitionDtoIsNull() {
final ResponseEntity responseEntity = definitionController.insertDefinition(null, bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verifyZeroInteractions(definitionRepository);
}
@Test
public void testInsertDefinition_bindingResultHasErrors() {
final DefinitionDto definitionDto = createDefinition();
when(bindingResult.hasErrors()).thenReturn(true);
final ResponseEntity responseEntity = definitionController.insertDefinition(definitionDto, bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.UNPROCESSABLE_ENTITY, responseEntity.getStatusCode());
verifyZeroInteractions(definitionRepository);
}
@Test
public void testUpdateDefinition() {
final DefinitionDto existingDefinition = createDefinition();
existingDefinition.setId(1);
existingDefinition.setVersion(1);
final DefinitionDto definitionUpdate = new DefinitionDto();
definitionUpdate.setName("Test Update");
final DefinitionDto updatedDefinition = existingDefinition;
updatedDefinition.setName("Test Update");
when(definitionRepository.findById(anyInt())).thenReturn(Optional.of(existingDefinition));
when(definitionRepository.save(any(DefinitionDto.class))).thenReturn(updatedDefinition);
final ResponseEntity<DefinitionDto> responseEntity = definitionController.updateDefinition(1, definitionUpdate, bindingResult);
assertNotNull(responseEntity);
assertTrue(responseEntity.hasBody());
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertEquals(updatedDefinition, responseEntity.getBody());
verify(definitionRepository).findById(anyInt());
verify(definitionRepository).save(any(DefinitionDto.class));
}
@Test
public void testUpdateDefinition_bindingResultErrors() {
when(bindingResult.hasErrors()).thenReturn(true);
final ResponseEntity<DefinitionDto> responseEntity = definitionController.updateDefinition(1, createDefinition(), bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.UNPROCESSABLE_ENTITY, responseEntity.getStatusCode());
verifyZeroInteractions(definitionRepository);
}
@Test
public void testUpdateDefinition_definitionDtoIsNull() {
final ResponseEntity<DefinitionDto> responseEntity = definitionController.updateDefinition(1, null, bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verifyZeroInteractions(definitionRepository);
}
@Test
public void testUpdateDefinition_idIsNull() {
final ResponseEntity<DefinitionDto> responseEntity = definitionController.updateDefinition(null, createDefinition(), bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verifyZeroInteractions(definitionRepository);
}
@Test
public void testUpdateDefinition_definitionDoesntExist() {
when(definitionRepository.findById(anyInt())).thenReturn(Optional.empty());
final ResponseEntity<DefinitionDto> responseEntity = definitionController.updateDefinition(1, createDefinition(), bindingResult);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verify(definitionRepository, times(0)).save(any(DefinitionDto.class));
}
@Test
public void testDeleteDefinitionById() {
doNothing().when(definitionRepository).deleteById(anyInt());
final ResponseEntity responseEntity = definitionController.deleteDefinitionById(1);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.NO_CONTENT, responseEntity.getStatusCode());
verify(definitionRepository).deleteById(anyInt());
}
@Test
public void testDeleteDefinitionById_nullId() {
final ResponseEntity responseEntity = definitionController.deleteDefinitionById(null);
assertNotNull(responseEntity);
assertFalse(responseEntity.hasBody());
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
verifyZeroInteractions(definitionRepository);
}
private DefinitionDto createDefinition() {
final List<String> definitionList = new ArrayList<>();
definitionList.add("Test definition 1");
final Definition definition = new Definition();
definition.setDefinitions(definitionList);
final List<String> notationList = new ArrayList<>();
notationList.add("\\testLaTeX");
final Notation notation = new Notation();
notation.setNotations(notationList);
final DefinitionDto definitionDto = new DefinitionDto();
definitionDto.setName("Test Name");
definitionDto.setDefinition(definition);
definitionDto.setNotation(notation);
return definitionDto;
}
}
@@ -7,6 +7,12 @@ version '1.0'
sourceCompatibility = 1.8
sonarqube {
properties {
property "sonar.projectName", 'Theorem Prover Services'
}
}
repositories {
mavenCentral()
}
@@ -0,0 +1,43 @@
package edu.msudenver.tsp.services.parser;
import lombok.Getter;
import lombok.Setter;
public class Node
{
@Getter private final String statement;
@Getter @Setter private Node left;
@Getter @Setter private Node right;
@Getter @Setter private Node center;
@Getter private final Node parent;
@Getter private final int depth;
public Node(final String statement, final Node parent)
{
this.statement = statement + "\n";
left = null;
right = null;
center = null;
this.parent = parent;
if(parent != null)
{
depth = parent.depth + 1;
}
else
{
depth = 0;
}
}
@Override
public String toString()
{
String returnVal = this.depth + ": " + this.statement;
if(this.left != null) returnVal += "... " + this.left.toString();
if(this.center != null) returnVal += "... " + this.center.toString();
if(this.right != null) returnVal += "... " + this.right.toString();
return returnVal;
}
}
@@ -0,0 +1,143 @@
package edu.msudenver.tsp.services.parser;
import edu.msudenver.tsp.persistence.controller.DefinitionController;
import edu.msudenver.tsp.persistence.controller.NotationController;
import edu.msudenver.tsp.persistence.controller.ProofController;
import edu.msudenver.tsp.persistence.controller.TheoremController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
class ParserService {
private final DefinitionController definitionController;
private final TheoremController theoremController;
private final NotationController notationController;
private final ProofController proofController;
private Node root;
@Autowired
public ParserService(final DefinitionController definitionController, final TheoremController theoremController,
final NotationController notationController, final ProofController proofController) {
this.definitionController = definitionController;
this.theoremController = theoremController;
this.notationController = notationController;
this.proofController = proofController;
}
public boolean parseUserInput(final String userInput)
{
try {
final Node tree = parseRawInput(userInput);
final List<String> statements = retrieveStatements(tree);
return true;
} catch(final Exception e) {
e.printStackTrace();
}
return false;
}
public Node parseRawInput(String input)
{
input = input.toLowerCase();
root = new Node(input, null);
if(input.equals(""))
{
return root;
}
recurse(root);
return root;
}
private void recurse(final Node current)
{
int startIndex;
int endIndex;
final String statement;
if (current != null) {
statement = current.getStatement();
} else {
return;
}
String nextStatement;
if(statement.contains("let"))
{
current.setLeft(new Node("let", current));
startIndex = statement.indexOf("let")+"let".length();
if(statement.contains("if")){
endIndex = statement.indexOf("if");
} else if(statement.contains("then")){
endIndex = statement.indexOf("then");
} else {
endIndex = statement.length();
}
nextStatement = statement.substring(startIndex, endIndex);
current.getLeft().setCenter(new Node(nextStatement, current.getLeft()));
recurse(current.getLeft().getCenter());
}
if(statement.contains("if"))
{
current.setCenter(new Node("if", current));
startIndex = statement.indexOf("if")+"if".length();
endIndex = (statement.contains("then") ? statement.indexOf("then") : statement.length());
nextStatement = statement.substring(startIndex, endIndex);
current.getCenter().setCenter(new Node(nextStatement, current.getCenter()));
recurse(current.getCenter().getCenter());
}
if(current.getStatement().contains("then"))
{
current.setRight(new Node("then", current));
startIndex = statement.indexOf("then")+"then".length();
nextStatement = statement.substring(startIndex);
current.getRight().setCenter(new Node(nextStatement, current.getRight()));
recurse(current.getRight().getCenter());
}
}
public List<String> retrieveStatements(final Node parsedTree)
{
return populateStatementList(parsedTree, new ArrayList<>());
}
private ArrayList<String> populateStatementList(final Node node, final ArrayList<String> statementList)
{
if(node == null)
{
return statementList;
}
final String statement = node.getStatement().trim();
if(!(statement.contains("let") || statement.contains("if") || statement.contains("then")))
{
statementList.add(statement);
}
populateStatementList(node.getLeft(), statementList);
populateStatementList(node.getCenter(), statementList);
populateStatementList(node.getRight(), statementList);
return statementList;
}
}
@@ -0,0 +1,143 @@
package edu.msudenver.tsp.services.parser;
import edu.msudenver.tsp.persistence.controller.DefinitionController;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class ParserServiceTest {
private final DefinitionController definitionControllerMock = mock(DefinitionController.class);
private final ParserService mockParserService = mock(ParserService.class);
@InjectMocks
private final ParserService parserService = new ParserService(definitionControllerMock, null,
null, null);
@Test
public void testEmptyStringEqualsEmptyString() {
final String expected = "0: \n";
final String actual = parserService.parseRawInput("").toString();
assertEquals(expected, actual);
}
@Test
public void testUselessStringEqualsUselessString() {
final String expected = "0: cat\n";
final String actual = parserService.parseRawInput("cat").toString();
assertEquals(expected, actual);
}
@Test
public void testSingleIfReturnsIfPlusEmptyString() {
final String expected = "0: if\n... 1: if\n... 2: \n\n";
final String actual = parserService.parseRawInput("if").toString();
assertEquals(expected, actual);
}
@Test
public void testBaseCaseIfXIsEvenThenXSquaredIsEven() {
final String expected = "0: if x is even then x^2 is even\n" +
"... 1: if\n" +
"... 2: x is even \n" +
"... 1: then\n" +
"... 2: x^2 is even\n\n";
final String actual = parserService.parseRawInput("if x is even then x^2 is even").toString();
assertEquals(expected, actual);
}
@Test
public void testLetXBeEvenThenXSquaredIsEven() {
final String expected = "0: let x be even. then x^2 is even.\n" +
"... 1: let\n" +
"... 2: x be even. \n" +
"... 1: then\n" +
"... 2: x^2 is even.\n\n";
final String actual = parserService.parseRawInput("Let x be even. Then x^2 is even.").toString();
assertEquals(expected, actual);
}
@Test
public void testLetIfThen() {
final String expected = "0: let a. if b, then c.\n" +
"... 1: let\n" +
"... 2: a. \n" +
"... 1: if\n" +
"... 2: b, \n" +
"... 1: then\n" +
"... 2: c.\n\n";
final String actual = parserService.parseRawInput("Let a. If b, then c.").toString();
assertEquals(expected, actual);
}
@Test
public void testLetStatementWithoutAnyIfOrThenStatements() {
final String expected = "0: let a be equal to b.\n" +
"... 1: let\n" +
"... 2: a be equal to b.\n\n";
final String actual = parserService.parseRawInput("Let a be equal to b.").toString();
assertEquals(expected, actual);
}
@Test
public void testEmptyStringReturnsEmptyList() {
final List<String> expectedList = new ArrayList<>();
expectedList.add("");
when(mockParserService.parseRawInput(anyString())).thenReturn(new Node("", null));
final List<String> actualList = parserService.retrieveStatements(mockParserService.parseRawInput(""));
assertEquals(expectedList, actualList);
}
@Test
public void testBaseCaseReturnsXIsEven() {
final List<String> expectedList = new ArrayList<>();
expectedList.add("x is even");
expectedList.add("x^2 is even");
final Node testNode = new Node("if x is even then x^2 is even", null);
testNode.setCenter(new Node("if", testNode));
testNode.getCenter().setCenter(new Node(" x is even ", testNode.getCenter()));
testNode.setRight(new Node("then", testNode));
testNode.getRight().setCenter(new Node(" x^2 is even", testNode.getRight()));
when(mockParserService.parseRawInput(anyString())).thenReturn(testNode);
final List<String> actualList = parserService.retrieveStatements(mockParserService.parseRawInput("baseCase"));
assertEquals(expectedList, actualList);
}
@Test
public void testDriveParseUserInput() {
final Node testNode = new Node("", null);
when(mockParserService.parseRawInput(anyString())).thenReturn(testNode);
when(mockParserService.retrieveStatements(testNode)).thenReturn(new ArrayList<>());
final boolean successfulTestDrive = parserService.parseUserInput("");
assertTrue(successfulTestDrive);
}
}
+58
View File
@@ -0,0 +1,58 @@
## PTP Persistence API
The PTP Persistence API is the web API for accessing the theorems database.
<http://localhost:8080/>
## Running from IntelliJ
* Create a new run configuration in IntelliJ.
```
Name: "Pandamonium Theorem Prover Tomcat"
Application Server: Tomcat (8.5.12)
HTTP Port: 8080
JMX Port: 1080
Deployment tabe: Deploy pandamonium-theorem-prover.war (exploded)
```
## Running the Tests
This project is unit tested with JUnit and Mockito. You can run the unit tests with IntelliJ or Gradle. To run them with IntelliJ, browse to any `*Test.java` file and use IntelliJ's built-in test runner to run or debug the test. To run all the unit tests with Gradle:
* On a Linux or Macintosh machine:
```$ ./gradlew test```
* On a Windows machine:
```$ gradlew.bat test```
You can also test modules individually:
* On a Linux or Macintosh machine:
```$ ./gradlew persistence:test```
* On a Windows machine:
```$ gradlew.bat persistence:test```
## Integration Tests
To run the integration tests with IntelliJ, browse to any `*Test.java` file residing in any module name `integrationTest` and use IntelliJ's built-in test runner to run or debug the test. To run all the integration tests with Gradle:
* On a Linux or Macintosh machine:
```$ ./gradlew integrationTest```
* On a Windows machine
```$ gradlew.bat integrationTest```
## Built with
* [Spring Boot](https://projects.spring.io/spring-boot/) - Web framework
* [Gradle](https://gradle.org/) - Dependency management
* [JUnit](http://junit.org/junit4/) - Unit tests
* [Mockito](http://site.mockito.org/) - Mock objects library
* [Lombok](https://projectlombok.org/) - Boilerplate Code Generator
+1
View File
@@ -0,0 +1 @@
integration.test.base.url=http://localhost:
@@ -7,11 +7,18 @@ version '1.0'
sourceCompatibility = 1.8
sonarqube {
properties {
property "sonar.projectName", 'Parsing and Proofs Utilities'
}
}
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile fileTree(dir: 'lib', include: '**/*.jar')
testCompile group: 'junit', name: 'junit', version: '4.12'
}
@@ -0,0 +1,27 @@
package edu.msudenver.tsp.utilities;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import java.beans.FeatureDescriptor;
import java.util.stream.Stream;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class PersistenceUtilities {
private static String[] getNullPropertyNames(final Object source) {
final BeanWrapper wrappedSource = new BeanWrapperImpl(source);
return Stream.of(wrappedSource.getPropertyDescriptors())
.map(FeatureDescriptor::getName)
.filter(propertyName -> wrappedSource.getPropertyValue(propertyName) == null
|| propertyName.equals("id"))
.toArray(String[]::new);
}
public static void copyNonNullProperties(final Object source, final Object target) {
BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
}
}